diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4754115..261dd114 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,68 +12,68 @@ defaults: shell: bash jobs: -# build: -# name: ${{ matrix.task.name}} - ${{ matrix.os.name }} ${{ matrix.python.name }} -# runs-on: ${{ matrix.os.runs-on }} -# strategy: -# fail-fast: false -# matrix: -# os: -# - name: Linux -# runs-on: ubuntu-latest -# python: -# - name: CPython 3.8 -# tox: py38 -# action: 3.8 -# task: -# - name: Build -# tox: build -# -# steps: -# - uses: actions/checkout@v2 -# with: -# ref: ${{ github.event.pull_request.head.sha }} -# - name: Set up ${{ matrix.python.name }} -# uses: actions/setup-python@v2 -# with: -# python-version: ${{ matrix.python.action }} -# -# - name: Install dependencies -# run: | -# python -m pip install --upgrade pip setuptools wheel -# python -m pip install build check-manifest twine -# -# - uses: twisted/python-info-action@v1 -# -# - name: Build -# run: | -# check-manifest --verbose . -# -# python -m build --sdist --outdir dist/ . -# -# mkdir empty/ -# cd empty -# -# tar -xvf ../dist/* -# cd * -# -# # build the wheel from the sdist -# python -m build --wheel --outdir ../../dist/ . -# cd ../../ -# -# twine check dist/* -# -# - name: Publish -# uses: actions/upload-artifact@v2 -# with: -# name: dist -# path: dist/ + build: + name: ${{ matrix.task.name}} - ${{ matrix.os.name }} ${{ matrix.python.name }} + runs-on: ${{ matrix.os.runs-on }} + strategy: + fail-fast: false + matrix: + os: + - name: Linux + runs-on: ubuntu-latest + python: + - name: CPython 3.8 + tox: py38 + action: 3.8 + task: + - name: Build + tox: build + + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Set up ${{ matrix.python.name }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python.action }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + python -m pip install build check-manifest twine + + - uses: twisted/python-info-action@v1 + + - name: Build + run: | + check-manifest --verbose . + + python -m build --sdist --outdir dist/ . + + mkdir empty/ + cd empty + + tar -xvf ../dist/* + cd * + + # build the wheel from the sdist + python -m build --wheel --outdir ../../dist/ . + cd ../../ + + twine check dist/* + + - name: Publish + uses: actions/upload-artifact@v2 + with: + name: dist + path: dist/ test: name: ${{ matrix.task.name}} - ${{ matrix.os.name }} ${{ matrix.python.name }} runs-on: ${{ matrix.os.runs-on }} -# needs: -# - build + needs: + - build strategy: fail-fast: false matrix: @@ -111,11 +111,11 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} -# - name: Download package files -# uses: actions/download-artifact@v2 -# with: -# name: dist -# path: dist/ + - name: Download package files + uses: actions/download-artifact@v2 + with: + name: dist + path: dist/ - name: Set up ${{ matrix.python.name }} uses: actions/setup-python@v2 @@ -129,11 +129,7 @@ jobs: - name: Prepare tox environment run: | - tox --notest - -# - name: Prepare tox environment -# run: | -# tox --notest --installpkg dist/*.whl + tox --notest --installpkg dist/*.whl - name: Runner info uses: twisted/python-info-action@v1 @@ -151,7 +147,7 @@ jobs: name: All runs-on: ubuntu-latest needs: -# - build + - build - test steps: - name: This diff --git a/.gitignore b/.gitignore index bee8a64b..82adb58b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__ +venv diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..169df8c4 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,7 @@ +include CHANGELOG.md +include LICENSE +include README.md +include *.md +include VERSION +include tox.ini +recursive-include src *.py diff --git a/README.md b/README.md index e0a033e7..0ef599e4 100644 --- a/README.md +++ b/README.md @@ -166,15 +166,25 @@ mode or the command line mode. There are many bugs and TODOs. +Plotman will always look in the current directory for the `config.yaml` file +([see also](https://github.com/ericaltendorf/plotman/pull/61#issuecomment-812967363)). + ## Installation -This program requires `psutil`, `pyfakefs`, `pyyaml` and `texttable`. +Installation for Linux: -Installation for Ubuntu 20.04: +1. Plotman assumes that a functioning [Chia](https://github.com/Chia-Network/chia-blockchain) + installation is present on the system. Activate your `chia` environment by typing + `source /path/to/your/chia/install/activate`. +2. Then, install Plotman using the following command: -``` -# Install Python package system -sudo apt-get install python3-pip + pip install git+https://github.com/ericaltendorf/plotman@development +3. Plotman will look for `config.yaml` in your current working directory when you run it. + You can find [an example configuration file](./config.yaml) in the project source that can be used + as a starting point. +5. That's it! You can now run Plotman by typing `plotman version` to verify its version. + Run `plotman --help` to learn about the available commands. -python3 -m pip install psutil pyfakefs pyyaml texttable -``` +### Development note: + +If you are forking Plotman, simply replace the installation step with `pip install --editable .[dev]` from the project root directory to install *your* version of plotman with test and development extras. diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..17e51c38 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.1.1 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..9787c3bd --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..5499cdd4 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,61 @@ +[metadata] +name = plotman +version = file: VERSION +author = Eric Altendorf +home-page = https://github.com/ericaltendorf/plotman +description = Chia plotting manager +long-description = file: README.md +long_description_content_type = text/markdown +license = Apache 2.0 +license-file = LICENSE +keywords = chia, blockchain, automation, process management +classifiers = + Development Status :: 3 - Alpha + Environment :: Console :: Curses + Intended Audience :: Developers + Intended Audience :: System Administrators + Intended Audience :: Information Technology + License :: OSI Approved :: Apache Software License + Natural Language :: English + Operating System :: POSIX + Programming Language :: Python :: 3 + Topic :: System :: Monitoring + Topic :: System :: Systems Administration + Topic :: Utilities +project_urls = + Bug Tracker = https://github.com/ericaltendorf/plotman/issues + Changelog = https://github.com/ericaltendorf/plotman/blob/main/CHANGELOG.md + +[options] +package_dir= + =src +packages=find: +install_requires = + psutil + pyyaml + texttable + +[options.packages.find] +where=src + +[options.entry_points] +console_scripts = + plotman = plotman.plotman:main + +[options.extras_require] +dev = + %(test)s + isort +test = + pytest + pyfakefs + +[options.data_files] +config = config.yaml +bin = util/listlogs + +[isort] +multi_line_output=3 +include_trailing_comma=True +force_grid_wrap=0 +line_length=88 diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..056ba45d --- /dev/null +++ b/setup.py @@ -0,0 +1,4 @@ +import setuptools + + +setuptools.setup() diff --git a/src/plotman/__init__.py b/src/plotman/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/plotman/__main__.py b/src/plotman/__main__.py new file mode 100644 index 00000000..c6f25c3f --- /dev/null +++ b/src/plotman/__main__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +from plotman import plotman + + +"""Plotman module launcher. +This is a shim that allows you to run plotman via + python3 -m plotman +""" +plotman.main() diff --git a/archive_test.py b/src/plotman/_tests/archive_test.py similarity index 95% rename from archive_test.py rename to src/plotman/_tests/archive_test.py index 0bff2f87..6318045a 100755 --- a/archive_test.py +++ b/src/plotman/_tests/archive_test.py @@ -1,5 +1,5 @@ -import archive -import manager +from plotman import archive, manager + def test_compute_priority(): assert (archive.compute_priority( (3, 1), 1000, 10) > diff --git a/manager_test.py b/src/plotman/_tests/manager_test.py similarity index 97% rename from manager_test.py rename to src/plotman/_tests/manager_test.py index 2ec4e245..9048dc03 100755 --- a/manager_test.py +++ b/src/plotman/_tests/manager_test.py @@ -2,8 +2,9 @@ from unittest.mock import patch import pytest -import manager -import job + +from plotman import job, manager + @pytest.fixture def sched_cfg(): @@ -44,14 +45,14 @@ def test_permit_new_job_override_tmp_dir(sched_cfg, dir_cfg): [ (3, 1), (3, 2), (3, 3), (3, 6) ], '/mnt/tmp/04', sched_cfg, dir_cfg) -@patch('job.Job') +@patch('plotman.job.Job') def job_w_tmpdir_phase(tmpdir, phase, MockJob): j = MockJob() j.progress.return_value = phase j.tmpdir = tmpdir return j -@patch('job.Job') +@patch('plotman.job.Job') def job_w_dstdir_phase(dstdir, phase, MockJob): j = MockJob() j.progress.return_value = phase diff --git a/plot_util_test.py b/src/plotman/_tests/plot_util_test.py similarity index 96% rename from plot_util_test.py rename to src/plotman/_tests/plot_util_test.py index 2585fced..5b8ca2ad 100755 --- a/plot_util_test.py +++ b/src/plotman/_tests/plot_util_test.py @@ -1,9 +1,10 @@ -from plot_util import GB - import os + import pyfakefs -import plot_util +from plotman import plot_util +from plotman.plot_util import GB + def test_human_format(): assert (plot_util.human_format(3442000000, 0) == '3G') diff --git a/reporting_test.py b/src/plotman/_tests/reporting_test.py similarity index 96% rename from reporting_test.py rename to src/plotman/_tests/reporting_test.py index 6cf374c4..b46dd873 100644 --- a/reporting_test.py +++ b/src/plotman/_tests/reporting_test.py @@ -1,9 +1,9 @@ # TODO: migrate away from unittest patch +import os from unittest.mock import patch -import os +from plotman import reporting -import reporting def test_phases_str_basic(): assert(reporting.phases_str([(1,2), (2,3), (3,4), (4,0)]) == @@ -24,7 +24,7 @@ def test_phases_str_none(): def test_job_viz_empty(): assert(reporting.job_viz([]) == '1 2 3 4 ') -@patch('job.Job') +@patch('plotman.job.Job') def job_w_phase(ph, MockJob): j = MockJob() j.progress.return_value = ph diff --git a/analyzer.py b/src/plotman/analyzer.py similarity index 99% rename from analyzer.py rename to src/plotman/analyzer.py index 84b26ca3..2dfbfbce 100644 --- a/analyzer.py +++ b/src/plotman/analyzer.py @@ -2,9 +2,11 @@ import re import statistics import sys + import texttable as tt -import plot_util +from plotman import plot_util + class LogAnalyzer: def analyze(self, logfilenames, bytmp, bybitfield): diff --git a/archive.py b/src/plotman/archive.py similarity index 99% rename from archive.py rename to src/plotman/archive.py index 887a5e6f..5dead637 100644 --- a/archive.py +++ b/src/plotman/archive.py @@ -1,18 +1,17 @@ -from datetime import datetime -import subprocess import argparse import contextlib import math import os -import psutil -import re import random +import re +import subprocess import sys +from datetime import datetime +import psutil import texttable as tt -import manager -import plot_util +from plotman import manager, plot_util # TODO : write-protect and delete-protect archived plots diff --git a/interactive.py b/src/plotman/interactive.py similarity index 99% rename from interactive.py rename to src/plotman/interactive.py index 60d1c835..4280bbf4 100644 --- a/interactive.py +++ b/src/plotman/interactive.py @@ -5,12 +5,12 @@ import os import subprocess import threading + import yaml -from job import Job -import archive -import manager -import reporting +from plotman import archive, manager, reporting +from plotman.job import Job + class Log: def __init__(self): diff --git a/job.py b/src/plotman/job.py similarity index 99% rename from job.py rename to src/plotman/job.py index 620e2348..6bbab062 100644 --- a/job.py +++ b/src/plotman/job.py @@ -1,18 +1,19 @@ # TODO do we use all these? -from datetime import datetime -from enum import Enum, auto -from subprocess import call import argparse - import contextlib import logging import os +import random import re +import sys import threading import time -import psutil # apt-get install python-psutil -import random -import sys +from datetime import datetime +from enum import Enum, auto +from subprocess import call + +import psutil + def job_phases_for_tmpdir(d, all_jobs): '''Return phase 2-tuples for jobs running on tmpdir d''' diff --git a/manager.py b/src/plotman/manager.py similarity index 97% rename from manager.py rename to src/plotman/manager.py index 0869cd04..2a17e619 100644 --- a/manager.py +++ b/src/plotman/manager.py @@ -1,21 +1,21 @@ -from datetime import datetime - import logging import operator import os +import random import re +import readline # For nice CLI +import subprocess +import sys import threading import time +from datetime import datetime + import psutil -import random -import readline # For nice CLI -import subprocess -import sys # Plotman libraries -import job -import plot_util -import archive # for get_archdir_freebytes(). TODO: move to avoid import loop +from plotman import \ + archive # for get_archdir_freebytes(). TODO: move to avoid import loop +from plotman import job, plot_util # Constants MIN = 60 # Seconds diff --git a/plot_util.py b/src/plotman/plot_util.py similarity index 100% rename from plot_util.py rename to src/plotman/plot_util.py diff --git a/plotman.py b/src/plotman/plotman.py similarity index 95% rename from plotman.py rename to src/plotman/plotman.py index 5264d195..4e4ffe22 100755 --- a/plotman.py +++ b/src/plotman/plotman.py @@ -1,26 +1,22 @@ #!/usr/bin/env python3 -from datetime import datetime -from subprocess import call - import argparse import os -import re -import threading import random -import readline # For nice CLI +import re +import readline # For nice CLI import sys +import threading import time +from datetime import datetime +from subprocess import call + import yaml # Plotman libraries -from job import Job -import analyzer -import archive -import interactive -import manager -import plot_util -import reporting +from plotman import analyzer, archive, interactive, manager, plot_util, reporting +from plotman.job import Job + class PlotmanArgParser: def add_idprefix_arg(self, subparser): @@ -34,6 +30,8 @@ def parse_args(self): parser = argparse.ArgumentParser(description='Chia plotting manager.') sp = parser.add_subparsers(dest='cmd') + p_version = sp.add_parser('version', help='print the version') + p_status = sp.add_parser('status', help='show current plotting status') p_dirs = sp.add_parser('dirs', help='show directories info') @@ -85,11 +83,16 @@ def get_term_width(): columns = 120 # 80 is typically too narrow. TODO: make a command line arg. return columns -if __name__ == "__main__": +def main(): random.seed() pm_parser = PlotmanArgParser() args = pm_parser.parse_args() + + if args.cmd == 'version': + import pkg_resources + print(pkg_resources.get_distribution('plotman')) + return with open('config.yaml', 'r') as ymlfile: cfg = yaml.load(ymlfile, Loader=yaml.FullLoader) @@ -207,4 +210,3 @@ def get_term_width(): elif args.cmd == 'resume': print('Resuming ' + job.plot_id) job.resume() - diff --git a/reporting.py b/src/plotman/reporting.py similarity index 98% rename from reporting.py rename to src/plotman/reporting.py index d3ffa980..23d39683 100644 --- a/reporting.py +++ b/src/plotman/reporting.py @@ -1,12 +1,11 @@ -import texttable as tt # from somewhere? +import math import os + import psutil +import texttable as tt # from somewhere? + +from plotman import archive, job, manager, plot_util -import archive -import job -import manager -import math -import plot_util def abbr_path(path, putative_prefix): if putative_prefix and path.startswith(putative_prefix): diff --git a/tox.ini b/tox.ini index c174a6a8..42fecde6 100644 --- a/tox.ini +++ b/tox.ini @@ -3,15 +3,10 @@ envlist = test-py{36,37,38,39,py36,py37} [testenv] ;changedir = {envtmpdir} -skip_install = true [testenv:test-py{36,37,38,39,py36,py37}] -;extras = -; test -deps = - psutil - pyfakefs - pytest - texttable +extras = + test + commands = pytest --capture=no --verbose {toxinidir} diff --git a/listlogs b/util/listlogs old mode 100644 new mode 100755 similarity index 100% rename from listlogs rename to util/listlogs