diff --git a/.coveragerc b/.coveragerc index 652b4d1..ee5abec 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,9 @@ [run] branch = True +include = argopt/* omit = argopt/tests/* argopt/_docopt.py +relative_files = True [report] show_missing = True diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..7e43b66 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# Require maintainer's :+1: for changes to the .github/ repo-config files +# mainly due to https://github.com/probot/settings privilege escalation +.github/* @github/pages diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..44774f1 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: casperdcl +custom: https://caspersci.uk.to/donate diff --git a/.github/workflows/comment-bot.yml b/.github/workflows/comment-bot.yml new file mode 100644 index 0000000..4451632 --- /dev/null +++ b/.github/workflows/comment-bot.yml @@ -0,0 +1,50 @@ +name: Comment Bot +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] +jobs: + tag: # /tag + if: startsWith(github.event.comment.body, '/tag ') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: React Seen + uses: actions/github-script@v2 + with: + script: | + const perm = await github.repos.getCollaboratorPermissionLevel({ + owner: context.repo.owner, repo: context.repo.repo, + username: context.payload.comment.user.login}) + post = (context.eventName == "issue_comment" + ? github.reactions.createForIssueComment + : github.reactions.createForPullRequestReviewComment) + if (!["admin", "write"].includes(perm.data.permission)){ + post({ + owner: context.repo.owner, repo: context.repo.repo, + comment_id: context.payload.comment.id, content: "laugh"}) + throw "Permission denied for user " + context.payload.comment.user.login + } + post({ + owner: context.repo.owner, repo: context.repo.repo, + comment_id: context.payload.comment.id, content: "eyes"}) + - name: Tag Commit + run: | + git clone https://${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY} repo + git -C repo tag $(echo "$BODY" | awk '{print $2" "$3}') + git -C repo push --tags + rm -rf repo + env: + BODY: ${{ github.event.comment.body }} + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + - name: React Success + uses: actions/github-script@v2 + with: + script: | + post = (context.eventName == "issue_comment" + ? github.reactions.createForIssueComment + : github.reactions.createForPullRequestReviewComment) + post({ + owner: context.repo.owner, repo: context.repo.repo, + comment_id: context.payload.comment.id, content: "rocket"}) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..e95ba47 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,136 @@ +name: Test +on: + push: + pull_request: + schedule: + - cron: '3 2 1 * *' # M H d m w (monthly at 2:03) +jobs: + check: + if: github.event_name != 'pull_request' || github.head_ref != 'devel' + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: set PYSHA + run: echo "PYSHA=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV + - uses: actions/cache@v1 + with: + path: ~/.cache/pre-commit + key: pre-commit|${{ env.PYSHA }}|${{ hashFiles('.pre-commit-config.yaml') }} + - name: Test + run: | + pip install -U tox + tox -e setup.py + - name: Self install + run: pip install -U .[dev] + - name: Build + run: | + python setup.py sdist bdist_wheel + twine check dist/* + - uses: reviewdog/action-setup@v1 + - if: github.event_name != 'schedule' + name: flake8 + run: | + pre-commit run -a flake8 | reviewdog -f=pep8 -name=Format -tee -reporter=github-check -filter-mode nofilter + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Lint + run: pre-commit run -a --show-diff-on-failure + test: + if: github.event_name != 'pull_request' || github.head_ref != 'devel' + strategy: + matrix: + python: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, pypy3] + name: Python ${{ matrix.python }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python }} + - name: Install + run: pip install -U tox + - name: Test + run: | + if [[ "$PYVER" == py* ]]; then + tox -e $PYVER # basic:pypy + else + tox -e py${PYVER/./} # normal + fi + env: + PYVER: ${{ matrix.python }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: Coveralls Parallel + uses: AndreMiras/coveralls-python-action@develop + with: + parallel: true + finish: + if: github.event_name != 'pull_request' || github.head_ref != 'devel' + name: Coverage + continue-on-error: ${{ github.event_name != 'push' }} + needs: test + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: AndreMiras/coveralls-python-action@develop + with: + parallel-finished: true + deploy: + if: github.event_name != 'pull_request' || github.head_ref != 'devel' + name: Deploy + needs: [check, test] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + uses: casperdcl/deploy-pypi@v1 + with: + build: true + gpg_key: ${{ secrets.GPG_KEY }} + password: ${{ secrets.PYPI_TOKEN }} + skip_existing: true + - id: collect_assets + name: Collect assets + run: | + echo "::set-output name=asset_path::$(ls dist/*.whl)" + echo "::set-output name=asset_name::$(basename dist/*.whl)" + echo "::set-output name=asset_path_sig::$(ls dist/*.whl.asc 2>/dev/null)" + echo "::set-output name=asset_name_sig::$(basename dist/*.whl.asc 2>/dev/null)" + git log --pretty='format:%d%n- %s%n%b---' $(git tag --sort=v:refname | tail -n2 | head -n1)..HEAD > _CHANGES.md + - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: argopt ${{ github.ref }} stable + body_path: _CHANGES.md + draft: true + - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ steps.collect_assets.outputs.asset_path }} + asset_name: ${{ steps.collect_assets.outputs.asset_name }} + asset_content_type: application/zip + - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ steps.collect_assets.outputs.asset_path_sig }} + asset_name: ${{ steps.collect_assets.outputs.asset_name_sig }} + asset_content_type: text/plain diff --git a/.gitignore b/.gitignore index db57cb8..e08feb6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ *.py[co] # build -argopt.egg-info/ -build/ -dist/ +/argopt/_dist_ver.py +/.eggs/ +/*.egg-info +/build/ +/dist/ # test .tox/ .coverage -__pycache__ \ No newline at end of file +__pycache__/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..c6c7843 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,28 @@ +default_language_version: + python: python3 +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.3.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-docstring-first + - id: check-executables-have-shebangs + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace +- hooks: + - id: flake8 + additional_dependencies: + - flake8-bugbear + - flake8-comprehensions + - flake8-debugger + - flake8-string-format + repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.4 +- hooks: + - id: isort + repo: https://github.com/timothycrosley/isort + rev: 5.6.4 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 405641b..0000000 --- a/.travis.yml +++ /dev/null @@ -1,89 +0,0 @@ -language: python -env: - global: - - PIP_CACHE_DIR="$HOME/.cache/pip" # unify pip cache location for all platforms -cache: - pip: true - directories: - - $HOME/.cache/pip -before_cache: -- rm -f $HOME/.cache/pip/log/debug.log -notifications: - email: false -stages: -- check -- test -- name: deploy - if: repo = casperdcl/argopt AND NOT type = pull_request -jobs: - include: - - stage: test - name: py2.6 - python: 2.6 - env: TOXENV=py26 - dist: trusty - - name: py2.7 - python: 2.7 - env: TOXENV=py27 - - name: py3.4 - python: 3.4 - env: TOXENV=py34 - - name: py3.5 - python: 3.5 - env: TOXENV=py35 - - name: py3.6 - python: 3.6 - env: TOXENV=py36 - - name: py3.7 - python: 3.7 - env: TOXENV=py37 - - name: pypy2.7 - python: pypy2.7-5.10.0 - env: TOXENV=pypy - - name: pypy3.5 - python: pypy3.5-5.10.0 - env: TOXENV=pypy3 - - stage: check - name: style - python: 3.7 - env: TOXENV=flake8 - - name: setup - python: 3.7 - env: TOXENV=setup.py - - stage: deploy - name: PyPI and GitHub - python: 3.7 - install: - script: - - pip install .[dev] - - make build - - echo "$GPG_KEY" | base64 --decode > .key.gpg - - gpg --import .key.gpg - - rm .key.gpg - - git log --pretty='format:- %s%n%b---' $(git tag --sort=creatordate | tail -n2 | head -n1)..HEAD > CHANGES.md - deploy: - - provider: script - script: twine upload -s -i casper.dcl@physics.org dist/argopt-* - skip_cleanup: true - on: - tags: true - - provider: releases - api_key: $GITHUB_TOKEN - file_glob: true - file: dist/argopt-*.whl* - skip_cleanup: true - draft: true - name: argopt $TRAVIS_TAG stable - edge: true - tag_name: $TRAVIS_TAG - target_commitish: $TRAVIS_COMMIT - release_notes_file: CHANGES.md - on: - tags: true -before_install: -- git fetch --tags -install: -- pip install tox -- pip install . -script: -- tox diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 99874d3..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,13 +0,0 @@ -# Misc -include .coveragerc -include LICENCE -include Makefile -include tox.ini - -# Test suite -recursive-include argopt/tests *.py -include requirements-dev.txt - -# Examples/Documentation -recursive-include examples *.py -include README.rst diff --git a/Makefile b/Makefile index 3345edd..d4e71da 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,6 @@ testtimer distclean coverclean - pre-commit prebuildclean clean toxclean @@ -71,15 +70,12 @@ distclean: @+make coverclean @+make prebuildclean @+make clean -pre-commit: - # quick sanity checks - @make testsetup - @flake8 -j 8 --count --statistics . - @make testnose prebuildclean: @+python -c "import shutil; shutil.rmtree('build', True)" @+python -c "import shutil; shutil.rmtree('dist', True)" @+python -c "import shutil; shutil.rmtree('argopt.egg-info', True)" + @+python -c "import shutil; shutil.rmtree('.eggs', True)" + @+python -c "import os; os.remove('argopt/_dist_ver.py') if os.path.exists('argopt/_dist_ver.py') else None" coverclean: @+python -c "import os; os.remove('.coverage') if os.path.exists('.coverage') else None" @+python -c "import shutil; shutil.rmtree('argopt/__pycache__', True)" diff --git a/README.rst b/README.rst index 354ec07..9f5973a 100644 --- a/README.rst +++ b/README.rst @@ -3,11 +3,11 @@ argopt doc to ``argparse`` driven by ``docopt`` -|PyPI-Status| |PyPI-Versions| +|Py-Versions| |PyPI| |Conda-Forge| -|Build-Status| |Coverage-Status| |Branch-Coverage-Status| |Codacy-Grade| +|Build-Status| |Coverage-Status| |Branch-Coverage-Status| |Codacy-Grade| |Libraries-Rank| |PyPI-Downloads| -|LICENCE| |Donate| |OpenHub-Status| +|LICENCE| |OpenHub-Status| |Gift-Casper| Define your command line interface (CLI) from a docstring (rather than the other way around). Because it's easy. It's quick. Painless. Then focus on @@ -32,31 +32,37 @@ Installation Latest PyPI stable release ~~~~~~~~~~~~~~~~~~~~~~~~~~ -|PyPI-Status| +|PyPI| |PyPI-Downloads| |Libraries-Dependents| .. code:: sh pip install argopt -Latest development release on github +Latest development release on GitHub ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -|GitHub-Status| +|GitHub-Status| |GitHub-Stars| |GitHub-Commits| |GitHub-Forks| |GitHub-Updated| -Pull and install in the current directory: +Pull and install: .. code:: sh - pip install -e git+https://github.com/casperdcl/argopt.git@master#egg=argopt + pip install "git+https://github.com/casperdcl/argopt.git@master#egg=argopt" + +Latest Conda release +~~~~~~~~~~~~~~~~~~~~ + +|Conda-Forge| + +.. code:: sh + + conda install -c conda-forge argopt Changelog --------- -The list of all changes is available either on -`Github's Releases `__ -or on crawlers such as -`allmychanges.com `__. +The list of all changes is available on the Releases page: |GitHub-Status|. Usage @@ -138,6 +144,8 @@ folder. Documentation ------------- +|Py-Versions| |README-Hits| + .. code:: python def argopt(doc='', argparser=ArgumentParser, @@ -186,63 +194,70 @@ Documentation Contributions ------------- -To run the testing suite please make sure tox (https://testrun.org/tox/latest/) -is installed, then type ``tox`` from the command line. - -Where ``tox`` is unavailable, a Makefile-like setup is -provided with the following command: - -.. code:: sh - - $ python setup.py make alltests - -To see all options, run: +|GitHub-Commits| |GitHub-Issues| |GitHub-PRs| |OpenHub-Status| -.. code:: sh +All source code is hosted on `GitHub `__. +Contributions are welcome. - $ python setup.py make - -Licence +LICENCE ------- Open Source (OSI approved): |LICENCE| -Copyright (c) 2016-8 Casper da Costa-Luis. - -This Source Code Form is subject to the terms of the -Mozilla Public License, v. 2.0. -If a copy of the MPL was not distributed with this file, You can obtain one -at `https://mozilla.org/MPL/2.0/ `__. - Authors ------- |OpenHub-Status| -- Casper da Costa-Luis (`@casperdcl `__) |Donate| +- Casper da Costa-Luis (`casperdcl `__ |Gift-Casper|) + +We are grateful for all |GitHub-Contributions|. -|argopt-hits| +|README-Hits| -.. |Build-Status| image:: https://travis-ci.org/casperdcl/argopt.svg?branch=master - :target: https://travis-ci.org/casperdcl/argopt -.. |Coverage-Status| image:: https://coveralls.io/repos/casperdcl/argopt/badge.svg?branch=master +.. |Build-Status| image:: https://img.shields.io/github/workflow/status/casperdcl/argopt/Test/master?logo=GitHub + :target: https://github.com/casperdcl/argopt/actions?query=workflow%3ATest +.. |Coverage-Status| image:: https://img.shields.io/coveralls/github/casperdcl/argopt/master?logo=coveralls :target: https://coveralls.io/github/casperdcl/argopt .. |Branch-Coverage-Status| image:: https://codecov.io/gh/casperdcl/argopt/branch/master/graph/badge.svg :target: https://codecov.io/gh/casperdcl/argopt -.. |GitHub-Status| image:: https://img.shields.io/github/tag/casperdcl/argopt.svg?maxAge=2592000 +.. |Codacy-Grade| image:: https://api.codacy.com/project/badge/Grade/5282d52c142d4c6ea24f978b03981c6f + :target: https://app.codacy.com/gh/casperdcl/argopt +.. |GitHub-Status| image:: https://img.shields.io/github/tag/casperdcl/argopt.svg?maxAge=86400&logo=github :target: https://github.com/casperdcl/argopt/releases -.. |PyPI-Status| image:: https://img.shields.io/pypi/v/argopt.svg - :target: https://pypi.python.org/pypi/argopt -.. |PyPI-Versions| image:: https://img.shields.io/pypi/pyversions/argopt.svg - :target: https://pypi.python.org/pypi/argopt -.. |argopt-hits| image:: https://caspersci.uk.to/cgi-bin/hits.cgi?q=argopt&a=hidden +.. |GitHub-Forks| image:: https://img.shields.io/github/forks/casperdcl/argopt.svg?logo=github + :target: https://github.com/casperdcl/argopt/network +.. |GitHub-Stars| image:: https://img.shields.io/github/stars/casperdcl/argopt.svg?logo=github + :target: https://github.com/casperdcl/argopt/stargazers +.. |GitHub-Commits| image:: https://img.shields.io/github/commit-activity/y/casperdcl/argopt?label=commits&logo=git + :target: https://github.com/casperdcl/argopt/graphs/commit-activity +.. |GitHub-Issues| image:: https://img.shields.io/github/issues-closed/casperdcl/argopt.svg?logo=github + :target: https://github.com/casperdcl/argopt/issues +.. |GitHub-PRs| image:: https://img.shields.io/github/issues-pr-closed/casperdcl/argopt.svg?logo=github + :target: https://github.com/casperdcl/argopt/pulls +.. |GitHub-Contributions| image:: https://img.shields.io/github/contributors/casperdcl/argopt.svg?logo=github + :target: https://github.com/casperdcl/argopt/graphs/contributors +.. |GitHub-Updated| image:: https://img.shields.io/github/last-commit/casperdcl/argopt?label=pushed&logo=github + :target: https://github.com/casperdcl/argopt/pulse +.. |Gift-Casper| image:: https://img.shields.io/badge/gift-donate-dc10ff.svg?logo=Contactless%20Payment + :target: https://caspersci.uk.to/donate +.. |PyPI| image:: https://img.shields.io/pypi/v/argopt.svg?logo=PyPI&logoColor=white + :target: https://pypi.org/project/argopt +.. |PyPI-Downloads| image:: https://img.shields.io/pypi/dm/argopt.svg?label=pypi%20downloads&logo=DocuSign + :target: https://pypi.org/project/argopt +.. |Py-Versions| image:: https://img.shields.io/pypi/pyversions/argopt.svg?logo=python&logoColor=white + :target: https://pypi.org/project/argopt +.. |Conda-Forge| image:: https://img.shields.io/conda/v/conda-forge/argopt.svg?label=conda-forge&logo=conda-forge + :target: https://anaconda.org/conda-forge/argopt +.. |Libraries-Rank| image:: https://img.shields.io/librariesio/sourcerank/pypi/argopt.svg?color=green&logo=koding + :target: https://libraries.io/pypi/argopt +.. |Libraries-Dependents| image:: https://img.shields.io/librariesio/dependent-repos/pypi/argopt.svg?logo=koding + :target: https://github.com/casperdcl/argopt/network/dependents .. |OpenHub-Status| image:: https://www.openhub.net/p/arg-opt/widgets/project_thin_badge?format=gif :target: https://www.openhub.net/p/arg-opt?ref=Thin+badge -.. |LICENCE| image:: https://img.shields.io/pypi/l/argopt.svg - :target: https://mozilla.org/MPL/2.0/ -.. |Codacy-Grade| image:: https://api.codacy.com/project/badge/Grade/5282d52c142d4c6ea24f978b03981c6f - :target: https://www.codacy.com/app/casper-dcl/argopt -.. |Donate| image:: https://img.shields.io/badge/gift-donate-dc10ff.svg - :target: https://caspersci.uk.to/donate.html +.. |LICENCE| image:: https://img.shields.io/pypi/l/argopt.svg?color=purple&logo=SPDX + :target: https://raw.githubusercontent.com/casperdcl/argopt/master/LICENCE +.. |README-Hits| image:: https://caspersci.uk.to/cgi-bin/hits.cgi?q=argopt&style=social&r=https://github.com/casperdcl/argopt + :target: https://caspersci.uk.to/cgi-bin/hits.cgi?q=argopt&a=plot&r=https://github.com/casperdcl/argopt&style=social diff --git a/argopt/__init__.py b/argopt/__init__.py index ca2847a..9f59dd3 100644 --- a/argopt/__init__.py +++ b/argopt/__init__.py @@ -1,10 +1,12 @@ -from ._argopt import __author__ -from ._argopt import __date__ -from ._argopt import __licence__ -from ._argopt import __copyright__ -from ._argopt import __version__ -from ._argopt import __license__ -from ._argopt import argopt +from ._argopt import ( + __author__, + __copyright__, + __date__, + __licence__, + __license__, + __version__, + argopt, +) from ._utils import DictAttrWrap __all__ = ['argopt', 'DictAttrWrap', diff --git a/argopt/_argopt.py b/argopt/_argopt.py index 64ae912..e2f3248 100644 --- a/argopt/_argopt.py +++ b/argopt/_argopt.py @@ -1,19 +1,36 @@ from __future__ import print_function -from argparse import ArgumentParser, RawDescriptionHelpFormatter +import logging import re -from ._docopt import Argument, Option, AnyOptions, DocoptLanguageError, \ - parse_defaults, parse_pattern, printable_usage, formal_usage +from argparse import ArgumentParser, RawDescriptionHelpFormatter + +from ._docopt import ( + AnyOptions, + Argument, + DocoptLanguageError, + Option, + formal_usage, + parse_defaults, + parse_pattern, + printable_usage, +) from ._utils import _range, set_nargs -import logging -from ._version import __version__ # NOQA +# version detector. Precedence: installed dist, git, 'UNKNOWN' +try: + from ._dist_ver import __version__ +except ImportError: + try: + from setuptools_scm import get_version + __version__ = get_version(root='..', relative_to=__file__) + except (ImportError, LookupError): + __version__ = "UNKNOWN" __author__ = "Casper da Costa-Luis " -__date__ = "2016-7" -__licence__ = "[MPLv2.0](https://mozilla.org/MPL/2.0/)" -__all__ = ["argopt"] +__date__ = "2016-2020" +__licence__ = __license__ = "[MPLv2.0](https://mozilla.org/MPL/2.0/)" __copyright__ = ' '.join(("Copyright (c)", __date__, __author__, __licence__)) -__license__ = __licence__ # weird foreign language + +log = logging.getLogger(__name__) RE_ARG_ONCE = re.compile(r"(?" -__date__ = "2016-7" -__licence__ = "[MPLv2.0](https://mozilla.org/MPL/2.0/)" __all__ = ["_range", "typecast", "set_nargs", "_sh", "DictAttrWrap"] -__copyright__ = ' '.join(("Copyright (c)", __date__, __author__, __licence__)) -__license__ = __licence__ # weird foreign language try: # pragma: no cover _range = xrange diff --git a/argopt/_version.py b/argopt/_version.py deleted file mode 100644 index 4f969eb..0000000 --- a/argopt/_version.py +++ /dev/null @@ -1,36 +0,0 @@ -# Definition of the version number -try: # pragma: no cover - from ._utils import _sh -except ValueError: # pragma: no cover - _sh = None -except ImportError: # pragma: no cover - _sh = None -except SystemError: # pragma: no cover - _sh = None - -from subprocess import STDOUT -__all__ = ["__version__"] - -# major, minor, patch, -extra -version_info = 0, 6, 1 - -# Nice string for the version -__version__ = '.'.join(map(str, version_info)) - - -# auto -extra based on commit hash (if not tagged as release) -if (_sh is not None) and (len(version_info) < 4): # pragma: no cover - def commit_hash(*args): - try: - res = _sh('git', 'log', '-n', '1', '--oneline', *args, - stderr=STDOUT).lstrip().split()[0] - return None if res.startswith('fatal') else res - except: # NOQA - return None - - cur_hash = commit_hash() - if cur_hash is not None: - last_release = commit_hash('v' + __version__) - - if (last_release is None) or (cur_hash not in last_release): - __version__ += '-' + cur_hash diff --git a/argopt/tests/tests_argopt.py b/argopt/tests/tests_argopt.py index 0440c79..ed510a0 100644 --- a/argopt/tests/tests_argopt.py +++ b/argopt/tests/tests_argopt.py @@ -1,5 +1,7 @@ -from argopt import argopt from argparse import RawDescriptionHelpFormatter + +from argopt import argopt + try: from StringIO import StringIO except ImportError: diff --git a/argopt/tests/tests_utils.py b/argopt/tests/tests_utils.py index 945b26b..e65f798 100644 --- a/argopt/tests/tests_utils.py +++ b/argopt/tests/tests_utils.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + from argopt import _utils diff --git a/examples/demo_advanced.py b/examples/demo_advanced.py index bf1439d..ae3aa9a 100644 --- a/examples/demo_advanced.py +++ b/examples/demo_advanced.py @@ -17,10 +17,10 @@ -f, --force Force. --ignore-gooey """ -from argopt import argopt -import sys import os +import sys +from argopt import argopt if '--with-gooey' in sys.argv: from gooey import Gooey diff --git a/examples/demo_basic.py b/examples/demo_basic.py index 452277b..e61ae2e 100644 --- a/examples/demo_basic.py +++ b/examples/demo_basic.py @@ -18,6 +18,7 @@ """ from argopt import argopt + __version__ = "0.1.2-3.4" diff --git a/examples/demo_basic_docopt.py b/examples/demo_basic_docopt.py index 1a2d751..9d0bad4 100644 --- a/examples/demo_basic_docopt.py +++ b/examples/demo_basic_docopt.py @@ -17,8 +17,10 @@ -h, --help Show this help message and exit. -v, --version Show program's version number and exit. """ -from docopt import docopt from ast import literal_eval + +from docopt import docopt + __version__ = "0.1.2-3.4" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f2c9f3f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,7 @@ +[build-system] +requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +write_to = "argopt/_dist_ver.py" +write_to_template = "__version__ = '{version}'\n" diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 44dd84c..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,2 +0,0 @@ -py-make>=0.1.0 # setup.py make/pymake -twine # pymake pypi diff --git a/setup.cfg b/setup.cfg index c01342e..e9eaa91 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,96 @@ +[metadata] +name = argopt +url = https://github.com/casperdcl/argopt +project_urls = + Changelog = https://github.com/casperdcl/argopt/releases + Documentation = https://github.com/casperdcl/argopt/#argopt +licence = MPL 2.0 +license_file = LICENCE +description = doc to argparse driven by docopt +long_description = file: README.rst +long_description_content_type = text/x-rst +author = Casper da Costa-Luis +author_email = casper.dcl@physics.org +keywords = docopt, argparse, doc, docstring, commandline, argument, option, optional, parameter, positional, console, terminal, command line, CLI, UI, gui, gooey +platforms = any +provides = argopt +# Trove classifiers (https://pypi.org/pypi?%3Aaction=list_classifiers) +classifiers = + Development Status :: 5 - Production/Stable + Environment :: Console + Environment :: MacOS X + Environment :: Other Environment + Environment :: Win32 (MS Windows) + Environment :: X11 Applications + Framework :: IPython + Intended Audience :: Developers + Intended Audience :: Education + Intended Audience :: End Users/Desktop + Intended Audience :: Other Audience + Intended Audience :: System Administrators + License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) + Operating System :: MacOS + Operating System :: MacOS :: MacOS X + Operating System :: Microsoft + Operating System :: Microsoft :: MS-DOS + Operating System :: Microsoft :: Windows + Operating System :: POSIX + Operating System :: POSIX :: BSD + Operating System :: POSIX :: BSD :: FreeBSD + Operating System :: POSIX :: Linux + Operating System :: POSIX :: SunOS/Solaris + Operating System :: Unix + Programming Language :: Python + Programming Language :: Python :: 2 + Programming Language :: Python :: 2.6 + Programming Language :: Python :: 2.7 + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.2 + Programming Language :: Python :: 3.3 + Programming Language :: Python :: 3.4 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: Implementation + Programming Language :: Python :: Implementation :: IronPython + Programming Language :: Python :: Implementation :: PyPy + Programming Language :: Unix Shell + Topic :: Desktop Environment + Topic :: Education :: Computer Aided Instruction (CAI) + Topic :: Education :: Testing + Topic :: Office/Business + Topic :: Other/Nonlisted Topic + Topic :: Software Development :: Build Tools + Topic :: Software Development :: Libraries + Topic :: Software Development :: Libraries :: Python Modules + Topic :: Software Development :: Pre-processors + Topic :: Software Development :: User Interfaces + Topic :: System :: Installation/Setup + Topic :: System :: Logging + Topic :: System :: Monitoring + Topic :: System :: Shells + Topic :: Terminals + Topic :: Utilities +[options] +setup_requires = setuptools>=42; setuptools_scm[toml]>=3.4 +install_requires = + argparse; python_version == "2.6" +python_requires = >=2.6, !=3.0.*, !=3.1.* +tests_require = nose; flake8; coverage +packages = find: +[options.extras_require] +dev = py-make>=0.1.0; twine; wheel; pre-commit [bdist_wheel] universal = 1 [flake8] -max_line_length = 80 -exclude = .tox,.ipynb_checkpoints,build,dist,.git,__pycache__ +# TODO: fix & remove C405,C407 after py26 deprecation +extend-ignore=E203,P1,C405,C407 +max_line_length = 88 +exclude = .eggs,.tox,dist,build,dist,.git,__pycache__ + +[isort] +profile = black +known_first_party = argopt,tests diff --git a/setup.py b/setup.py index ce6182c..cbfee8f 100644 --- a/setup.py +++ b/setup.py @@ -1,121 +1,16 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import os -try: - from setuptools import setup -except ImportError: - from distutils.core import setup import sys -from io import open as io_open +from os import path -__author__ = None -__licence__ = None -__version__ = None -src_dir = os.path.abspath(os.path.dirname(__file__)) -main_file = os.path.join(src_dir, 'argopt', '_argopt.py') -for l in io_open(main_file, mode='r'): - if any(l.startswith(i) for i in ('__author__', '__licence__')): - exec(l) -version_file = os.path.join(src_dir, 'argopt', '_version.py') -with io_open(version_file, mode='r') as fd: - exec(fd.read()) +from setuptools import setup -# Executing makefile commands if specified -if sys.argv[1].lower().strip() == 'make': +src_dir = path.abspath(path.dirname(__file__)) +if sys.argv[1].lower().strip() == 'make': # exec Makefile commands import pymake - # Filename of the makefile - fpath = os.path.join(src_dir, 'Makefile') + fpath = path.join(src_dir, 'Makefile') pymake.main(['-f', fpath] + sys.argv[2:]) # Stop to avoid setup.py raising non-standard command error sys.exit(0) -extras_require = {} -requirements_dev = os.path.join(src_dir, 'requirements-dev.txt') -with io_open(requirements_dev, mode='r') as fd: - extras_require['dev'] = [i.strip().split('#', 1)[0].strip() - for i in fd.read().strip().split('\n')] - -README_rst = '' -fndoc = os.path.join(src_dir, 'README.rst') -with io_open(fndoc, mode='r', encoding='utf-8') as fd: - README_rst = fd.read() -setup( - name='argopt', - version=__version__, - description='doc to argparse driven by docopt', - long_description=README_rst, - license=__licence__.lstrip('[').split(']')[0], - author=__author__.split('<')[0].strip(), - author_email=__author__.split('<')[1][1:-1], - url='https://github.com/casperdcl/argopt', - platforms=['any'], - packages=['argopt'], - install_requires=['argparse'] if sys.version_info[:2] < (2, 7) else [], - extras_require=extras_require, - package_data={'argopt': ['LICENCE']}, - python_requires='>=2.6, !=3.0.*, !=3.1.*', - classifiers=[ - # Trove classifiers - # (https://pypi.org/pypi?%3Aaction=list_classifiers) - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Environment :: MacOS X', - 'Environment :: Other Environment', - 'Environment :: Win32 (MS Windows)', - 'Environment :: X11 Applications', - 'Framework :: IPython', - 'Intended Audience :: Developers', - 'Intended Audience :: Education', - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Other Audience', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)', - 'Operating System :: MacOS', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft', - 'Operating System :: Microsoft :: MS-DOS', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Operating System :: POSIX :: BSD', - 'Operating System :: POSIX :: BSD :: FreeBSD', - 'Operating System :: POSIX :: Linux', - 'Operating System :: POSIX :: SunOS/Solaris', - 'Operating System :: Unix', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: Implementation', - 'Programming Language :: Python :: Implementation :: IronPython', - 'Programming Language :: Python :: Implementation :: PyPy', - 'Programming Language :: Unix Shell', - 'Topic :: Desktop Environment', - 'Topic :: Education :: Computer Aided Instruction (CAI)', - 'Topic :: Education :: Testing', - 'Topic :: Office/Business', - 'Topic :: Other/Nonlisted Topic', - 'Topic :: Software Development :: Build Tools', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Software Development :: Pre-processors', - 'Topic :: Software Development :: User Interfaces', - 'Topic :: System :: Installation/Setup', - 'Topic :: System :: Logging', - 'Topic :: System :: Monitoring', - 'Topic :: System :: Shells', - 'Topic :: Terminals', - 'Topic :: Utilities' - ], - keywords='docopt argparse doc docstring commandline' - ' argument option optional parameter positional' - ' console terminal command line CLI UI gui gooey', - test_suite='nose.collector', - tests_require=['nose', 'flake8', 'coverage'], -) +setup(use_scm_version=True, test_suite='nose.collector') diff --git a/tox.ini b/tox.ini index e389850..75f3686 100644 --- a/tox.ini +++ b/tox.ini @@ -5,14 +5,14 @@ [tox] # deprecation warning: py{26,32,33,34} -envlist = py{26,27,33,34,35,36,37,py,py3}, flake8, setup.py +envlist = py{26,27,33,34,35,36,37,38,39,py,py3}, flake8, setup.py +isolated_build = True [core] deps = nose argparse -commands = - nosetests -d -v argopt/ +commands = nosetests -d -v argopt/ [coverage] deps = @@ -34,7 +34,7 @@ commands = codecov [testenv] -passenv = CI TRAVIS TRAVIS_* +passenv = CI TOXENV CODECOV_* COVERALLS_* deps = {[extra]deps} commands = {[extra]commands} @@ -52,8 +52,7 @@ commands = [testenv:flake8] deps = flake8 -commands = - flake8 -j 8 --count --statistics . +commands = flake8 -j 8 --count --statistics . [testenv:setup.py] deps = @@ -61,5 +60,5 @@ deps = pygments py-make>=0.1.0 commands = - python setup.py check --restructuredtext --metadata --strict - python setup.py make none + {envpython} setup.py check --restructuredtext --metadata --strict + {envpython} setup.py make none