From ededf00035e6ccfac78946213009c1ecd7c110a9 Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Fri, 7 Jan 2022 11:46:51 +0000 Subject: [PATCH 01/76] Initial structure --- .gitattributes | 1 + .github/pages/index.html | 9 + .github/workflows/code.yml | 112 ++++++++++++ .github/workflows/docs.yml | 46 +++++ .gitignore | 65 +++++++ .gitlab-ci.yml | 4 + .gitremotes | 1 + .pre-commit-config.yaml | 31 ++++ .vscode/extensions.json | 7 + .vscode/launch.json | 23 +++ .vscode/settings.json | 16 ++ .vscode/tasks.json | 16 ++ CONTRIBUTING.rst | 102 +++++++++++ LICENSE | 201 ++++++++++++++++++++++ Pipfile | 17 ++ README.rst | 55 ++++++ docs/_static/theme_overrides.css | 34 ++++ docs/conf.py | 117 +++++++++++++ docs/explanations.rst | 11 ++ docs/explanations/why-is-something-so.rst | 7 + docs/how-to.rst | 11 ++ docs/how-to/accomplish-a-task.rst | 7 + docs/images/dls-favicon.ico | Bin 0 -> 99678 bytes docs/images/dls-logo.svg | 11 ++ docs/index.rst | 48 ++++++ docs/reference.rst | 18 ++ docs/reference/api.rst | 24 +++ docs/reference/contributing.rst | 1 + docs/tutorials.rst | 11 ++ docs/tutorials/installation.rst | 48 ++++++ pyproject.toml | 6 + setup.cfg | 84 +++++++++ setup.py | 13 ++ src/dls_python3_skeleton/__init__.py | 6 + src/dls_python3_skeleton/__main__.py | 20 +++ src/dls_python3_skeleton/_version_git.py | 100 +++++++++++ src/dls_python3_skeleton/hello.py | 41 +++++ tests/test_boilerplate_removed.py | 79 +++++++++ tests/test_dls_python3_skeleton.py | 28 +++ 39 files changed, 1431 insertions(+) create mode 100644 .gitattributes create mode 100644 .github/pages/index.html create mode 100644 .github/workflows/code.yml create mode 100644 .github/workflows/docs.yml create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 .gitremotes create mode 100644 .pre-commit-config.yaml create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 CONTRIBUTING.rst create mode 100644 LICENSE create mode 100644 Pipfile create mode 100644 README.rst create mode 100644 docs/_static/theme_overrides.css create mode 100644 docs/conf.py create mode 100644 docs/explanations.rst create mode 100644 docs/explanations/why-is-something-so.rst create mode 100644 docs/how-to.rst create mode 100644 docs/how-to/accomplish-a-task.rst create mode 100644 docs/images/dls-favicon.ico create mode 100644 docs/images/dls-logo.svg create mode 100644 docs/index.rst create mode 100644 docs/reference.rst create mode 100644 docs/reference/api.rst create mode 100644 docs/reference/contributing.rst create mode 100644 docs/tutorials.rst create mode 100644 docs/tutorials/installation.rst create mode 100644 pyproject.toml create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 src/dls_python3_skeleton/__init__.py create mode 100644 src/dls_python3_skeleton/__main__.py create mode 100644 src/dls_python3_skeleton/_version_git.py create mode 100644 src/dls_python3_skeleton/hello.py create mode 100644 tests/test_boilerplate_removed.py create mode 100644 tests/test_dls_python3_skeleton.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..075748c47 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/*/_version_git.py export-subst diff --git a/.github/pages/index.html b/.github/pages/index.html new file mode 100644 index 000000000..cc33127d4 --- /dev/null +++ b/.github/pages/index.html @@ -0,0 +1,9 @@ + + + + Redirecting to master branch + + + + + diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml new file mode 100644 index 000000000..62b51616c --- /dev/null +++ b/.github/workflows/code.yml @@ -0,0 +1,112 @@ +name: Code CI + +on: + push: + branches: + # Restricting to these branches and tags stops duplicate jobs on internal + # PRs but stops CI running on internal branches without a PR. Delete the + # next 5 lines to restore the original behaviour + - master + - main + tags: + - "*" + pull_request: + schedule: + # Run every Monday at 8am to check latest versions of dependencies + - cron: '0 8 * * MON' + +jobs: + lint: + runs-on: "ubuntu-latest" + steps: + - name: Run black, flake8, mypy + uses: dls-controls/pipenv-run-action@v1 + with: + pipenv-run: lint + + wheel: + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Create Sdist and Wheel + # Set SOURCE_DATE_EPOCH from git commit for reproducible build + # https://reproducible-builds.org/ + # Set group writable and umask to do the same to match inside DLS + run: | + chmod -R g+w . + umask 0002 + SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) pipx run build --sdist --wheel + + - name: Test cli works from the installed wheel + # Can remove the repository reference after https://github.com/pypa/pipx/pull/733 + run: pipx run --spec dist/*.whl ${GITHUB_REPOSITORY##*/} --version + + - name: Upload Wheel and Sdist as artifacts + uses: actions/upload-artifact@v2 + with: + name: dist + path: dist/* + + test: + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest"] # can add windows-latest, macos-latest + python: ["3.7", "3.8", "3.9"] + pipenv: ["skip-lock"] + + include: + # Add an extra Python3.7 runner to use the lockfile + - os: "ubuntu-latest" + python: "3.7" + pipenv: "deploy" + + runs-on: ${{ matrix.os }} + env: + # https://github.com/pytest-dev/pytest/issues/2042 + PY_IGNORE_IMPORTMISMATCH: "1" + + steps: + - name: Setup repo and test + uses: dls-controls/pipenv-run-action@v1 + with: + python-version: ${{ matrix.python }} + pipenv-install: --dev --${{ matrix.pipenv }} + allow-editable-installs: ${{ matrix.pipenv == 'deploy' }} + pipenv-run: tests + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v2 + with: + name: ${{ matrix.python }}/${{ matrix.os }}/${{ matrix.pipenv }} + files: cov.xml + + release: + needs: [lint, wheel, test] + runs-on: ubuntu-latest + # upload to PyPI and make a release on every tag + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + steps: + - uses: actions/download-artifact@v2 + with: + name: dist + path: dist + + - name: Github Release + # We pin to the SHA, not the tag, for security reasons. + # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions + uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14 + with: + files: dist/* + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish to PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.pypi_token }} + run: pipx run twine upload dist/* diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..e3b8fc903 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,46 @@ +name: Docs CI + +on: + push: + branches: + # Add more branches here to publish docs from other branches + - master + - main + tags: + - "*" + pull_request: + +jobs: + docs: + runs-on: ubuntu-latest + + steps: + - name: Avoid git conflicts when tag and branch pushed at same time + if: startsWith(github.ref, 'refs/tags') + run: sleep 60 + + - name: Install Packages + # Can delete this if you don't use graphviz in your docs + run: sudo apt-get install graphviz + + - name: Build docs + uses: dls-controls/pipenv-run-action@v1 + with: + pipenv-run: docs + + - name: Move to versioned directory + # e.g. master or 0.1.2 + run: mv build/html ".github/pages/${GITHUB_REF##*/}" + + - name: Write versions.txt + run: pipenv run sphinx_rtd_theme_github_versions .github/pages + + - name: Publish Docs to gh-pages + if: github.event_name == 'push' + # We pin to the SHA, not the tag, for security reasons. + # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions + uses: peaceiris/actions-gh-pages@068dc23d9710f1ba62e86896f84735d869951305 # v3.8.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: .github/pages + keep_files: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..0ce69d995 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +cov.xml +.pytest_cache/ +.mypy_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# DLS build dir and virtual environment +/prefix/ +/venv/ +/lightweight-venv/ +/installed.files diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..1efd50249 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,4 @@ +include: + - project: 'controls/reports/ci_templates' + ref: master + file: 'python3/dls_py3_template.yml' diff --git a/.gitremotes b/.gitremotes new file mode 100644 index 000000000..3d3f03492 --- /dev/null +++ b/.gitremotes @@ -0,0 +1 @@ +github git@github.com:dls-controls/dls-python3-skeleton.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..23a81d4e8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,31 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-added-large-files + - id: check-yaml + - id: check-merge-conflict + + - repo: local + hooks: + - id: black + name: Run black + stages: [commit] + language: system + entry: pipenv run black --check --diff + types: [python] + + - id: flake8 + name: Run flake8 + stages: [commit] + language: system + entry: pipenv run flake8 + types: [python] + exclude: setup.py + + - id: mypy + name: Run mypy + stages: [commit] + language: system + entry: pipenv run mypy src tests + pass_filenames: false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..734f215e6 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "ms-python.vscode-pylance", + "ms-python.python", + "ryanluker.vscode-coverage-gutters" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..1d960dc9e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Unit Test", + "type": "python", + "request": "launch", + "justMyCode": false, + "program": "${file}", + "purpose": ["debug-test"], + "console": "integratedTerminal", + "env": { + // The default config in setup.cfg's "[tool:pytest]" adds coverage. + // Cannot have coverage and debugging at the same time. + // https://github.com/microsoft/vscode-python/issues/693 + "PYTEST_ADDOPTS": "--no-cov" + }, + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..192c474eb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "editor.defaultFormatter": "ms-python.python", + "python.linting.pylintEnabled": false, + "python.linting.flake8Enabled": true, + "python.linting.mypyEnabled": true, + "python.linting.enabled": true, + "python.testing.pytestArgs": [], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "python.formatting.provider": "black", + "python.languageServer": "Pylance", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": true + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..ff78a11b7 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,16 @@ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "Tests with coverage", + "command": "pipenv run tests", + "options": { + "cwd": "${workspaceRoot}" + }, + "problemMatcher": [], + } + ] +} \ No newline at end of file diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 000000000..eba66b594 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,102 @@ +Contributing +============ + +Contributions and issues are most welcome! All issues and pull requests are +handled through GitHub_. Also, please check for any existing issues before +filing a new one. If you have a great idea but it involves big changes, please +file a ticket before making a pull request! We want to make sure you don't spend +your time coding something that might not fit the scope of the project. + +.. _GitHub: https://github.com/dls-controls/dls-python3-skeleton/issues + +Running the tests +----------------- + +To get the source source code and run the unit tests, run:: + + $ git clone git://github.com/dls-controls/dls-python3-skeleton.git + $ cd dls-python3-skeleton + $ pipenv install --dev + $ pipenv run tests + +While 100% code coverage does not make a library bug-free, it significantly +reduces the number of easily caught bugs! Please make sure coverage remains the +same or is improved by a pull request! + +Code Styling +------------ + +The code in this repository conforms to standards set by the following tools: + +- black_ for code formatting +- flake8_ for style checks +- isort_ for import ordering +- mypy_ for static type checking + +These checks will be run by pre-commit_. You can either choose to run these +tests on all files tracked by git:: + + $ pipenv run lint + +Or you can install a pre-commit hook that will run each time you do a ``git +commit`` on just the files that have changed:: + + $ pipenv run pre-commit install + +.. _black: https://github.com/psf/black +.. _flake8: http://flake8.pycqa.org/en/latest/ +.. _isort: https://github.com/timothycrosley/isort +.. _mypy: https://github.com/python/mypy +.. _pre-commit: https://pre-commit.com/ + +Documentation +------------- + +Documentation is contained in the ``docs`` directory and extracted from +docstrings of the API. + +Docs follow the underlining convention:: + + Headling 1 (page title) + ======================= + + Heading 2 + --------- + + Heading 3 + ~~~~~~~~~ + +You can build the docs from the project directory by running:: + + $ pipenv run docs + $ firefox build/html/index.html + +Release Process +--------------- + +To make a new release, please follow this checklist: + +- Choose a new PEP440 compliant release number +- Git tag the version +- Push to GitHub and the actions will make a release on pypi +- Push to internal gitlab and do a dls-release.py of the tag +- Check and edit for clarity the autogenerated GitHub release_ + +.. _release: https://dls-controls.github.io/dls-python3-skeleton/releases + +Updating the tools +------------------ + +This module is merged with the dls-python3-skeleton_. This is a generic +Python project structure which provides a means to keep tools and +techniques in sync between multiple Python projects. To update to the +latest version of the skeleton, run:: + + $ git pull https://github.com/dls-controls/dls-python3-skeleton skeleton + +Any merge conflicts will indicate an area where something has changed that +conflicts with the setup of the current module. Check the `closed pull requests +`_ +of the skeleton module for more details. + +.. _dls-python3-skeleton: https://dls-controls.github.io/dls-python3-skeleton diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Pipfile b/Pipfile new file mode 100644 index 000000000..d1ebb0d94 --- /dev/null +++ b/Pipfile @@ -0,0 +1,17 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] +dls_python3_skeleton = {editable = true, extras = ["dev"], path = "."} + +[packages] +dls_python3_skeleton = {editable = true, path = "."} + +[scripts] +lint = "pre-commit run --all-files --show-diff-on-failure --color=always -v" +tests = "pytest" +docs = "sphinx-build -EWT --keep-going docs build/html" +# Delete any files that git ignore hides from us +gitclean = "git clean -fdX" diff --git a/README.rst b/README.rst new file mode 100644 index 000000000..9b99e2cb4 --- /dev/null +++ b/README.rst @@ -0,0 +1,55 @@ +dls-python3-skeleton +=========================== + +|code_ci| |docs_ci| |coverage| |pypi_version| |license| + +This is where you should write a short paragraph that describes what your module does, +how it does it, and why people should use it. + +============== ============================================================== +PyPI ``pip install dls_python3_skeleton`` +Source code https://github.com/dls-controls/dls-python3-skeleton +Documentation https://dls-controls.github.io/dls-python3-skeleton +Releases https://github.com/dls-controls/dls-python3-skeleton/releases +============== ============================================================== + +This is where you should put some images or code snippets that illustrate +some relevant examples. If it is a library then you might put some +introductory code here: + +.. code:: python + + from dls_python3_skeleton.hello import HelloClass + + hello = HelloClass("me") + print(hello.format_greeting()) + +Or if it is a commandline tool then you might put some example commands here:: + + dls-python3-skeleton person --times=2 + +.. |code_ci| image:: https://github.com/dls-controls/dls-python3-skeleton/workflows/Code%20CI/badge.svg?branch=master + :target: https://github.com/dls-controls/dls-python3-skeleton/actions?query=workflow%3A%22Code+CI%22 + :alt: Code CI + +.. |docs_ci| image:: https://github.com/dls-controls/dls-python3-skeleton/workflows/Docs%20CI/badge.svg?branch=master + :target: https://github.com/dls-controls/dls-python3-skeleton/actions?query=workflow%3A%22Docs+CI%22 + :alt: Docs CI + +.. |coverage| image:: https://codecov.io/gh/dls-controls/dls-python3-skeleton/branch/master/graph/badge.svg + :target: https://codecov.io/gh/dls-controls/dls-python3-skeleton + :alt: Test Coverage + +.. |pypi_version| image:: https://img.shields.io/pypi/v/dls_python3_skeleton.svg + :target: https://pypi.org/project/dls_python3_skeleton + :alt: Latest PyPI version + +.. |license| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg + :target: https://opensource.org/licenses/Apache-2.0 + :alt: Apache License + +.. + Anything below this line is used when viewing README.rst and will be replaced + when included in index.rst + +See https://dls-controls.github.io/dls-python3-skeleton for more detailed documentation. diff --git a/docs/_static/theme_overrides.css b/docs/_static/theme_overrides.css new file mode 100644 index 000000000..5fd9b7214 --- /dev/null +++ b/docs/_static/theme_overrides.css @@ -0,0 +1,34 @@ +/* override table width restrictions */ +@media screen and (min-width: 639px) { + .wy-table-responsive table td { + /* !important prevents the common CSS stylesheets from + overriding this as on RTD they are loaded after this stylesheet */ + white-space: normal !important; + } +} + +/* override table padding */ +.rst-content table.docutils th, .rst-content table.docutils td { + padding: 4px 6px; +} + +/* Add two-column option */ +@media only screen and (min-width: 1000px) { + .columns { + padding-left: 10px; + padding-right: 10px; + float: left; + width: 50%; + min-height: 145px; + } +} + +.endcolumns { + clear: both +} + +/* Hide toctrees within columns and captions from all toctrees. + This is what makes the include trick in index.rst work */ +.columns .toctree-wrapper, .toctree-wrapper .caption-text { + display: none; +} diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 000000000..f2ca6a2d4 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,117 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import dls_python3_skeleton + +# -- General configuration ------------------------------------------------ + +# General information about the project. +project = "dls-python3-skeleton" + +# The full version, including alpha/beta/rc tags. +release = dls_python3_skeleton.__version__ + +# The short X.Y version. +if "+" in release: + # Not on a tag + version = "master" +else: + version = release + +extensions = [ + # Use this for generating API docs + "sphinx.ext.autodoc", + # This can parse google style docstrings + "sphinx.ext.napoleon", + # For linking to external sphinx documentation + "sphinx.ext.intersphinx", + # Add links to source code in API docs + "sphinx.ext.viewcode", + # Adds the inheritance-diagram generation directive + "sphinx.ext.inheritance_diagram", +] + +# If true, Sphinx will warn about all references where the target cannot +# be found. +nitpicky = True + +# A list of (type, target) tuples (by default empty) that should be ignored when +# generating warnings in "nitpicky mode". Note that type should include the +# domain name if present. Example entries would be ('py:func', 'int') or +# ('envvar', 'LD_LIBRARY_PATH'). +nitpick_ignore = [("py:func", "int")] + +# Both the class’ and the __init__ method’s docstring are concatenated and +# inserted into the main body of the autoclass directive +autoclass_content = "both" + +# Order the members by the order they appear in the source code +autodoc_member_order = "bysource" + +# Don't inherit docstrings from baseclasses +autodoc_inherit_docstrings = False + +# Output graphviz directive produced images in a scalable format +graphviz_output_format = "svg" + +# The name of a reST role (builtin or Sphinx extension) to use as the default +# role, that is, for text marked up `like this` +default_role = "any" + +# The suffix of source filenames. +source_suffix = ".rst" + +# The master toctree document. +master_doc = "index" + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# These patterns also affect html_static_path and html_extra_path +exclude_patterns = ["_build"] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# This means you can link things like `str` and `asyncio` to the relevant +# docs in the python documentation. +intersphinx_mapping = dict(python=("https://docs.python.org/3/", None)) + +# A dictionary of graphviz graph attributes for inheritance diagrams. +inheritance_graph_attrs = dict(rankdir="TB") + +# Common links that should be available on every page +rst_epilog = """ +.. _Diamond Light Source: + http://www.diamond.ac.uk +""" + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme_github_versions" + +# Options for the sphinx rtd theme, use DLS blue +html_theme_options = dict(style_nav_header_background="rgb(7, 43, 93)") + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +html_show_sphinx = False + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +html_show_copyright = False + +# Add some CSS classes for columns and other tweaks in a custom css file +html_css_files = ["theme_overrides.css"] + +# Logo +html_logo = "images/dls-logo.svg" +html_favicon = "images/dls-favicon.ico" diff --git a/docs/explanations.rst b/docs/explanations.rst new file mode 100644 index 000000000..39de4e6be --- /dev/null +++ b/docs/explanations.rst @@ -0,0 +1,11 @@ +:orphan: + +Explanations +============ + +Explanation of how the library works and why it works that way. + +.. toctree:: + :caption: Explanations + + explanations/why-is-something-so diff --git a/docs/explanations/why-is-something-so.rst b/docs/explanations/why-is-something-so.rst new file mode 100644 index 000000000..21708377e --- /dev/null +++ b/docs/explanations/why-is-something-so.rst @@ -0,0 +1,7 @@ +Why is something the way it is +============================== + +Often, reading the code will not explain *why* it is written that way. These +explanations should be grouped together in articles here. They might include +history of dls-python3-skeleton, architectural decisions, or the +real world tests that influenced the design of dls-python3-skeleton. diff --git a/docs/how-to.rst b/docs/how-to.rst new file mode 100644 index 000000000..86b2ddbd4 --- /dev/null +++ b/docs/how-to.rst @@ -0,0 +1,11 @@ +:orphan: + +How-to Guides +============= + +Practical step-by-step guides for the more experienced user. + +.. toctree:: + :caption: How-to Guides + + how-to/accomplish-a-task diff --git a/docs/how-to/accomplish-a-task.rst b/docs/how-to/accomplish-a-task.rst new file mode 100644 index 000000000..8ee493904 --- /dev/null +++ b/docs/how-to/accomplish-a-task.rst @@ -0,0 +1,7 @@ +How to accomplish a task +======================== + +Here you would explain how to use dls-python3-skeleton to accomplish +a particular task. It doesn't have to be an exhaustive guide like the tutorials, +just enough information to show someone who knows what they want to do, how to +accomplish that task. diff --git a/docs/images/dls-favicon.ico b/docs/images/dls-favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9a11f508ef8aed28f14c5ce0d8408e1ec8b614a1 GIT binary patch literal 99678 zcmeI537lO;m4{y-5^&fxAd7U62#m-odom^>E-11%hzcU;%qW8>qNAV!X%rBR1O<_G zlo>@u83#o{W)z#S%OZm8BQq&!G^+HP(&n3&@W+)-9$hLOTPl^tjT;RAocFi!Zm+$n;Ww8`pBh^#O`bd$ z-t~}DY10X%Qg3fHyy2+Q{%4m;y8?rxKpcFJm&pY|u-6wCRW5(cjPg@`tAm&CdMS9B z-%o#TQRNE0?HvbX^O@z1HkeVq^0H->N|}gPE~^Af__3Vl@}-qP@2*;2sSxMtEoPQq zYs1-$wB*q@dPX_;yP4(Sk(Y_=xW{?7G2ax2xYNn62IKezl`B5Buo8T2aYcCq3)VS_ z2|mxetNC`;i~d2h<| z1L0&p|I2sR_3;k8>*A623f?_wr#*T>B~WUWL3O6z&+%LSv3#@RlJ;qyHRj!$W|xB( zN%WHym4NyQ9$Hfg9(}nIY|8IzDf?2s?L21)2hy%J={F+IpH>IKr=B0mmvt^~WxsY|c^bETWshNJpW zo$@@vv!?nyiT?vrUORpeluB!QN~QiWrBdJegHP`$_({ZLzALWMD6RO+IG)Ko;$Mxr zZTricy>@2#IB>ms%#88_@SR08{a5sSWpQPZ-fcLue2wC4*IyQkE5reRJkK>V)&{E% z92jcH7t#KVy8@nOXuCIU{mHcfy&?D^&(3*~*uKBK5q)ne?R>4thi)5uo^}hZ1Mv;x z{>%rxJDI*_y$&v2R#^*-Y1_{p;)z-Cfk*5Fyhl_f>NJ@C(okN?Q~cX?FFL&S{xv}W zEy8*M*5Bamnd$?A*(yZ;*}=7!GXGstcPv-!+svtxk;n?+nIj;uKAVVKj4>H-SrGs?lGN^-$l0Z(cPHo;nGh{BdY^4mkch_3#He)3d}>zw>nrufYt`-Uf^x z0&5B|PXf01zW6tJ{!nG#y1%>$ZElsJPn55|eJW#CR`+Fi1pKhZlcHdf=jyHClkkUQ zqrSWEz7GCb-8AGnH+@u?ypIFV$T8NAe+YH9E_?Q&d~`VN--Z$Oo4l`~ZtsoyX5P_P zf_YX)5G(v8{mX6>bd}&2yt8G*7f2(%W#B~l|GM@^IHb8--!6QO3C11uTy*|QW9Sjp7Rc)X`oQHj?0=(Pqw3p^ zqu;wTwitIH@~r#a4T~OU)1K`2+ihDPm^AQF*-*m)ZOP**fh8%qAo4#;w8A1NQUC9Xpx)qI~4V-LvBGFZ5~6 zN8Eg(!oXaJejuDzN9Ak3Q$0{mskHb2d@pVuZsVXjPb;^bzkY8;d#JX_*nY9s+)ALi zyq%ZxdoBI!+wiIlUHDnU>YL&Z)ZZ{3#k){OaPrh#XC-N_BJKFB`J}}g3!fCP2JYq5 z=e;}&c-B-O{nooHh;uA)H%WtMzK1-#e@qbcjtVNJ(v)?j(xf$|QqR&-X|sM8#lYW9pmxw^n**Nr$3;l zcor0v@`QQ}{AF*QQ=Y-MKN9Cs;-1hmyS)8uDOB3zz-dcl%G0)-Rlc8gRntMK%}F2P zy7xM=meNp;2k%`Ie1W*HYgIAGYa5>L@vP)Q=NT{`t{k5!LhU6{s`YXJ3w<5~0 z`Kz;>I6s;&zf&peU<4Z8;5#mNRE)L1bNr^ ziwi#~Ou7djVE({*;?^1;lH$gF(|UQMPP*hc_$luzto?4!`1j$Ic#-h;g*Quw+^F*z z!(2SU{RHN87rF1#!WvVggD%R6w@A00maqFA+%Kga{oZ|_7QP-H5#@e|F!5E|gXS}? z({hLO#P<4z9p_fk!UMg^fX%>djLD%rN*d1QdsLej5BjV%Kb&gW02myvw&q_aF~5}T z<~rZL0PZt*78%^q{HQknEbVAN%YH#HPLAl;XFB~9S*vbMNoDcv3*f$j=cP2f^*yT1 zt1TcC4x_o&JzS?cck@B64}Qd$Xgi<20Pba;)h^tqu-)cOdlCPSikn4$VyAQ4Q`Wvv z#Xq(E*lk|zMRLELzxx~AlwGCa?>%WRZah2ewx=w80sNQqB=%ps&BwJD8xQ@4uMM+t zU_Cw&f2FhAQYAAGP@? z{t_48e*af%y;}0B{VmIH^razx(mGIF*`f0#jKOv5j0U#WI@Mn6`J4Hc#aF(@-N)Q1 zOBy$hX;0E~xZe~;2K^W^&{k3M+hLBrH7b45JKL`4*VIE&+_Y~oxKz-ih4V1l(OqdU ze7|e`%Q)K(&lgTyd~m+s$p6emPKk?`_q}uo#`Q+nG3147(t-2o27lR5(uV4EoF-mg zU;1d{Bv0gp6O|5JSJ8Ir)(q&&v3w{BM%uec=%tL4{wOWJ&v(hqrtXc8zFPfwnGc+# zxLVUN?tql>Ith;Z4IEdZBiz>DZTqyTFS_ybhS8yhHtZ^cw9MSBOgT-tse-T`YW31rt*8EKy_tFp4YY`A z>N%|V!Tn^D0ny9TY&$Koh;?t7Q{En35Jwcz#9P3rKS;a_0`QfIIX9I*C#A`-3U#GtG{o?b2|G@o|K(!L|MYJQI^=fDLW+S619$izU~?F_!3WB`KnEW zYPr9TFT2E=(>@gR2QEDW>EGg<_Ha1#5A|#jYdgz;aRE=;>VdWM_0R!+8vB6fz5=FGTAv(v!xyZ!W1U0*6zNTUdefw$8COJRUxEhoRLC=mF!L_F<_% zFusO;LUt^1PJ2{MJlW+)KON^3cT9EujI41ldsZ{eAsekF`0_`Q7wTj@tu-alNoCNU z#w=^IGoiPhB&WHz%PZhF(!ZS4X!+vObDqF@*osXxGwBhP#GD{TPZzTVC!>bKf#vz=^sqw==jf$NRz``a*2S=}@T&#P=eU;m8_ zKkhfOe~`or8m$|{AL8=2--Gk-_Z?`g4zPz_kGlN14L9w#c!AcXigt@5`g|HL)WMDK zou9uiAcuZCEsv=0K6`(&)>GcK8p?2q+orRG8CO3NRkpNulKW)uS+tAVkC}#x`A%6* z%2H+%hdJ<@C`Y0`Mtz-l?CBWXQ*{RVB-!BG>$64If%MMWJIwhV!Ewk@+DnBj5-V$) z@@s4a*G%%kM;DgYL!P)@bd>yhP_=xrbK$I>KzpYjW1oH#NSwR6w4}@#BH`Y~tH4pV zQpcm?n+WdMfQI$MJnCNdzop8F$QGYWJHIG5qHRj3`cd2AETmIR8;|lqZxfycZ9=mZ z+3F0O*f|r`bWSUfXlEXj@q#GY?>xJ_DSYz9x3W)N`=Dgo^lfYfbT-Pp2(~&$i?ki@ zgrjVH?gwYdV&7q{MY;p&%lBmeDe}p3)(W?D>wt0cG{Z0BeAY~Y-Kd}UF{jnpTRKxq zYf-8noh`;+)1Bmh&3|-;k@N!Er=vZ1+S|JaxFP?i%Ey%B47>cC%}|0rJ|0)@tnaDA zaBgCs|4~$hXs?BI2Re@}D?V}Ym}AfQ#KIw68a8bE#>LI^Ui1B;-DR}nJh;TAc|H0> z(*}@}FN}+q=Y2EeKkf05%#{b9s5F%MyQciKhex8~wwNO!R-+s}Ys%E!H_$ZrZ3bUIjyIW{+BS?{>OIcmd^K&69YRU{o3OF0RkJ z?cGh!94l5naL?PY(+D|d@<;V~o!=PM-t97&-%)$K)RM5Rifl6`oqY8N zSW2DCD;KEzzU@D%&x^muwRanL^E+y-OmdU?p5{mOhdjK1@~i#NNXyUu?)Le#_HL&& zzjd~$>!hDD-?R8p{Xw{7No(Rz_Ib#`nfF-OeLjxA8`w#H#Cm>kJ4(8wG;!awC&?Zk ze0Tw6e~2;gx;WVOd%Ms3ws#wjeqYL5)^*aOxbd=v?f&4y3nc#_|DBbVkKO0qfB*ZKFZbNA6^ffE(S^as(&mA%~f z)Y&oP=ak11FV@ae@_3Rw#=)e_Ppa&4@PPB<;x*&F)(u@J-E=eZii1g+rwx{# zvm5)%`^3d-#(QM0VYV{h(9-hLrVlpd=Y9(Hfx>ivS?WxCh>eptr1jP;>57O$S)XP- z1Z(Ia#~AmSB4B5Qq4gQ#^6X>Inom?b%KC3ZB_I67-iVE%LGHP5R6a@XZektXIISNg z#Vzt1Wn9X>!Oh+BD~vplDhm~bi`MCl)A?CN!A*lh8PAIAAWjQ+N@kwQN zzp>BygQPEHUCiKN`#RUuxc#XM`&-e!ndcnmmM=?~aq=5Q<6__;e+H%oTw87vrwAW@ zKkV%KEM-@mchXo;oPoKYjzkzIhKCVvC*N+Cy4N>?v`c8N1 z$*!nTI8o`r`8Vu6E9AUpY<{#yxA1nLJwgxXyAL9<&M5oOlg?9(qjl2zcgzcI!Nm^> z^e)Raav;X`}MU^iLoFkDF8COrF-gD0vbpDg>Me?P!iBH}Ok!k<=o%6~~ zYwu}wfgH23=8fRuJ$KgrHOT>{JXwA6dXYSP(O+(whF`0`b63*F(xEg{j|A+;$m2Bb zSm>B?yY-8WONskT_J*$KgYUyhy7dh7uBbkNbs;eKMMvyr*YRQ6#aOMeP=>SMnb%RC zJK90HRoXfo*vvo(EUDrOpWtX74 zL$W$?3V2NJ{B({V_ruHw%!NEV6ETOheH!Rh0DJV)@fO|R!kmZnFiF4W&A^4!joSb=;GoowoT z#sl5WuWEl^9=6RL754Yv%vpH5k+$jmtdla}jKK{#gXUcHqTyXgI`<~8(|Evoa3ZaAwvDe# zvt88vI4S%-G0UG-_eG#5UW?uERL(lwxRYqqEL^Z*pTL~C?hYgMqdYV+6`V94Xk5-g z{t$HB-me_|-k=)#(l6+)R-3=T$7Zs&|1J*CZC2H{748YoSH{rJFJvwjsjrdkyzU{* z>(s-qVa?s%ldL&>Bj@(%-dq=+?k38~@57?0Epmoo9qmm!kUoj_`hE7M{9Rj#RdD9q z<^E>$ruUn2#`(IV+nGCgHwWEKtb1+0k8GfR)~J&`zxGLK?%Cf!`!smyo~^j@oA>B7 zALUN^-3ul|%fZcnmtlW@G;5!kZB84J1xy`xs;@Dhb%a#mLx8JF)ASYjZ#-jXZowmHwlOeVu8?h#m zdakftR{OVPHr=m1Qk>Qk;>LWt+;P8IQ}`WcKXE_TmxS{dE%QTypTg{E2Y@EP;n^1ET?h)=^u z#&sIqh0nx+^0wetH?Mc`_YG^^t`WUJRvI-cp5`Aq7s$8VN%65k>ECy5rKL8}Y3+@( z^xptph0@;CfnUv>IYft0q()z*1Xoc z3zh`yp&R{KBl!EI)qMyur051$^qDtF^@L90X7*dP)GqlM^m^zerX=CjjBh$0z0;l6 zA#^uIGs+(a6B+5^sY_d@CqyrKgs)yN4)?6@wLbKUDz^)q?2WRPtB80SYp{Vop%tS5 z>k>Pmn|`qfytBg4I^HkPop+1Vx*_{VTG|G%rC7=O@gB`=14lhq*#JG%Jz43NH=gJ% z9;$VA?x74Gi#a2>liR~Q^w+(de}jEf0KW{FA2+={FeiBQu;t65+DUlirKOL9fG2znk3P-_6XAGmLI5c~&r3g^-`bYA8=xf_-> z(p>uu>^e2SS$FyVpH~(y3t$g_Ao{phOg>3Iyh!6wFp2)Feeh>PU)g4ezRy74h+~31 zYI0;omED8v3%El&(D@lUN9>pc>Vl;DBisk(tE!lGTz%s_o|pT0$K?B6^=;i>+ZK}usKHGew+5dYkr}5 z#(B&)evDi>9r;r85bc3@wQ+Pt~a8i zMjybMLZaQa^qJC2NIxMxh4dBDTink4RCb_2`_}cCqrMI zQJ}q#oLyR*`x_mN>!YuEkK51V!mKGbysj@Dp!AxYwH)d>rSFv9vkx7D^q{Zm0EcL< z{wsTT-G%&9=&Q3+b$0xFsXNwm0_odadisX3)A@ZIz3unhy}2!V-nG8)ed24qQf1P* zh}KF!L0Pp{axLxSPqYu+%OoAsNO985h`x71-|L|71y%aWPDJ;wp<8Xby^z-HS-aiE zrghYB)(_6|p=Gn;YJ5@q&^=w!J9eAXy{7*{yAJtt3+S7L4&04&Q54P1JJxE}qb)w0 z1y(ELXiwM=SRd>br*)84toQoT0G_+x6ARDrjqJN_W!pI@=8oi6 z)m2hHth;}}^mo^%jxS3}+wO1AcZvO9Gw(fVlm^Iw*SU08`1pmD(eQ_XM&UOrz2*|# zG6G;H)v&zYta`+DZ|RZP?YnJ2_8ra2vk17d59$`DdAjzl6;bYHz~DT@!(93!8#e7u zs7A}6{?u)YP_k)jwA{@~kACM;m;T88_cbfOM&N1=xTp)peU~>$|JiCg@T~RB+~ld7 ztaHn`XJ!ld)yrAaw<@0OfW=F@)#>b@?OMDSBnxe1BY5zhW_m7xTV$kC*_Cz za-ehEMvCi1SpXT}Zqc7QF7Z3}U3W=z%=1lSzSglvnv*QRp4pD!1Jv`1ud;6#`;M`! z$CdNYsu^jfjes#fuI+Y`ETA>meK?mBUOS-~bj$;@h%sOLPh|h1b0oEwrcw6@>v)>W z>n{60%c8nL*GaMfXDS?y9C%_LS{0q9(RsecSlO6p{4ls_-SCPA^oD<69nZGCP@j>l zg3nztZgY{X2lMS3jt19u_?+Ky8hXFpcI0j6+2}l9wr|>JYr{0ZS?>sz=9DFOk2$AV zHg!JtNx5yHQ)B_;{)>68GIiB1zmYLtcde)CSZ?&V`_0fw`;e3BLpD1)6FRSk;#Tk$ ze@e=u+27Cu-#|Hj)9ieb;7hlkrw+yMH6~}#t>n=oWxc;%``2~l(VR~zC2k=fLZyyi=%jjuRATn zJq>O?3Tr&@ogcJIFF>1J$r!LOsvOOH=R42$<@YY`;?KVBSnQ5nI9bDa#)Edq0`UG< zcv^avm+zRLMZQm?i_YTmH6hU1Q)zIMzWa^`?N}o~w^42-{e8xKBj4++sHA$%@=fzB z-!r8ex&PP3$!C7hYFR+^ZzccFI_4+obL_hH`K@znvO2Xr*_->oPm1fKFKVSMApXz% zxh4BOvX1$Z@6+@-Np&6fO?&IIx+RDU()Gr{%JZJO&OAS8l`J6n54@T_|I0Gw8-AZf zpOdHleeMC&y$yNt$dV?@co6CZ*jJqeUL$cBj|ZUtU5&s_&l+}Hi^#V72Gs8*af%-|a_7QMy$VHs#d_vJ>OB(Zw(C6gA zSNAVwbvm;+Pach=Ntz!tOBSH-e-8VvgBrm*Ds9x5-)esE;w4!sD+hRYj4g=^vl-#I z`GMA>i=G=%C-1}l^L5O1*A-QksCmBlz0MIUDvvyHkaaSjDHCV+lPBLiY2wC%B4q(+ zUcvq|yhji{;M_cTx@n^3`K^-gU0kBVYKLh~qXc7OTidE|H{*eg@1QJDOh00bUdH{Z z>uV1HbAX$o>dWUH`^xL=_6@&pw~dos2Hne&=CpRJve@a``P-cz%wr*|hWeJ?`Y6o zB2V7FX+DEZSDMo~bG~p}9badHicj5#Jd-DH#{S2CcNw)BuRQrluGaladDf}X`_{&O!vi>9>uq`P=%zFW(^k{mr&uTGrZVNhl`(tR zoe&>dP+1>6Kz|;1-I7M<3Zyyi%^K14XKuUbkolD{rr+B>bAs=73oY~D$zHcWa#NDq zFQ-hE2cLGNVIFa_G<{bT=j;MA%-HD;!rA=>J@yIWOulMiP-#ohyed^8GKuIct* z2A6jDe@ob>r8^0_MV8G|ce3|7;oa~PC$kW|YcExLNQ2z>>nK`By+aqU7kseX4dwF1@rwz2!F9*6FT8GuueE;UzR6Lvj(XQSE6|$o z&D~HoUmTB1*b9EX=bmrhyxSEY-TvKYEGc{41IwD=1ht!X;oPiz51ALw|38~^&v&zM zEefveyrTMf(z~;lj!Yh)`y4mf;{+jN}BgYoCo=(7Vr5kx-O9Sm!PlNxlm%q07IX6DC5j4MVFyf@b-?_3og6* zR^?xGKGO5BC+veUJ>*mW?T&kswHJJ52k!Y!svl_oBHidPn6ce$*{v!Pl+5;Q!U(d%jKk6VGSwZ%6few;k+1x4a2* zNypm`o?`6Qp`9LDpVyoekTGbeCR_J36NvpVNM?Xqx7MCtWf2LmjtXzbk2T5F@zL^8DmH1`vX#m4AM z%on=uOe*C0XTbeyd$ND7C6zUTGdY@b$&eBD)48RrfpzQ|mEbl2j+fEbC%$KXdu*~s za5D&t_Cd}mWqf!W>r3ar7w&|=wrx)m`kI%es{@yB&^`}@=80#kjda?yqkIQ*c0F?A zyXbdkGtS-w-<^xBRrq{TFzMg(C7+U4FY6kI9XL?lq8(*^HP7T4VEuVZc<_O&Kc2uC zd=~Sq%Xw}TzrcSCp79LrWC7vDgcs{K@1EuN<2-ls{@3_dl6DGusuO$q%M&KfE00ai zwL8C>HSl_WU8yw5e$!hjjk3aPRMwuM7kvt^KNME5RH}u6CO65vSUMOUW5Rud;TnL! zU=2Vuc@03AyW;c=0_ZpKs{s2gaRpa#C0K@EI0gDSQHvYF!d*T9v+ z4Eu({VTQd!;jqqzf?`SF7EI`=bC)J@7B4nWxB4nWxBIJhqZFnHqXNN)14fopL zLD&u3pH+bR@RU0ADUcJMWYw-x4hz>6j{>^ky5dpbv~Yhteq(&Yef8Ob9ufIP3F}~rn_UC?g+p`-^>mN>ka{Jd5w?8`J;r+SSt^oRbpB;|i5B>Ic z_(@#>VTf+Hu7Ewm`B`0oT>eM6t^fpWh7|Hs3*nI8S_p>x*g`1e*A_xOf@jtEB!w-6 zrYJm=VVIp&Lt%E-01##u1hou$!sJ64Od1T=N>mM+DzAd8Rbhy&;#4u5Wa3u=)PjQm ZYRRh@^bCDh5vs@!z69bV>$COq{{Z);QUw42 literal 0 HcmV?d00001 diff --git a/docs/images/dls-logo.svg b/docs/images/dls-logo.svg new file mode 100644 index 000000000..79ba266fd --- /dev/null +++ b/docs/images/dls-logo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 000000000..9bde8adfb --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,48 @@ +.. include:: ../README.rst + :end-before: when included in index.rst + + +How the documentation is structured +----------------------------------- + +Documentation is split into four categories, also accessible from links in the +side-bar. + +.. rst-class:: columns + +`tutorials` +~~~~~~~~~~~ + +.. include:: tutorials.rst + :start-after: ========= + +.. rst-class:: columns + +`how-to` +~~~~~~~~ + +.. include:: how-to.rst + :start-after: ============= + +.. rst-class:: columns + +`explanations` +~~~~~~~~~~~~~~ + +.. include:: explanations.rst + :start-after: ============ + +.. rst-class:: columns + +`reference` +~~~~~~~~~~~ + +.. include:: reference.rst + :start-after: ========= + +.. rst-class:: endcolumns + +About the documentation +~~~~~~~~~~~~~~~~~~~~~~~ + +`Why is the documentation structured this way? `_ diff --git a/docs/reference.rst b/docs/reference.rst new file mode 100644 index 000000000..3f01ee357 --- /dev/null +++ b/docs/reference.rst @@ -0,0 +1,18 @@ +:orphan: + +Reference +========= + +Practical step-by-step guides for the more experienced user. + +.. toctree:: + :caption: Reference + + reference/api + reference/contributing + Releases + Index + +.. + Index link above is a hack to make genindex.html a relative link + https://stackoverflow.com/a/31820846 diff --git a/docs/reference/api.rst b/docs/reference/api.rst new file mode 100644 index 000000000..06bf3c66b --- /dev/null +++ b/docs/reference/api.rst @@ -0,0 +1,24 @@ +API +=== + +.. automodule:: dls_python3_skeleton + + ``dls_python3_skeleton`` + ----------------------------------- + +This is the internal API reference for dls_python3_skeleton + +You can mix verbose text with docstring and signature extraction by +using ``autoclass`` and ``autofunction`` directives instead of +``automodule`` below. + +.. data:: dls_python3_skeleton.__version__ + :type: str + + Version number as calculated by https://github.com/dls-controls/versiongit + +.. automodule:: dls_python3_skeleton.hello + :members: + + ``dls_python3_skeleton.hello`` + ----------------------------------------- diff --git a/docs/reference/contributing.rst b/docs/reference/contributing.rst new file mode 100644 index 000000000..ac7b6bcf3 --- /dev/null +++ b/docs/reference/contributing.rst @@ -0,0 +1 @@ +.. include:: ../../CONTRIBUTING.rst diff --git a/docs/tutorials.rst b/docs/tutorials.rst new file mode 100644 index 000000000..dfdef509c --- /dev/null +++ b/docs/tutorials.rst @@ -0,0 +1,11 @@ +:orphan: + +Tutorials +========= + +Tutorials for installation, library and commandline usage. New users start here. + +.. toctree:: + :caption: Tutorials + + tutorials/installation diff --git a/docs/tutorials/installation.rst b/docs/tutorials/installation.rst new file mode 100644 index 000000000..d23580a3e --- /dev/null +++ b/docs/tutorials/installation.rst @@ -0,0 +1,48 @@ +Installation +============ + +.. note:: + + For installation inside DLS, please see the internal documentation on + ``dls-python3`` and ``pipenv``. Although these instructions will work + inside DLS, they are intended for external use. + + If you want to contribute to the library itself, please follow + the `../reference/contributing` instructions. + + +Check your version of python +---------------------------- + +You will need python 3.7 or later. You can check your version of python by +typing into a terminal:: + + python3 --version + + +Create a virtual environment +---------------------------- + +It is recommended that you install into a “virtual environment” so this +installation will not interfere with any existing Python software:: + + python3 -m venv /path/to/venv + source /path/to/venv/bin/activate + + +Installing the library +---------------------- + +You can now use ``pip`` to install the library:: + + python3 -m pip install dls_python3_skeleton + +If you require a feature that is not currently released you can also install +from github:: + + python3 -m pip install git+git://github.com/dls-controls/dls-python3-skeleton.git + +The library should now be installed and the commandline interface on your path. +You can check the version that has been installed by typing:: + + dls-python3-skeleton --version diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..ccd70c768 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +# To get a reproducible wheel, wheel must be pinned to the same version as in +# dls-python3, and setuptools must produce the same dist-info. Cap setuptools +# to the last version that didn't add License-File to METADATA +requires = ["setuptools<57", "wheel==0.33.1"] +build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000..167860a5d --- /dev/null +++ b/setup.cfg @@ -0,0 +1,84 @@ +[metadata] +name = dls_python3_skeleton +description = One line description of your module +url = https://github.com/dls-controls/dls-python3-skeleton +author = Firstname Lastname +author_email = email@address.com +license = Apache License 2.0 +long_description = file: README.rst +long_description_content_type = text/x-rst +classifiers = + Development Status :: 4 - Beta + License :: OSI Approved :: Apache Software License + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + +[options] +python_requires = >=3.7 +packages = find: +package_dir = + =src +# Specify any package dependencies below. +# install_requires = +# numpy +# scipy + +[options.extras_require] +# For development tests/docs +dev = + black==21.9b0 + isort>5.0 + pytest-cov + mypy + flake8-isort + sphinx-rtd-theme-github-versions + pre-commit + +[options.packages.find] +where = src + +# Specify any package data to be included in the wheel below. +# [options.package_data] +# dls_python3_skeleton = +# subpackage/*.yaml + +[options.entry_points] +# Include a command line script +console_scripts = + dls-python3-skeleton = dls_python3_skeleton.__main__:main + +[mypy] +# Ignore missing stubs for modules we use +ignore_missing_imports = True + +[isort] +profile=black +float_to_top=true +skip=setup.py,conf.py,build + +[flake8] +# Make flake8 respect black's line length (default 88), +max-line-length = 88 +extend-ignore = + E203, # See https://github.com/PyCQA/pycodestyle/issues/373 + F811, # support typing.overload decorator + +[tool:pytest] +# Run pytest with all our checkers, and don't spam us with massive tracebacks on error +addopts = + --tb=native -vv --doctest-modules --doctest-glob="*.rst" + --cov=dls_python3_skeleton --cov-report term --cov-report xml:cov.xml +# https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings +filterwarnings = error + +[coverage:run] +# This is covered in the versiongit test suite so exclude it here +omit = */_version_git.py +data_file = /tmp/dls_python3_skeleton.coverage + +[coverage:paths] +# Tests are run from installed location, map back to the src directory +source = + src + **/site-packages/ diff --git a/setup.py b/setup.py new file mode 100644 index 000000000..39de827e9 --- /dev/null +++ b/setup.py @@ -0,0 +1,13 @@ +# type: ignore +import glob +import importlib.util + +from setuptools import setup + +# Import ._version_git.py without importing +path = glob.glob(__file__.replace("setup.py", "src/*/_version_git.py"))[0] +spec = importlib.util.spec_from_file_location("_version_git", path) +vg = importlib.util.module_from_spec(spec) +spec.loader.exec_module(vg) + +setup(cmdclass=vg.get_cmdclass(), version=vg.__version__) diff --git a/src/dls_python3_skeleton/__init__.py b/src/dls_python3_skeleton/__init__.py new file mode 100644 index 000000000..25eb98fa3 --- /dev/null +++ b/src/dls_python3_skeleton/__init__.py @@ -0,0 +1,6 @@ +from . import hello +from ._version_git import __version__ + +# __all__ defines the public API for the package. +# Each module also defines its own __all__. +__all__ = ["__version__", "hello"] diff --git a/src/dls_python3_skeleton/__main__.py b/src/dls_python3_skeleton/__main__.py new file mode 100644 index 000000000..960eff10f --- /dev/null +++ b/src/dls_python3_skeleton/__main__.py @@ -0,0 +1,20 @@ +from argparse import ArgumentParser + +from . import __version__ +from .hello import HelloClass, say_hello_lots + +__all__ = ["main"] + + +def main(args=None): + parser = ArgumentParser() + parser.add_argument("--version", action="version", version=__version__) + parser.add_argument("name", help="Name of the person to greet") + parser.add_argument("--times", type=int, default=5, help="Number of times to greet") + args = parser.parse_args(args) + say_hello_lots(HelloClass(args.name), args.times) + + +# test with: pipenv run python -m dls_python3_skeleton +if __name__ == "__main__": + main() diff --git a/src/dls_python3_skeleton/_version_git.py b/src/dls_python3_skeleton/_version_git.py new file mode 100644 index 000000000..bb7f0c2a5 --- /dev/null +++ b/src/dls_python3_skeleton/_version_git.py @@ -0,0 +1,100 @@ +# Compute a version number from a git repo or archive + +# This file is released into the public domain. Generated by: +# versiongit-2.1 (https://github.com/dls-controls/versiongit) +import re +import sys +from pathlib import Path +from subprocess import STDOUT, CalledProcessError, check_output + +# These will be filled in if git archive is run or by setup.py cmdclasses +GIT_REFS = "$Format:%D$" +GIT_SHA1 = "$Format:%h$" + +# Git describe gives us sha1, last version-like tag, and commits since then +CMD = "git describe --tags --dirty --always --long --match=[0-9]*[-.][0-9]*" + + +def get_version_from_git(path=None): + """Try to parse version from git describe, fallback to git archive tags.""" + tag, plus, suffix = "0.0", "untagged", "" + if not GIT_SHA1.startswith("$"): + # git archive or the cmdclasses below have filled in these strings + sha1 = GIT_SHA1 + for ref_name in GIT_REFS.split(", "): + if ref_name.startswith("tag: "): + # git from 1.8.3 onwards labels archive tags "tag: TAGNAME" + tag, plus = ref_name[5:], "0" + else: + if path is None: + # If no path to git repo, choose the directory this file is in + path = Path(__file__).absolute().parent + # output is TAG-NUM-gHEX[-dirty] or HEX[-dirty] + try: + cmd_out = check_output(CMD.split(), stderr=STDOUT, cwd=path) + except Exception as e: + sys.stderr.write("%s: %s\n" % (type(e).__name__, str(e))) + if isinstance(e, CalledProcessError): + sys.stderr.write("-> %s" % e.output.decode()) + return "0.0+unknown", None, e + else: + out = cmd_out.decode().strip() + if out.endswith("-dirty"): + out = out[:-6] + suffix = ".dirty" + if "-" in out: + # There is a tag, extract it and the other pieces + match = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", out) + tag, plus, sha1 = match.groups() + else: + # No tag, just sha1 + sha1 = out + # Replace dashes in tag for dots + tag = tag.replace("-", ".") + if plus != "0" or suffix: + # Not on a tag, add additional info + tag = f"{tag}+{plus}.g{sha1}{suffix}" + return tag, sha1, None + + +__version__, git_sha1, git_error = get_version_from_git() + + +def get_cmdclass(build_py=None, sdist=None): + """Create cmdclass dict to pass to setuptools.setup. + + Create cmdclass dict to pass to setuptools.setup which will write a + _version_static.py file in our resultant sdist, wheel or egg. + """ + if build_py is None: + from setuptools.command.build_py import build_py + if sdist is None: + from setuptools.command.sdist import sdist + + def make_version_static(base_dir: str, pkg: str): + vg = Path(base_dir) / pkg.split(".")[0] / "_version_git.py" + if vg.is_file(): + lines = open(vg).readlines() + with open(vg, "w") as f: + for line in lines: + # Replace GIT_* with static versions + if line.startswith("GIT_SHA1 = "): + f.write("GIT_SHA1 = '%s'\n" % git_sha1) + elif line.startswith("GIT_REFS = "): + f.write("GIT_REFS = 'tag: %s'\n" % __version__) + else: + f.write(line) + + class BuildPy(build_py): + def run(self): + build_py.run(self) + for pkg in self.packages: + make_version_static(self.build_lib, pkg) + + class Sdist(sdist): + def make_release_tree(self, base_dir, files): + sdist.make_release_tree(self, base_dir, files) + for pkg in self.distribution.packages: + make_version_static(base_dir, pkg) + + return dict(build_py=BuildPy, sdist=Sdist) diff --git a/src/dls_python3_skeleton/hello.py b/src/dls_python3_skeleton/hello.py new file mode 100644 index 000000000..c0b099396 --- /dev/null +++ b/src/dls_python3_skeleton/hello.py @@ -0,0 +1,41 @@ +# The purpose of __all__ is to define the public API of this module, and which +# objects are imported if we call "from dls_python3_skeleton.hello import *" +__all__ = [ + "HelloClass", + "say_hello_lots", +] + + +class HelloClass: + """A class whose only purpose in life is to say hello""" + + def __init__(self, name: str): + """ + Args: + name: The initial value of the name of the person who gets greeted + """ + #: The name of the person who gets greeted + self.name = name + + def format_greeting(self) -> str: + """Return a greeting for `name` + + >>> HelloClass("me").format_greeting() + 'Hello me' + """ + greeting = f"Hello {self.name}" + return greeting + + +def say_hello_lots(hello: HelloClass = None, times=5): + """Print lots of greetings using the given `HelloClass` + + Args: + hello: A `HelloClass` that `format_greeting` will be called on. + If not given, use a HelloClass with name="me" + times: The number of times to call it + """ + if hello is None: + hello = HelloClass("me") + for _ in range(times): + print(hello.format_greeting()) diff --git a/tests/test_boilerplate_removed.py b/tests/test_boilerplate_removed.py new file mode 100644 index 000000000..ca8086cbc --- /dev/null +++ b/tests/test_boilerplate_removed.py @@ -0,0 +1,79 @@ +""" +This file checks that all the example boilerplate text has been removed. +It can be deleted when all the contained tests pass +""" +import configparser +from pathlib import Path + +ROOT = Path(__file__).parent.parent + + +def skeleton_check(check: bool, text: str): + if ROOT.name == "dls-python3-skeleton": + # In the skeleton module the check should fail + check = not check + text = f"Skeleton didn't raise: {text}" + if check: + raise AssertionError(text) + + +def assert_not_contains_text(path: str, text: str, explanation: str): + full_path = ROOT / path + if full_path.exists(): + contents = full_path.read_text().replace("\n", " ") + skeleton_check(text in contents, f"Please change ./{path} {explanation}") + + +def assert_not_exists(path: str, explanation: str): + exists = (ROOT / path).exists() + skeleton_check(exists, f"Please delete ./{path} {explanation}") + + +# setup.cfg +def test_module_description(): + conf = configparser.ConfigParser() + conf.read("setup.cfg") + description = conf["metadata"]["description"] + skeleton_check( + "One line description of your module" in description, + "Please change description in ./setup.cfg " + "to be a one line description of your module", + ) + + +# README +def test_changed_README_intro(): + assert_not_contains_text( + "README.rst", + "This is where you should write a short paragraph", + "to include an intro on what your module does", + ) + + +def test_changed_README_body(): + assert_not_contains_text( + "README.rst", + "This is where you should put some images or code snippets", + "to include some features and why people should use it", + ) + + +# Docs +def test_docs_ref_api_changed(): + assert_not_contains_text( + "docs/reference/api.rst", + "You can mix verbose text with docstring and signature", + "to introduce the API for your module", + ) + + +def test_how_tos_written(): + assert_not_exists( + "docs/how-to/accomplish-a-task.rst", "and write some docs/how-tos" + ) + + +def test_explanations_written(): + assert_not_exists( + "docs/explanations/why-is-something-so.rst", "and write some docs/explanations" + ) diff --git a/tests/test_dls_python3_skeleton.py b/tests/test_dls_python3_skeleton.py new file mode 100644 index 000000000..fffef4b49 --- /dev/null +++ b/tests/test_dls_python3_skeleton.py @@ -0,0 +1,28 @@ +import subprocess +import sys + +from dls_python3_skeleton import __main__, __version__, hello + + +def test_hello_class_formats_greeting() -> None: + inst = hello.HelloClass("person") + assert inst.format_greeting() == "Hello person" + + +def test_hello_lots_defaults(capsys) -> None: + hello.say_hello_lots() + captured = capsys.readouterr() + assert captured.out == "Hello me\n" * 5 + assert captured.err == "" + + +def test_cli_greets(capsys) -> None: + __main__.main(["person", "--times=2"]) + captured = capsys.readouterr() + assert captured.out == "Hello person\n" * 2 + assert captured.err == "" + + +def test_cli_version(): + cmd = [sys.executable, "-m", "dls_python3_skeleton", "--version"] + assert subprocess.check_output(cmd).decode().strip() == __version__ From de6d5f161b940ebd052ee3123a7250a0776dcf50 Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Mon, 7 Feb 2022 15:47:21 +0000 Subject: [PATCH 02/76] Squash all into new skeleton base commit --- .containerignore | 7 + .devcontainer.json | 39 ++++ .gitattributes | 1 - .github/dependabot.yml | 16 ++ .github/pages/index.html | 14 +- .github/workflows/code.yml | 189 ++++++++++++------ .github/workflows/container_tests.sh | 13 ++ .github/workflows/docs.yml | 37 ++-- .github/workflows/docs_clean.yml | 41 ++++ .github/workflows/linkcheck.yml | 34 ++++ .gitignore | 12 +- .gitlab-ci.yml | 4 - .gitremotes | 1 - .pre-commit-config.yaml | 12 +- .vscode/extensions.json | 3 +- .vscode/launch.json | 4 +- .vscode/settings.json | 1 - .vscode/tasks.json | 4 +- CONTRIBUTING.rst | 109 +++++++--- Dockerfile | 47 +++++ Pipfile | 17 -- README.rst | 47 ++--- docs/conf.py | 23 ++- docs/explanations.rst | 2 +- docs/explanations/decisions.rst | 17 ++ .../0001-record-architecture-decisions.rst | 26 +++ docs/explanations/why-is-something-so.rst | 7 - docs/how-to.rst | 2 +- docs/how-to/accomplish-a-task.rst | 7 - docs/{reference => how-to}/contributing.rst | 0 docs/images/dls-logo.svg | 2 +- docs/reference.rst | 5 +- docs/reference/api.rst | 20 +- docs/tutorials/installation.rst | 25 +-- pyproject.toml | 8 +- setup.cfg | 72 +++++-- setup.py | 13 -- src/dls_python3_skeleton/__init__.py | 6 - src/dls_python3_skeleton/__main__.py | 20 -- src/dls_python3_skeleton/_version_git.py | 100 --------- src/dls_python3_skeleton/hello.py | 41 ---- src/python3_pip_skeleton/__init__.py | 12 ++ src/python3_pip_skeleton/__main__.py | 16 ++ tests/test_boilerplate_removed.py | 34 +--- tests/test_cli.py | 9 + tests/test_dls_python3_skeleton.py | 28 --- 46 files changed, 667 insertions(+), 480 deletions(-) create mode 100644 .containerignore create mode 100644 .devcontainer.json delete mode 100644 .gitattributes create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/container_tests.sh create mode 100644 .github/workflows/docs_clean.yml create mode 100644 .github/workflows/linkcheck.yml delete mode 100644 .gitlab-ci.yml delete mode 100644 .gitremotes create mode 100644 Dockerfile delete mode 100644 Pipfile create mode 100644 docs/explanations/decisions.rst create mode 100644 docs/explanations/decisions/0001-record-architecture-decisions.rst delete mode 100644 docs/explanations/why-is-something-so.rst delete mode 100644 docs/how-to/accomplish-a-task.rst rename docs/{reference => how-to}/contributing.rst (100%) delete mode 100644 setup.py delete mode 100644 src/dls_python3_skeleton/__init__.py delete mode 100644 src/dls_python3_skeleton/__main__.py delete mode 100644 src/dls_python3_skeleton/_version_git.py delete mode 100644 src/dls_python3_skeleton/hello.py create mode 100644 src/python3_pip_skeleton/__init__.py create mode 100644 src/python3_pip_skeleton/__main__.py create mode 100644 tests/test_cli.py delete mode 100644 tests/test_dls_python3_skeleton.py diff --git a/.containerignore b/.containerignore new file mode 100644 index 000000000..eb7d5ae15 --- /dev/null +++ b/.containerignore @@ -0,0 +1,7 @@ +Dockerfile +build/ +dist/ +.mypy_cache +.tox +.venv* +venv* diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 000000000..d0921df6d --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,39 @@ +// For format details, see https://aka.ms/devcontainer.json +{ + "name": "Python 3 Developer Container", + "build": { + "dockerfile": "Dockerfile", + "target": "build", + "context": ".", + "args": {} + }, + "remoteEnv": { + "DISPLAY": "${localEnv:DISPLAY}" + }, + // Set *default* container specific settings.json values on container create. + "settings": { + "python.defaultInterpreterPath": "/venv/bin/python", + "python.linting.enabled": true + }, + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance" + ], + // Make sure the files we are mapping into the container exist on the host + "initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'", + "runArgs": [ + "--net=host", + "-v=${localEnv:HOME}/.ssh:/root/.ssh", + "-v=${localEnv:HOME}/.inputrc:/root/.inputrc" + ], + "mounts": [ + // map in home directory - not strictly necessary but useful + "source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached" + ], + // make the workspace folder the same inside and outside of the container + "workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind", + "workspaceFolder": "${localWorkspaceFolder}", + // After the container is created, install the python project in editable form + "postCreateCommand": "pip install $([ -f requirements_dev.txt ] && echo -r requirements_dev.txt ) -e .[dev]" +} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 075748c47..000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -src/*/_version_git.py export-subst diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..fb7c6ee67 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/pages/index.html b/.github/pages/index.html index cc33127d4..80f0a0091 100644 --- a/.github/pages/index.html +++ b/.github/pages/index.html @@ -1,9 +1,11 @@ - - Redirecting to master branch + + + Redirecting to main branch - - - - + + + + + \ No newline at end of file diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 62b51616c..5ea6e1f28 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -2,67 +2,39 @@ name: Code CI on: push: - branches: - # Restricting to these branches and tags stops duplicate jobs on internal - # PRs but stops CI running on internal branches without a PR. Delete the - # next 5 lines to restore the original behaviour - - master - - main - tags: - - "*" pull_request: schedule: # Run every Monday at 8am to check latest versions of dependencies - - cron: '0 8 * * MON' + - cron: "0 8 * * WED" jobs: lint: - runs-on: "ubuntu-latest" - steps: - - name: Run black, flake8, mypy - uses: dls-controls/pipenv-run-action@v1 - with: - pipenv-run: lint + # pull requests are a duplicate of a branch push if within the same repo. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository + runs-on: ubuntu-latest - wheel: - runs-on: "ubuntu-latest" steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup python + uses: actions/setup-python@v4 with: - fetch-depth: 0 + python-version: "3.10" - - name: Create Sdist and Wheel - # Set SOURCE_DATE_EPOCH from git commit for reproducible build - # https://reproducible-builds.org/ - # Set group writable and umask to do the same to match inside DLS + - name: Lint run: | - chmod -R g+w . - umask 0002 - SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) pipx run build --sdist --wheel - - - name: Test cli works from the installed wheel - # Can remove the repository reference after https://github.com/pypa/pipx/pull/733 - run: pipx run --spec dist/*.whl ${GITHUB_REPOSITORY##*/} --version - - - name: Upload Wheel and Sdist as artifacts - uses: actions/upload-artifact@v2 - with: - name: dist - path: dist/* + touch requirements_dev.txt requirements.txt + pip install -r requirements.txt -r requirements_dev.txt -e .[dev] + tox -e pre-commit,mypy test: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository strategy: fail-fast: false matrix: - os: ["ubuntu-latest"] # can add windows-latest, macos-latest - python: ["3.7", "3.8", "3.9"] - pipenv: ["skip-lock"] - - include: - # Add an extra Python3.7 runner to use the lockfile - - os: "ubuntu-latest" - python: "3.7" - pipenv: "deploy" + os: ["ubuntu-latest"] # can add windows-latest, macos-latest + python: ["3.8", "3.9", "3.10"] runs-on: ${{ matrix.os }} env: @@ -70,37 +42,130 @@ jobs: PY_IGNORE_IMPORTMISMATCH: "1" steps: - - name: Setup repo and test - uses: dls-controls/pipenv-run-action@v1 + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Setup python ${{ matrix.python }} + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} - pipenv-install: --dev --${{ matrix.pipenv }} - allow-editable-installs: ${{ matrix.pipenv == 'deploy' }} - pipenv-run: tests + + - name: Install with latest dependencies + run: pip install .[dev] + + - name: Run tests + run: pytest tests - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 with: - name: ${{ matrix.python }}/${{ matrix.os }}/${{ matrix.pipenv }} + name: ${{ matrix.python }}/${{ matrix.os }} files: cov.xml - release: - needs: [lint, wheel, test] + container: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository runs-on: ubuntu-latest - # upload to PyPI and make a release on every tag - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + permissions: + contents: read + packages: write + steps: - - uses: actions/download-artifact@v2 + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Log in to GitHub Docker Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=ref,event=branch + type=ref,event=tag + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + + - name: Build developer image for testing + uses: docker/build-push-action@v3 + with: + tags: build:latest + context: . + target: build + load: true + + - name: Run tests in the container locked with requirements_dev.txt + run: | + docker run --name test build bash /project/.github/workflows/container_tests.sh + docker cp test:/project/dist . + docker cp test:/project/cov.xml . + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + name: 3.10-locked/ubuntu-latest + files: cov.xml + + - name: Build runtime image + uses: docker/build-push-action@v3 + with: + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + context: . + labels: ${{ steps.meta.outputs.labels }} + + - name: Check runtime + run: for i in ${{ steps.meta.outputs.tags }}; do docker run ${i} --version; done + + - name: Upload build files + uses: actions/upload-artifact@v3 with: name: dist - path: dist + path: dist/* + + sdist: + needs: container + runs-on: ubuntu-latest + + steps: + - uses: actions/download-artifact@v3 + + - name: Install sdist in a venv and check cli works + # ${GITHUB_REPOSITORY##*/} is the repo name without org + # Replace this with the cli command if different to the repo name + run: | + pip install dist/*.gz + ${GITHUB_REPOSITORY##*/} --version + + release: + # upload to PyPI and make a release on every tag + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + needs: container + runs-on: ubuntu-latest + + steps: + - uses: actions/download-artifact@v3 - name: Github Release # We pin to the SHA, not the tag, for security reasons. # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions - uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14 + uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14 with: - files: dist/* + prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }} + files: | + dist/* generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -108,5 +173,5 @@ jobs: - name: Publish to PyPI env: TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.pypi_token }} - run: pipx run twine upload dist/* + TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + run: pipx run twine upload dist/*/whl dist/*.tar.gz diff --git a/.github/workflows/container_tests.sh b/.github/workflows/container_tests.sh new file mode 100644 index 000000000..5f9215974 --- /dev/null +++ b/.github/workflows/container_tests.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -x + +cd /project +source /venv/bin/activate + +touch requirements_dev.txt +pip install -r requirements_dev.txt -e .[dev] +pip freeze --exclude-editable > dist/requirements_dev.txt + +pipdeptree + +pytest tests diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e3b8fc903..c3c5eda88 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -2,16 +2,16 @@ name: Docs CI on: push: - branches: - # Add more branches here to publish docs from other branches - - master - - main - tags: - - "*" pull_request: jobs: docs: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository + strategy: + fail-fast: false + matrix: + python: ["3.10"] + runs-on: ubuntu-latest steps: @@ -19,27 +19,40 @@ jobs: if: startsWith(github.ref, 'refs/tags') run: sleep 60 + - name: Install python version + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + - name: Install Packages # Can delete this if you don't use graphviz in your docs run: sudo apt-get install graphviz - - name: Build docs - uses: dls-controls/pipenv-run-action@v1 + - name: checkout + uses: actions/checkout@v2 with: - pipenv-run: docs + fetch-depth: 0 + + - name: Install dependencies + run: | + touch requirements_dev.txt + pip install -r requirements_dev.txt -e .[dev] + + - name: Build docs + run: tox -e docs - name: Move to versioned directory - # e.g. master or 0.1.2 + # e.g. main or 0.1.2 run: mv build/html ".github/pages/${GITHUB_REF##*/}" - name: Write versions.txt - run: pipenv run sphinx_rtd_theme_github_versions .github/pages + run: sphinx_rtd_theme_github_versions .github/pages - name: Publish Docs to gh-pages if: github.event_name == 'push' # We pin to the SHA, not the tag, for security reasons. # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions - uses: peaceiris/actions-gh-pages@068dc23d9710f1ba62e86896f84735d869951305 # v3.8.0 + uses: peaceiris/actions-gh-pages@068dc23d9710f1ba62e86896f84735d869951305 # v3.8.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: .github/pages diff --git a/.github/workflows/docs_clean.yml b/.github/workflows/docs_clean.yml new file mode 100644 index 000000000..2059c7f34 --- /dev/null +++ b/.github/workflows/docs_clean.yml @@ -0,0 +1,41 @@ +name: Docs Cleanup CI + +# delete branch documentation when a branch is deleted +# also allow manually deleting a documentation version +on: + delete: + workflow_dispatch: + inputs: + version: + description: "documentation version to DELETE" + required: true + type: string + +jobs: + remove: + if: github.event.ref_type == 'branch' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@v2 + with: + ref: gh-pages + + - name: removing documentation for branch ${{ github.event.ref }} + if: ${{ github.event_name != 'workflow_dispatch' }} + run: echo "remove_me=${{ github.event.ref }}" >> $GITHUB_ENV + + - name: manually removing documentation version ${{ github.event.inputs.version }} + if: ${{ github.event_name == 'workflow_dispatch' }} + run: echo "remove_me=${{ github.event.inputs.version }}" >> $GITHUB_ENV + + - name: update index and push changes + run: | + echo removing redundant documentation version ${{ env.remove_me }} + rm -r ${{ env.remove_me }} + sed -i /${{ env.remove_me }}/d versions.txt + git config --global user.name 'GitHub Actions Docs Cleanup CI' + git config --global user.email 'gha@users.noreply.github.com' + git commit -am"removing redundant docs version ${{ env.remove_me }}" + git push diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml new file mode 100644 index 000000000..6b37f194e --- /dev/null +++ b/.github/workflows/linkcheck.yml @@ -0,0 +1,34 @@ +name: Link Check + +on: + schedule: + # Run every Monday at 8am to check URL links still resolve + - cron: "0 8 * * WED" + +jobs: + docs: + strategy: + fail-fast: false + matrix: + python: ["3.10"] + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install python version + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + + - name: Install dependencies + run: | + touch requirements_dev.txt + pip install -r requirements_dev.txt -e .[dev] + + - name: Check links + run: tox -e docs -- -b linkcheck diff --git a/.gitignore b/.gitignore index 0ce69d995..e0fba46ad 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ __pycache__/ # Distribution / packaging .Python env/ +.venv build/ develop-eggs/ dist/ @@ -22,6 +23,7 @@ var/ *.egg-info/ .installed.cfg *.egg +**/_version.py # PyInstaller # Usually these files are written by a python script from a template @@ -58,8 +60,8 @@ docs/_build/ # PyBuilder target/ -# DLS build dir and virtual environment -/prefix/ -/venv/ -/lightweight-venv/ -/installed.files +# likely venv names +.venv* +venv* + + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 1efd50249..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,4 +0,0 @@ -include: - - project: 'controls/reports/ci_templates' - ref: master - file: 'python3/dls_py3_template.yml' diff --git a/.gitremotes b/.gitremotes deleted file mode 100644 index 3d3f03492..000000000 --- a/.gitremotes +++ /dev/null @@ -1 +0,0 @@ -github git@github.com:dls-controls/dls-python3-skeleton.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 23a81d4e8..5e270b08d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,20 +12,12 @@ repos: name: Run black stages: [commit] language: system - entry: pipenv run black --check --diff + entry: black --check --diff types: [python] - id: flake8 name: Run flake8 stages: [commit] language: system - entry: pipenv run flake8 + entry: flake8 types: [python] - exclude: setup.py - - - id: mypy - name: Run mypy - stages: [commit] - language: system - entry: pipenv run mypy src tests - pass_filenames: false diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 734f215e6..d173f8d6d 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,8 @@ { "recommendations": [ + "ms-vscode-remote.remote-containers" "ms-python.vscode-pylance", "ms-python.python", "ryanluker.vscode-coverage-gutters" ] -} \ No newline at end of file +} diff --git a/.vscode/launch.json b/.vscode/launch.json index 1d960dc9e..f8fcdb4f2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,9 @@ "request": "launch", "justMyCode": false, "program": "${file}", - "purpose": ["debug-test"], + "purpose": [ + "debug-test" + ], "console": "integratedTerminal", "env": { // The default config in setup.cfg's "[tool:pytest]" adds coverage. diff --git a/.vscode/settings.json b/.vscode/settings.json index 192c474eb..2472acfd6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,4 @@ { - "editor.defaultFormatter": "ms-python.python", "python.linting.pylintEnabled": false, "python.linting.flake8Enabled": true, "python.linting.mypyEnabled": true, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ff78a11b7..946e69d4b 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,8 +5,8 @@ "tasks": [ { "type": "shell", - "label": "Tests with coverage", - "command": "pipenv run tests", + "label": "Tests, lint and docs", + "command": "tox -p", "options": { "cwd": "${workspaceRoot}" }, diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index eba66b594..327e3920b 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -7,17 +7,45 @@ filing a new one. If you have a great idea but it involves big changes, please file a ticket before making a pull request! We want to make sure you don't spend your time coding something that might not fit the scope of the project. -.. _GitHub: https://github.com/dls-controls/dls-python3-skeleton/issues +.. _GitHub: https://github.com/epics-containers/python3-pip-skeleton/issues Running the tests ----------------- -To get the source source code and run the unit tests, run:: +To run in a container +~~~~~~~~~~~~~~~~~~~~~ - $ git clone git://github.com/dls-controls/dls-python3-skeleton.git - $ cd dls-python3-skeleton - $ pipenv install --dev - $ pipenv run tests +Use vscode devcontainer as follows:: + + $ git clone git://github.com/epics-containers/python3-pip-skeleton.git + $ vscode python3-pip-skeleton + Click on 'Reopen in Container' when prompted + In a vscode Terminal: + $ tox -p + + +To run locally +~~~~~~~~~~~~~~ + +Get the source source code and run the unit tests directly +on your workstation as follows:: + + $ git clone git://github.com/epics-containers/python3-pip-skeleton.git + $ cd python3-pip-skeleton + $ virtualenv .venv + $ source .venv/bin/activate + $ pip install -e .[dev] + $ tox -p + +In both cases tox -p runs in parallel the following checks: + + - Build Sphinx Documentation + - run pytest on all tests in ./tests + - run mypy linting on all files in ./src ./tests + - run pre-commit checks: + + - run flake8 style checks against all source + - run black formatting checks against all source While 100% code coverage does not make a library bug-free, it significantly reduces the number of easily caught bugs! Please make sure coverage remains the @@ -33,22 +61,43 @@ The code in this repository conforms to standards set by the following tools: - isort_ for import ordering - mypy_ for static type checking -These checks will be run by pre-commit_. You can either choose to run these -tests on all files tracked by git:: +flake8 and black and isort are run by pre-commit_. You can run the above checks on +all files with this command:: - $ pipenv run lint + $ tox -e pre-commit,mypy Or you can install a pre-commit hook that will run each time you do a ``git -commit`` on just the files that have changed:: +commit`` on just the files that have changed. Note that mypy is not in +the pre-commit because it is a little slow :: - $ pipenv run pre-commit install + $ pre-commit install .. _black: https://github.com/psf/black -.. _flake8: http://flake8.pycqa.org/en/latest/ -.. _isort: https://github.com/timothycrosley/isort +.. _flake8: https://flake8.pycqa.org/en/latest/ +.. _isort: https://github.com/PyCQA/isort .. _mypy: https://github.com/python/mypy .. _pre-commit: https://pre-commit.com/ +Docstrings are pre-processed using the Sphinx Napoleon extension. As such, +google-style_ is considered as standard for this repository. Please use type +hints in the function signature for types. For example:: + + def func(arg1: str, arg2: int) -> bool: + """Summary line. + + Extended description of function. + + Args: + arg1: Description of arg1 + arg2: Description of arg2 + + Returns: + Description of return value + """ + return True + +.. _google-style: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/index.html#google-vs-numpy + Documentation ------------- @@ -68,7 +117,7 @@ Docs follow the underlining convention:: You can build the docs from the project directory by running:: - $ pipenv run docs + $ tox -e docs $ firefox build/html/index.html Release Process @@ -76,27 +125,39 @@ Release Process To make a new release, please follow this checklist: -- Choose a new PEP440 compliant release number -- Git tag the version -- Push to GitHub and the actions will make a release on pypi -- Push to internal gitlab and do a dls-release.py of the tag -- Check and edit for clarity the autogenerated GitHub release_ +- Choose a new PEP440 compliant release number (see https://peps.python.org/pep-0440/) +- Go to the GitHub release_ page +- Choose ``Draft New Release`` +- Click ``Choose Tag`` and supply the new tag you chose (click create new tag) +- Click ``Generate release notes``, review and edit these notes +- Choose a title and click ``Publish Release`` + +Note that tagging and pushing to the main branch has the same effect except that +you will not get the option to edit the release notes. + +.. _release: https://github.com/epics-containers/python3-pip-skeleton/releases + + +Checking Dependencies +--------------------- + +To see a graph of the python package dependency tree type:: -.. _release: https://dls-controls.github.io/dls-python3-skeleton/releases + pipdeptree Updating the tools ------------------ -This module is merged with the dls-python3-skeleton_. This is a generic +This module is merged with the python3-pip-skeleton_. This is a generic Python project structure which provides a means to keep tools and techniques in sync between multiple Python projects. To update to the latest version of the skeleton, run:: - $ git pull https://github.com/dls-controls/dls-python3-skeleton skeleton + $ git pull https://github.com/dls-controls/python3-pip-skeleton main Any merge conflicts will indicate an area where something has changed that conflicts with the setup of the current module. Check the `closed pull requests -`_ +`_ of the skeleton module for more details. -.. _dls-python3-skeleton: https://dls-controls.github.io/dls-python3-skeleton +.. _python3-pip-skeleton: https://epics-containers.github.io/python3-pip-skeleton diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..76b5dad30 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# This file is for use as a devcontainer and a runtime container +# +# The devcontainer should use the build target and run as root with podman +# or docker with user namespaces. +# +FROM python:3.10 as build + +# Add any system dependencies for the developer/build environment here +RUN apt-get update && apt-get upgrade -y && \ + apt-get install -y --no-install-recommends \ + build-essential \ + busybox \ + git \ + net-tools \ + vim \ + && rm -rf /var/lib/apt/lists/* \ + && busybox --install + +COPY . /project + +RUN cd /project && \ + pip install --upgrade pip build && \ + export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) && \ + python -m build --sdist --wheel && \ + touch requirements.txt + +RUN python -m venv /venv +ENV PATH=/venv/bin:$PATH + +RUN cd /project && \ + pip install --upgrade pip && \ + pip install -r requirements.txt dist/*.whl && \ + pip freeze > dist/requirements.txt && \ + # we don't want to include our own wheel in requirements - remove with sed + # and replace with a comment to avoid a zero length asset upload later + sed -i '/file:/s/^/# Requirements for /' dist/requirements.txt + +FROM python:3.10-slim as runtime + +# Add apt-get system dependecies for runtime here if needed + +COPY --from=build /venv/ /venv/ +ENV PATH=/venv/bin:$PATH + +# change this entrypoint if it is not the same as the repo +ENTRYPOINT ["python3-pip-skeleton"] +CMD ["--version"] diff --git a/Pipfile b/Pipfile deleted file mode 100644 index d1ebb0d94..000000000 --- a/Pipfile +++ /dev/null @@ -1,17 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -dls_python3_skeleton = {editable = true, extras = ["dev"], path = "."} - -[packages] -dls_python3_skeleton = {editable = true, path = "."} - -[scripts] -lint = "pre-commit run --all-files --show-diff-on-failure --color=always -v" -tests = "pytest" -docs = "sphinx-build -EWT --keep-going docs build/html" -# Delete any files that git ignore hides from us -gitclean = "git clean -fdX" diff --git a/README.rst b/README.rst index 9b99e2cb4..360d0ef61 100644 --- a/README.rst +++ b/README.rst @@ -1,47 +1,44 @@ -dls-python3-skeleton +python3-pip-skeleton =========================== |code_ci| |docs_ci| |coverage| |pypi_version| |license| +.. note:: + + This project contains template code only. For documentation on how to + adopt this skeleton project see + https://epics-containers.github.io/python3-pip-skeleton-cli + This is where you should write a short paragraph that describes what your module does, how it does it, and why people should use it. ============== ============================================================== -PyPI ``pip install dls_python3_skeleton`` -Source code https://github.com/dls-controls/dls-python3-skeleton -Documentation https://dls-controls.github.io/dls-python3-skeleton -Releases https://github.com/dls-controls/dls-python3-skeleton/releases +PyPI ``pip install python3-pip-skeleton`` +Source code https://github.com/epics-containers/python3-pip-skeleton +Documentation https://epics-containers.github.io/python3-pip-skeleton +Releases https://github.com/epics-containers/python3-pip-skeleton/releases ============== ============================================================== This is where you should put some images or code snippets that illustrate some relevant examples. If it is a library then you might put some -introductory code here: - -.. code:: python - - from dls_python3_skeleton.hello import HelloClass - - hello = HelloClass("me") - print(hello.format_greeting()) - -Or if it is a commandline tool then you might put some example commands here:: +introductory code here. - dls-python3-skeleton person --times=2 +Or if it is a commandline tool then you might put some example commands here. -.. |code_ci| image:: https://github.com/dls-controls/dls-python3-skeleton/workflows/Code%20CI/badge.svg?branch=master - :target: https://github.com/dls-controls/dls-python3-skeleton/actions?query=workflow%3A%22Code+CI%22 +.. |code_ci| image:: https://github.com/epics-containers/python3-pip-skeleton/workflows/Code%20CI/badge.svg?branch=main + :target: https://github.com/epics-containers/python3-pip-skeleton/actions?query=workflow%3A%22Code+CI%22 :alt: Code CI -.. |docs_ci| image:: https://github.com/dls-controls/dls-python3-skeleton/workflows/Docs%20CI/badge.svg?branch=master - :target: https://github.com/dls-controls/dls-python3-skeleton/actions?query=workflow%3A%22Docs+CI%22 +.. |docs_ci| image:: https://github.com/epics-containers/python3-pip-skeleton/workflows/Docs%20CI/badge.svg?branch=main + :target: https://github.com/epics-containers/python3-pip-skeleton/actions?query=workflow%3A%22Docs+CI%22 :alt: Docs CI -.. |coverage| image:: https://codecov.io/gh/dls-controls/dls-python3-skeleton/branch/master/graph/badge.svg - :target: https://codecov.io/gh/dls-controls/dls-python3-skeleton +.. |coverage| image:: https://codecov.io/gh/epics-containers/python3-pip-skeleton/branch/main/graph/badge.svg + :target: https://codecov.io/gh/epics-containers/python3-pip-skeleton :alt: Test Coverage -.. |pypi_version| image:: https://img.shields.io/pypi/v/dls_python3_skeleton.svg - :target: https://pypi.org/project/dls_python3_skeleton +.. |pypi_version| image:: https://img.shields.io/pypi/v/python3-pip-skeleton.svg + :target: https://pypi.org/project/python3-pip-skeleton :alt: Latest PyPI version .. |license| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg @@ -52,4 +49,4 @@ Or if it is a commandline tool then you might put some example commands here:: Anything below this line is used when viewing README.rst and will be replaced when included in index.rst -See https://dls-controls.github.io/dls-python3-skeleton for more detailed documentation. +See https://epics-containers.github.io/python3-pip-skeleton for more detailed documentation. diff --git a/docs/conf.py b/docs/conf.py index f2ca6a2d4..bee41d4b9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,20 +4,20 @@ # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html -import dls_python3_skeleton +import python3_pip_skeleton # -- General configuration ------------------------------------------------ # General information about the project. -project = "dls-python3-skeleton" +project = "python3-pip-skeleton" # The full version, including alpha/beta/rc tags. -release = dls_python3_skeleton.__version__ +release = python3_pip_skeleton.__version__ # The short X.Y version. if "+" in release: # Not on a tag - version = "master" + version = "main" else: version = release @@ -42,7 +42,17 @@ # generating warnings in "nitpicky mode". Note that type should include the # domain name if present. Example entries would be ('py:func', 'int') or # ('envvar', 'LD_LIBRARY_PATH'). -nitpick_ignore = [("py:func", "int")] +nitpick_ignore = [ + ("py:class", "NoneType"), + ("py:class", "'str'"), + ("py:class", "'float'"), + ("py:class", "'int'"), + ("py:class", "'bool'"), + ("py:class", "'object'"), + ("py:class", "'id'"), + ("py:class", "apischema.utils.UndefinedType"), + ("py:class", "typing_extensions.Literal"), +] # Both the class’ and the __init__ method’s docstring are concatenated and # inserted into the main body of the autoclass directive @@ -88,6 +98,9 @@ http://www.diamond.ac.uk """ +# Ignore localhost links for period check that links in docs are valid +linkcheck_ignore = [r"http://localhost:\d+/"] + # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for diff --git a/docs/explanations.rst b/docs/explanations.rst index 39de4e6be..1e3296731 100644 --- a/docs/explanations.rst +++ b/docs/explanations.rst @@ -8,4 +8,4 @@ Explanation of how the library works and why it works that way. .. toctree:: :caption: Explanations - explanations/why-is-something-so + explanations/decisions diff --git a/docs/explanations/decisions.rst b/docs/explanations/decisions.rst new file mode 100644 index 000000000..5841e6ea0 --- /dev/null +++ b/docs/explanations/decisions.rst @@ -0,0 +1,17 @@ +.. 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 http://mozilla.org/MPL/2.0/. + +Architectural Decision Records +============================== + +We record major architectural decisions in Architecture Decision Records (ADRs), +as `described by Michael Nygard +`_. +Below is the list of our current ADRs. + +.. toctree:: + :maxdepth: 1 + :glob: + + decisions/* \ No newline at end of file diff --git a/docs/explanations/decisions/0001-record-architecture-decisions.rst b/docs/explanations/decisions/0001-record-architecture-decisions.rst new file mode 100644 index 000000000..b2d3d0fe8 --- /dev/null +++ b/docs/explanations/decisions/0001-record-architecture-decisions.rst @@ -0,0 +1,26 @@ +1. Record architecture decisions +================================ + +Date: 2022-02-18 + +Status +------ + +Accepted + +Context +------- + +We need to record the architectural decisions made on this project. + +Decision +-------- + +We will use Architecture Decision Records, as `described by Michael Nygard +`_. + +Consequences +------------ + +See Michael Nygard's article, linked above. To create new ADRs we will copy and +paste from existing ones. diff --git a/docs/explanations/why-is-something-so.rst b/docs/explanations/why-is-something-so.rst deleted file mode 100644 index 21708377e..000000000 --- a/docs/explanations/why-is-something-so.rst +++ /dev/null @@ -1,7 +0,0 @@ -Why is something the way it is -============================== - -Often, reading the code will not explain *why* it is written that way. These -explanations should be grouped together in articles here. They might include -history of dls-python3-skeleton, architectural decisions, or the -real world tests that influenced the design of dls-python3-skeleton. diff --git a/docs/how-to.rst b/docs/how-to.rst index 86b2ddbd4..700797cce 100644 --- a/docs/how-to.rst +++ b/docs/how-to.rst @@ -8,4 +8,4 @@ Practical step-by-step guides for the more experienced user. .. toctree:: :caption: How-to Guides - how-to/accomplish-a-task + how-to/contributing diff --git a/docs/how-to/accomplish-a-task.rst b/docs/how-to/accomplish-a-task.rst deleted file mode 100644 index 8ee493904..000000000 --- a/docs/how-to/accomplish-a-task.rst +++ /dev/null @@ -1,7 +0,0 @@ -How to accomplish a task -======================== - -Here you would explain how to use dls-python3-skeleton to accomplish -a particular task. It doesn't have to be an exhaustive guide like the tutorials, -just enough information to show someone who knows what they want to do, how to -accomplish that task. diff --git a/docs/reference/contributing.rst b/docs/how-to/contributing.rst similarity index 100% rename from docs/reference/contributing.rst rename to docs/how-to/contributing.rst diff --git a/docs/images/dls-logo.svg b/docs/images/dls-logo.svg index 79ba266fd..0af1a1770 100644 --- a/docs/images/dls-logo.svg +++ b/docs/images/dls-logo.svg @@ -8,4 +8,4 @@ - + \ No newline at end of file diff --git a/docs/reference.rst b/docs/reference.rst index 3f01ee357..bfa7a4f44 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -3,14 +3,13 @@ Reference ========= -Practical step-by-step guides for the more experienced user. +Technical reference material including APIs and release notes. .. toctree:: :caption: Reference reference/api - reference/contributing - Releases + Releases Index .. diff --git a/docs/reference/api.rst b/docs/reference/api.rst index 06bf3c66b..8544e1728 100644 --- a/docs/reference/api.rst +++ b/docs/reference/api.rst @@ -1,24 +1,14 @@ API === -.. automodule:: dls_python3_skeleton +.. automodule:: python3_pip_skeleton - ``dls_python3_skeleton`` + ``python3_pip_skeleton`` ----------------------------------- -This is the internal API reference for dls_python3_skeleton +This is the internal API reference for python3_pip_skeleton -You can mix verbose text with docstring and signature extraction by -using ``autoclass`` and ``autofunction`` directives instead of -``automodule`` below. - -.. data:: dls_python3_skeleton.__version__ +.. data:: python3_pip_skeleton.__version__ :type: str - Version number as calculated by https://github.com/dls-controls/versiongit - -.. automodule:: dls_python3_skeleton.hello - :members: - - ``dls_python3_skeleton.hello`` - ----------------------------------------- + Version number as calculated by https://github.com/pypa/setuptools_scm diff --git a/docs/tutorials/installation.rst b/docs/tutorials/installation.rst index d23580a3e..bbffd0150 100644 --- a/docs/tutorials/installation.rst +++ b/docs/tutorials/installation.rst @@ -1,20 +1,10 @@ Installation ============ -.. note:: - - For installation inside DLS, please see the internal documentation on - ``dls-python3`` and ``pipenv``. Although these instructions will work - inside DLS, they are intended for external use. - - If you want to contribute to the library itself, please follow - the `../reference/contributing` instructions. - - Check your version of python ---------------------------- -You will need python 3.7 or later. You can check your version of python by +You will need python 3.8 or later. You can check your version of python by typing into a terminal:: python3 --version @@ -35,14 +25,21 @@ Installing the library You can now use ``pip`` to install the library:: - python3 -m pip install dls_python3_skeleton + python3 -m pip install python3-pip-skeleton If you require a feature that is not currently released you can also install from github:: - python3 -m pip install git+git://github.com/dls-controls/dls-python3-skeleton.git + python3 -m pip install git+https://github.com/epics-containers/python3-pip-skeleton.git The library should now be installed and the commandline interface on your path. You can check the version that has been installed by typing:: - dls-python3-skeleton --version + python3-pip-skeleton --version + +Running in a container +---------------------- + +To pull the container from github container registry and run:: + + docker run ghcr.io/epics-containers/python3-pip-skeleton:main --version diff --git a/pyproject.toml b/pyproject.toml index ccd70c768..1b8c998a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -# To get a reproducible wheel, wheel must be pinned to the same version as in -# dls-python3, and setuptools must produce the same dist-info. Cap setuptools -# to the last version that didn't add License-File to METADATA -requires = ["setuptools<57", "wheel==0.33.1"] +requires = ["setuptools>=64", "setuptools_scm[toml]>=6.2", "wheel"] build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +write_to = "src/python3_pip_skeleton/_version.py" diff --git a/setup.cfg b/setup.cfg index 167860a5d..008fd8a4d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,24 +1,29 @@ [metadata] -name = dls_python3_skeleton +name = python3-pip-skeleton description = One line description of your module -url = https://github.com/dls-controls/dls-python3-skeleton +url = https://github.com/epics-containers/python3-pip-skeleton author = Firstname Lastname author_email = email@address.com license = Apache License 2.0 long_description = file: README.rst long_description_content_type = text/x-rst classifiers = - Development Status :: 4 - Beta License :: OSI Approved :: Apache Software License - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 [options] -python_requires = >=3.7 +python_requires = >=3.8 packages = find: +# =src is interpreted as {"": "src"} +# as per recommendation here https://hynek.me/articles/testing-packaging/ package_dir = =src + +setup_requires = + setuptools_scm[toml]>=6.2 + # Specify any package dependencies below. # install_requires = # numpy @@ -27,26 +32,32 @@ package_dir = [options.extras_require] # For development tests/docs dev = - black==21.9b0 + black==22.6.0 + flake8-isort isort>5.0 - pytest-cov mypy - flake8-isort - sphinx-rtd-theme-github-versions + pipdeptree pre-commit + pytest-cov + setuptools_scm[toml]>=6.2 + sphinx-rtd-theme-github-versions + tox + types-mock [options.packages.find] where = src +# Don't include our tests directory in the distribution +exclude = tests # Specify any package data to be included in the wheel below. # [options.package_data] -# dls_python3_skeleton = +# python3_pip_skeleton = # subpackage/*.yaml [options.entry_points] # Include a command line script console_scripts = - dls-python3-skeleton = dls_python3_skeleton.__main__:main + python3-pip-skeleton = python3_pip_skeleton.__main__:main [mypy] # Ignore missing stubs for modules we use @@ -55,7 +66,6 @@ ignore_missing_imports = True [isort] profile=black float_to_top=true -skip=setup.py,conf.py,build [flake8] # Make flake8 respect black's line length (default 88), @@ -63,22 +73,52 @@ max-line-length = 88 extend-ignore = E203, # See https://github.com/PyCQA/pycodestyle/issues/373 F811, # support typing.overload decorator + F722, # allow Annotated[typ, some_func("some string")] +exclude = + ui_* + .tox + .venv [tool:pytest] # Run pytest with all our checkers, and don't spam us with massive tracebacks on error addopts = --tb=native -vv --doctest-modules --doctest-glob="*.rst" - --cov=dls_python3_skeleton --cov-report term --cov-report xml:cov.xml + --cov=python3_pip_skeleton --cov-report term --cov-report xml:cov.xml # https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings filterwarnings = error +# Doctest python code in docs, python code in src docstrings, test functions in tests +testpaths = + docs src tests [coverage:run] -# This is covered in the versiongit test suite so exclude it here -omit = */_version_git.py -data_file = /tmp/dls_python3_skeleton.coverage +data_file = /tmp/python3_pip_skeleton.coverage [coverage:paths] # Tests are run from installed location, map back to the src directory source = src **/site-packages/ + +# Use tox to provide parallel linting and testing +# NOTE that we pre-install all tools in the dev dependencies (including tox). +# Hence the use of allowlist_externals instead of using the tox virtualenvs. +# This ensures a match between developer time tools in the IDE and tox tools. +[tox:tox] +minversion = 3.7 +skipsdist=true +skipinstall=true + +[testenv:{pre-commit,mypy,pytest,docs}] +passenv = + PYTHONPATH + HOME +allowlist_externals = + pytest + pre-commit + mypy + sphinx-build +commands = + pytest: pytest tests {posargs} + mypy: mypy src tests {posargs} + pre-commit: pre-commit run --all-files {posargs} + docs: sphinx-build -EWT --keep-going docs build/html {posargs} diff --git a/setup.py b/setup.py deleted file mode 100644 index 39de827e9..000000000 --- a/setup.py +++ /dev/null @@ -1,13 +0,0 @@ -# type: ignore -import glob -import importlib.util - -from setuptools import setup - -# Import ._version_git.py without importing -path = glob.glob(__file__.replace("setup.py", "src/*/_version_git.py"))[0] -spec = importlib.util.spec_from_file_location("_version_git", path) -vg = importlib.util.module_from_spec(spec) -spec.loader.exec_module(vg) - -setup(cmdclass=vg.get_cmdclass(), version=vg.__version__) diff --git a/src/dls_python3_skeleton/__init__.py b/src/dls_python3_skeleton/__init__.py deleted file mode 100644 index 25eb98fa3..000000000 --- a/src/dls_python3_skeleton/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from . import hello -from ._version_git import __version__ - -# __all__ defines the public API for the package. -# Each module also defines its own __all__. -__all__ = ["__version__", "hello"] diff --git a/src/dls_python3_skeleton/__main__.py b/src/dls_python3_skeleton/__main__.py deleted file mode 100644 index 960eff10f..000000000 --- a/src/dls_python3_skeleton/__main__.py +++ /dev/null @@ -1,20 +0,0 @@ -from argparse import ArgumentParser - -from . import __version__ -from .hello import HelloClass, say_hello_lots - -__all__ = ["main"] - - -def main(args=None): - parser = ArgumentParser() - parser.add_argument("--version", action="version", version=__version__) - parser.add_argument("name", help="Name of the person to greet") - parser.add_argument("--times", type=int, default=5, help="Number of times to greet") - args = parser.parse_args(args) - say_hello_lots(HelloClass(args.name), args.times) - - -# test with: pipenv run python -m dls_python3_skeleton -if __name__ == "__main__": - main() diff --git a/src/dls_python3_skeleton/_version_git.py b/src/dls_python3_skeleton/_version_git.py deleted file mode 100644 index bb7f0c2a5..000000000 --- a/src/dls_python3_skeleton/_version_git.py +++ /dev/null @@ -1,100 +0,0 @@ -# Compute a version number from a git repo or archive - -# This file is released into the public domain. Generated by: -# versiongit-2.1 (https://github.com/dls-controls/versiongit) -import re -import sys -from pathlib import Path -from subprocess import STDOUT, CalledProcessError, check_output - -# These will be filled in if git archive is run or by setup.py cmdclasses -GIT_REFS = "$Format:%D$" -GIT_SHA1 = "$Format:%h$" - -# Git describe gives us sha1, last version-like tag, and commits since then -CMD = "git describe --tags --dirty --always --long --match=[0-9]*[-.][0-9]*" - - -def get_version_from_git(path=None): - """Try to parse version from git describe, fallback to git archive tags.""" - tag, plus, suffix = "0.0", "untagged", "" - if not GIT_SHA1.startswith("$"): - # git archive or the cmdclasses below have filled in these strings - sha1 = GIT_SHA1 - for ref_name in GIT_REFS.split(", "): - if ref_name.startswith("tag: "): - # git from 1.8.3 onwards labels archive tags "tag: TAGNAME" - tag, plus = ref_name[5:], "0" - else: - if path is None: - # If no path to git repo, choose the directory this file is in - path = Path(__file__).absolute().parent - # output is TAG-NUM-gHEX[-dirty] or HEX[-dirty] - try: - cmd_out = check_output(CMD.split(), stderr=STDOUT, cwd=path) - except Exception as e: - sys.stderr.write("%s: %s\n" % (type(e).__name__, str(e))) - if isinstance(e, CalledProcessError): - sys.stderr.write("-> %s" % e.output.decode()) - return "0.0+unknown", None, e - else: - out = cmd_out.decode().strip() - if out.endswith("-dirty"): - out = out[:-6] - suffix = ".dirty" - if "-" in out: - # There is a tag, extract it and the other pieces - match = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", out) - tag, plus, sha1 = match.groups() - else: - # No tag, just sha1 - sha1 = out - # Replace dashes in tag for dots - tag = tag.replace("-", ".") - if plus != "0" or suffix: - # Not on a tag, add additional info - tag = f"{tag}+{plus}.g{sha1}{suffix}" - return tag, sha1, None - - -__version__, git_sha1, git_error = get_version_from_git() - - -def get_cmdclass(build_py=None, sdist=None): - """Create cmdclass dict to pass to setuptools.setup. - - Create cmdclass dict to pass to setuptools.setup which will write a - _version_static.py file in our resultant sdist, wheel or egg. - """ - if build_py is None: - from setuptools.command.build_py import build_py - if sdist is None: - from setuptools.command.sdist import sdist - - def make_version_static(base_dir: str, pkg: str): - vg = Path(base_dir) / pkg.split(".")[0] / "_version_git.py" - if vg.is_file(): - lines = open(vg).readlines() - with open(vg, "w") as f: - for line in lines: - # Replace GIT_* with static versions - if line.startswith("GIT_SHA1 = "): - f.write("GIT_SHA1 = '%s'\n" % git_sha1) - elif line.startswith("GIT_REFS = "): - f.write("GIT_REFS = 'tag: %s'\n" % __version__) - else: - f.write(line) - - class BuildPy(build_py): - def run(self): - build_py.run(self) - for pkg in self.packages: - make_version_static(self.build_lib, pkg) - - class Sdist(sdist): - def make_release_tree(self, base_dir, files): - sdist.make_release_tree(self, base_dir, files) - for pkg in self.distribution.packages: - make_version_static(base_dir, pkg) - - return dict(build_py=BuildPy, sdist=Sdist) diff --git a/src/dls_python3_skeleton/hello.py b/src/dls_python3_skeleton/hello.py deleted file mode 100644 index c0b099396..000000000 --- a/src/dls_python3_skeleton/hello.py +++ /dev/null @@ -1,41 +0,0 @@ -# The purpose of __all__ is to define the public API of this module, and which -# objects are imported if we call "from dls_python3_skeleton.hello import *" -__all__ = [ - "HelloClass", - "say_hello_lots", -] - - -class HelloClass: - """A class whose only purpose in life is to say hello""" - - def __init__(self, name: str): - """ - Args: - name: The initial value of the name of the person who gets greeted - """ - #: The name of the person who gets greeted - self.name = name - - def format_greeting(self) -> str: - """Return a greeting for `name` - - >>> HelloClass("me").format_greeting() - 'Hello me' - """ - greeting = f"Hello {self.name}" - return greeting - - -def say_hello_lots(hello: HelloClass = None, times=5): - """Print lots of greetings using the given `HelloClass` - - Args: - hello: A `HelloClass` that `format_greeting` will be called on. - If not given, use a HelloClass with name="me" - times: The number of times to call it - """ - if hello is None: - hello = HelloClass("me") - for _ in range(times): - print(hello.format_greeting()) diff --git a/src/python3_pip_skeleton/__init__.py b/src/python3_pip_skeleton/__init__.py new file mode 100644 index 000000000..0fe6655ff --- /dev/null +++ b/src/python3_pip_skeleton/__init__.py @@ -0,0 +1,12 @@ +try: + # Use live version from git + from setuptools_scm import get_version + + # Warning: If the install is nested to the same depth, this will always succeed + __version__ = get_version(root="../../", relative_to=__file__) + del get_version +except (ImportError, LookupError): + # Use installed version + from ._version import __version__ + +__all__ = ["__version__"] diff --git a/src/python3_pip_skeleton/__main__.py b/src/python3_pip_skeleton/__main__.py new file mode 100644 index 000000000..1a97fb446 --- /dev/null +++ b/src/python3_pip_skeleton/__main__.py @@ -0,0 +1,16 @@ +from argparse import ArgumentParser + +from . import __version__ + +__all__ = ["main"] + + +def main(args=None): + parser = ArgumentParser() + parser.add_argument("--version", action="version", version=__version__) + args = parser.parse_args(args) + + +# test with: pipenv run python -m python3_pip_skeleton +if __name__ == "__main__": + main() diff --git a/tests/test_boilerplate_removed.py b/tests/test_boilerplate_removed.py index ca8086cbc..f5204fa97 100644 --- a/tests/test_boilerplate_removed.py +++ b/tests/test_boilerplate_removed.py @@ -9,7 +9,7 @@ def skeleton_check(check: bool, text: str): - if ROOT.name == "dls-python3-skeleton": + if ROOT.name == "python3-pip-skeleton" or str(ROOT) == "/project": # In the skeleton module the check should fail check = not check text = f"Skeleton didn't raise: {text}" @@ -24,11 +24,6 @@ def assert_not_contains_text(path: str, text: str, explanation: str): skeleton_check(text in contents, f"Please change ./{path} {explanation}") -def assert_not_exists(path: str, explanation: str): - exists = (ROOT / path).exists() - skeleton_check(exists, f"Please delete ./{path} {explanation}") - - # setup.cfg def test_module_description(): conf = configparser.ConfigParser() @@ -50,30 +45,17 @@ def test_changed_README_intro(): ) -def test_changed_README_body(): +def test_removed_adopt_skeleton(): assert_not_contains_text( "README.rst", - "This is where you should put some images or code snippets", - "to include some features and why people should use it", + "This project contains template code only", + "remove the note at the start", ) -# Docs -def test_docs_ref_api_changed(): +def test_changed_README_body(): assert_not_contains_text( - "docs/reference/api.rst", - "You can mix verbose text with docstring and signature", - "to introduce the API for your module", - ) - - -def test_how_tos_written(): - assert_not_exists( - "docs/how-to/accomplish-a-task.rst", "and write some docs/how-tos" - ) - - -def test_explanations_written(): - assert_not_exists( - "docs/explanations/why-is-something-so.rst", "and write some docs/explanations" + "README.rst", + "This is where you should put some images or code snippets", + "to include some features and why people should use it", ) diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 000000000..2ff648c03 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,9 @@ +import subprocess +import sys + +from python3_pip_skeleton import __version__ + + +def test_cli_version(): + cmd = [sys.executable, "-m", "python3_pip_skeleton", "--version"] + assert subprocess.check_output(cmd).decode().strip() == __version__ diff --git a/tests/test_dls_python3_skeleton.py b/tests/test_dls_python3_skeleton.py deleted file mode 100644 index fffef4b49..000000000 --- a/tests/test_dls_python3_skeleton.py +++ /dev/null @@ -1,28 +0,0 @@ -import subprocess -import sys - -from dls_python3_skeleton import __main__, __version__, hello - - -def test_hello_class_formats_greeting() -> None: - inst = hello.HelloClass("person") - assert inst.format_greeting() == "Hello person" - - -def test_hello_lots_defaults(capsys) -> None: - hello.say_hello_lots() - captured = capsys.readouterr() - assert captured.out == "Hello me\n" * 5 - assert captured.err == "" - - -def test_cli_greets(capsys) -> None: - __main__.main(["person", "--times=2"]) - captured = capsys.readouterr() - assert captured.out == "Hello person\n" * 2 - assert captured.err == "" - - -def test_cli_version(): - cmd = [sys.executable, "-m", "dls_python3_skeleton", "--version"] - assert subprocess.check_output(cmd).decode().strip() == __version__ From 52a0239c36920828c63207a77487f16709565a04 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Fri, 2 Sep 2022 10:39:24 +0000 Subject: [PATCH 03/76] switch org to DiamondLightSource --- CONTRIBUTING.rst | 14 +++++++------- README.rst | 22 +++++++++++----------- docs/reference.rst | 2 +- docs/tutorials/installation.rst | 4 ++-- setup.cfg | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 327e3920b..8f7950d1d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -7,7 +7,7 @@ filing a new one. If you have a great idea but it involves big changes, please file a ticket before making a pull request! We want to make sure you don't spend your time coding something that might not fit the scope of the project. -.. _GitHub: https://github.com/epics-containers/python3-pip-skeleton/issues +.. _GitHub: https://github.com/DiamondLightSource/python3-pip-skeleton/issues Running the tests ----------------- @@ -17,7 +17,7 @@ To run in a container Use vscode devcontainer as follows:: - $ git clone git://github.com/epics-containers/python3-pip-skeleton.git + $ git clone git://github.com/DiamondLightSource/python3-pip-skeleton.git $ vscode python3-pip-skeleton Click on 'Reopen in Container' when prompted In a vscode Terminal: @@ -30,7 +30,7 @@ To run locally Get the source source code and run the unit tests directly on your workstation as follows:: - $ git clone git://github.com/epics-containers/python3-pip-skeleton.git + $ git clone git://github.com/DiamondLightSource/python3-pip-skeleton.git $ cd python3-pip-skeleton $ virtualenv .venv $ source .venv/bin/activate @@ -135,7 +135,7 @@ To make a new release, please follow this checklist: Note that tagging and pushing to the main branch has the same effect except that you will not get the option to edit the release notes. -.. _release: https://github.com/epics-containers/python3-pip-skeleton/releases +.. _release: https://github.com/DiamondLightSource/python3-pip-skeleton/releases Checking Dependencies @@ -153,11 +153,11 @@ Python project structure which provides a means to keep tools and techniques in sync between multiple Python projects. To update to the latest version of the skeleton, run:: - $ git pull https://github.com/dls-controls/python3-pip-skeleton main + $ git pull https://github.com/DiamondLightSource/python3-pip-skeleton main Any merge conflicts will indicate an area where something has changed that conflicts with the setup of the current module. Check the `closed pull requests -`_ +`_ of the skeleton module for more details. -.. _python3-pip-skeleton: https://epics-containers.github.io/python3-pip-skeleton +.. _python3-pip-skeleton: https://DiamondLightSource.github.io/python3-pip-skeleton diff --git a/README.rst b/README.rst index 360d0ef61..95d590c31 100644 --- a/README.rst +++ b/README.rst @@ -7,16 +7,16 @@ python3-pip-skeleton This project contains template code only. For documentation on how to adopt this skeleton project see - https://epics-containers.github.io/python3-pip-skeleton-cli + https://DiamondLightSource.github.io/python3-pip-skeleton-cli This is where you should write a short paragraph that describes what your module does, how it does it, and why people should use it. ============== ============================================================== PyPI ``pip install python3-pip-skeleton`` -Source code https://github.com/epics-containers/python3-pip-skeleton -Documentation https://epics-containers.github.io/python3-pip-skeleton -Releases https://github.com/epics-containers/python3-pip-skeleton/releases +Source code https://github.com/DiamondLightSource/python3-pip-skeleton +Documentation https://DiamondLightSource.github.io/python3-pip-skeleton +Releases https://github.com/DiamondLightSource/python3-pip-skeleton/releases ============== ============================================================== This is where you should put some images or code snippets that illustrate @@ -25,16 +25,16 @@ introductory code here. Or if it is a commandline tool then you might put some example commands here. -.. |code_ci| image:: https://github.com/epics-containers/python3-pip-skeleton/workflows/Code%20CI/badge.svg?branch=main - :target: https://github.com/epics-containers/python3-pip-skeleton/actions?query=workflow%3A%22Code+CI%22 +.. |code_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/workflows/Code%20CI/badge.svg?branch=main + :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions?query=workflow%3A%22Code+CI%22 :alt: Code CI -.. |docs_ci| image:: https://github.com/epics-containers/python3-pip-skeleton/workflows/Docs%20CI/badge.svg?branch=main - :target: https://github.com/epics-containers/python3-pip-skeleton/actions?query=workflow%3A%22Docs+CI%22 +.. |docs_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/workflows/Docs%20CI/badge.svg?branch=main + :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions?query=workflow%3A%22Docs+CI%22 :alt: Docs CI -.. |coverage| image:: https://codecov.io/gh/epics-containers/python3-pip-skeleton/branch/main/graph/badge.svg - :target: https://codecov.io/gh/epics-containers/python3-pip-skeleton +.. |coverage| image:: https://codecov.io/gh/DiamondLightSource/python3-pip-skeleton/branch/main/graph/badge.svg + :target: https://codecov.io/gh/DiamondLightSource/python3-pip-skeleton :alt: Test Coverage .. |pypi_version| image:: https://img.shields.io/pypi/v/python3-pip-skeleton.svg @@ -49,4 +49,4 @@ Or if it is a commandline tool then you might put some example commands here. Anything below this line is used when viewing README.rst and will be replaced when included in index.rst -See https://epics-containers.github.io/python3-pip-skeleton for more detailed documentation. +See https://DiamondLightSource.github.io/python3-pip-skeleton for more detailed documentation. diff --git a/docs/reference.rst b/docs/reference.rst index bfa7a4f44..84c8cf137 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -9,7 +9,7 @@ Technical reference material including APIs and release notes. :caption: Reference reference/api - Releases + Releases Index .. diff --git a/docs/tutorials/installation.rst b/docs/tutorials/installation.rst index bbffd0150..399dc2c56 100644 --- a/docs/tutorials/installation.rst +++ b/docs/tutorials/installation.rst @@ -30,7 +30,7 @@ You can now use ``pip`` to install the library:: If you require a feature that is not currently released you can also install from github:: - python3 -m pip install git+https://github.com/epics-containers/python3-pip-skeleton.git + python3 -m pip install git+https://github.com/DiamondLightSource/python3-pip-skeleton.git The library should now be installed and the commandline interface on your path. You can check the version that has been installed by typing:: @@ -42,4 +42,4 @@ Running in a container To pull the container from github container registry and run:: - docker run ghcr.io/epics-containers/python3-pip-skeleton:main --version + docker run ghcr.io/DiamondLightSource/python3-pip-skeleton:main --version diff --git a/setup.cfg b/setup.cfg index 008fd8a4d..f32a34418 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,7 @@ [metadata] name = python3-pip-skeleton description = One line description of your module -url = https://github.com/epics-containers/python3-pip-skeleton +url = https://github.com/DiamondLightSource/python3-pip-skeleton author = Firstname Lastname author_email = email@address.com license = Apache License 2.0 From 13da3015fba3f486b0f784449a87982c491e9bf7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 10:39:50 +0000 Subject: [PATCH 04/76] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/code.yml | 6 +++--- .github/workflows/docs.yml | 2 +- .github/workflows/docs_clean.yml | 2 +- .github/workflows/linkcheck.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 5ea6e1f28..b2f561a73 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup python uses: actions/setup-python@v4 @@ -43,7 +43,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 @@ -73,7 +73,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c3c5eda88..09e6f3efa 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -29,7 +29,7 @@ jobs: run: sudo apt-get install graphviz - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 diff --git a/.github/workflows/docs_clean.yml b/.github/workflows/docs_clean.yml index 2059c7f34..f39519f77 100644 --- a/.github/workflows/docs_clean.yml +++ b/.github/workflows/docs_clean.yml @@ -18,7 +18,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: ref: gh-pages diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 6b37f194e..e68385603 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 From 0f37bbc885ae54486d890deee65547ae3cc10290 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Sep 2022 09:28:58 +0000 Subject: [PATCH 05/76] Bump black from 22.6.0 to 22.8.0 Bumps [black](https://github.com/psf/black) from 22.6.0 to 22.8.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.6.0...22.8.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index f32a34418..568ecc48b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,7 +32,7 @@ setup_requires = [options.extras_require] # For development tests/docs dev = - black==22.6.0 + black==22.8.0 flake8-isort isort>5.0 mypy From 9e16fc2ce9bd9a318b19c31107aeb4d3c64b3811 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Fri, 2 Sep 2022 12:50:57 +0000 Subject: [PATCH 06/76] fix twine command --- .github/workflows/code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index b2f561a73..ebffb2fcb 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -174,4 +174,4 @@ jobs: env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - run: pipx run twine upload dist/*/whl dist/*.tar.gz + run: pipx run twine upload dist/*.whl dist/*.tar.gz From c975f6dfc55dffc395099ba7ae2b9ad28e136814 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Fri, 2 Sep 2022 15:26:48 +0000 Subject: [PATCH 07/76] obscure the docs cleanup email --- .github/workflows/docs_clean.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs_clean.yml b/.github/workflows/docs_clean.yml index f39519f77..e0f7e4859 100644 --- a/.github/workflows/docs_clean.yml +++ b/.github/workflows/docs_clean.yml @@ -36,6 +36,6 @@ jobs: rm -r ${{ env.remove_me }} sed -i /${{ env.remove_me }}/d versions.txt git config --global user.name 'GitHub Actions Docs Cleanup CI' - git config --global user.email 'gha@users.noreply.github.com' + git config --global user.email 'GithubActionsCleanup@users.noreply.github.com' git commit -am"removing redundant docs version ${{ env.remove_me }}" git push From 10e23967dbdd36a2e207a1b28f1d79f201dff262 Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Fri, 9 Sep 2022 14:21:46 +0000 Subject: [PATCH 08/76] Made tox faster with tox-direct --- Dockerfile | 1 + setup.cfg | 40 ++++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index 76b5dad30..056d144e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,7 @@ RUN cd /project && \ RUN python -m venv /venv ENV PATH=/venv/bin:$PATH +ENV TOX_DIRECT=1 RUN cd /project && \ pip install --upgrade pip && \ diff --git a/setup.cfg b/setup.cfg index 568ecc48b..5d9ac2691 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,6 +42,7 @@ dev = setuptools_scm[toml]>=6.2 sphinx-rtd-theme-github-versions tox + tox-direct types-mock [options.packages.find] @@ -75,9 +76,8 @@ extend-ignore = F811, # support typing.overload decorator F722, # allow Annotated[typ, some_func("some string")] exclude = - ui_* .tox - .venv + venv [tool:pytest] # Run pytest with all our checkers, and don't spam us with massive tracebacks on error @@ -103,22 +103,22 @@ source = # NOTE that we pre-install all tools in the dev dependencies (including tox). # Hence the use of allowlist_externals instead of using the tox virtualenvs. # This ensures a match between developer time tools in the IDE and tox tools. +# Setting TOX_DIRECT=1 in the environment will make this even faster [tox:tox] -minversion = 3.7 -skipsdist=true -skipinstall=true - -[testenv:{pre-commit,mypy,pytest,docs}] -passenv = - PYTHONPATH - HOME -allowlist_externals = - pytest - pre-commit - mypy - sphinx-build -commands = - pytest: pytest tests {posargs} - mypy: mypy src tests {posargs} - pre-commit: pre-commit run --all-files {posargs} - docs: sphinx-build -EWT --keep-going docs build/html {posargs} +skipsdist = True + +[testenv:pytest] +allowlist_externals = pytest +commands = pytest {posargs} + +[testenv:mypy] +allowlist_externals = mypy +commands = mypy src tests {posargs} + +[testenv:pre-commit] +allowlist_externals = pre-commit +commands = pre-commit run --all-files {posargs} + +[testenv:docs] +allowlist_externals = sphinx-build +commands = sphinx-build -EWT --keep-going docs build/html {posargs} From d7a937a22bdf6c95c2ae9a49dfbce9e9509e1c9f Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Fri, 9 Sep 2022 15:45:31 +0000 Subject: [PATCH 09/76] Switch to pydata-theme and split docs There are now developer and user guides. The version switcher is native to the theme so added a script to generate it. --- .github/CONTRIBUTING.rst | 35 ++++ .github/pages/make_switcher.py | 99 +++++++++++ .github/workflows/code.yml | 5 +- .github/workflows/docs.yml | 6 +- .github/workflows/docs_clean.yml | 7 +- .vscode/extensions.json | 4 +- CONTRIBUTING.rst | 163 ------------------ Dockerfile | 4 +- README.rst | 16 +- docs/_static/theme_overrides.css | 34 ---- docs/conf.py | 80 +++++++-- .../explanations/decisions.rst | 0 .../0001-record-architecture-decisions.rst | 0 docs/developer/how-to/build-docs.rst | 20 +++ docs/developer/how-to/contribute.rst | 1 + docs/developer/how-to/lint.rst | 38 ++++ docs/developer/how-to/make-release.rst | 16 ++ docs/developer/how-to/run-tests.rst | 12 ++ docs/developer/how-to/static-analysis.rst | 8 + docs/developer/how-to/update-tools.rst | 16 ++ docs/developer/index.rst | 62 +++++++ docs/developer/reference/standards.rst | 64 +++++++ docs/developer/tutorials/dev-install.rst | 60 +++++++ docs/explanations.rst | 11 -- docs/genindex.rst | 5 + docs/how-to.rst | 11 -- docs/how-to/contributing.rst | 1 - docs/index.rst | 51 ++---- docs/reference.rst | 17 -- docs/tutorials.rst | 11 -- docs/user/explanations/docs-structure.rst | 18 ++ docs/user/how-to/run-container.rst | 15 ++ docs/user/index.rst | 57 ++++++ docs/{ => user}/reference/api.rst | 0 docs/{ => user}/tutorials/installation.rst | 21 +-- setup.cfg | 6 +- src/python3_pip_skeleton/__main__.py | 2 +- 37 files changed, 640 insertions(+), 336 deletions(-) create mode 100644 .github/CONTRIBUTING.rst create mode 100755 .github/pages/make_switcher.py delete mode 100644 CONTRIBUTING.rst delete mode 100644 docs/_static/theme_overrides.css rename docs/{ => developer}/explanations/decisions.rst (100%) rename docs/{ => developer}/explanations/decisions/0001-record-architecture-decisions.rst (100%) create mode 100644 docs/developer/how-to/build-docs.rst create mode 100644 docs/developer/how-to/contribute.rst create mode 100644 docs/developer/how-to/lint.rst create mode 100644 docs/developer/how-to/make-release.rst create mode 100644 docs/developer/how-to/run-tests.rst create mode 100644 docs/developer/how-to/static-analysis.rst create mode 100644 docs/developer/how-to/update-tools.rst create mode 100644 docs/developer/index.rst create mode 100644 docs/developer/reference/standards.rst create mode 100644 docs/developer/tutorials/dev-install.rst delete mode 100644 docs/explanations.rst create mode 100644 docs/genindex.rst delete mode 100644 docs/how-to.rst delete mode 100644 docs/how-to/contributing.rst delete mode 100644 docs/reference.rst delete mode 100644 docs/tutorials.rst create mode 100644 docs/user/explanations/docs-structure.rst create mode 100644 docs/user/how-to/run-container.rst create mode 100644 docs/user/index.rst rename docs/{ => user}/reference/api.rst (100%) rename docs/{ => user}/tutorials/installation.rst (56%) diff --git a/.github/CONTRIBUTING.rst b/.github/CONTRIBUTING.rst new file mode 100644 index 000000000..19ab494ff --- /dev/null +++ b/.github/CONTRIBUTING.rst @@ -0,0 +1,35 @@ +Contributing to the project +=========================== + +Contributions and issues are most welcome! All issues and pull requests are +handled through GitHub_. Also, please check for any existing issues before +filing a new one. If you have a great idea but it involves big changes, please +file a ticket before making a pull request! We want to make sure you don't spend +your time coding something that might not fit the scope of the project. + +.. _GitHub: https://github.com/DiamondLightSource/python3-pip-skeleton/issues + +Issue or Discussion? +-------------------- + +Github also offers discussions_ as a place to ask questions and share ideas. If +your issue is open ended and it is not obvious when it can be "closed", please +raise it as a discussion instead. + +.. _discussions: https://github.com/DiamondLightSource/python3-pip-skeleton/discussions + +Code coverage +------------- + +While 100% code coverage does not make a library bug-free, it significantly +reduces the number of easily caught bugs! Please make sure coverage remains the +same or is improved by a pull request! + +Developer guide +--------------- + +The `Developer Guide`_ contains information on setting up a development +environment, running the tests and what standards the code and documentation +should follow. + +.. _Developer Guide: https://diamondlightsource.github.io/python3-pip-skeleton/main/developer/how-to/contribute.html diff --git a/.github/pages/make_switcher.py b/.github/pages/make_switcher.py new file mode 100755 index 000000000..5c65d7889 --- /dev/null +++ b/.github/pages/make_switcher.py @@ -0,0 +1,99 @@ +import json +import logging +from argparse import ArgumentParser +from pathlib import Path +from subprocess import CalledProcessError, check_output +from typing import List, Optional + + +def report_output(stdout: bytes, label: str) -> List[str]: + ret = stdout.decode().strip().split("\n") + print(f"{label}: {ret}") + return ret + + +def get_branch_contents(ref: str) -> List[str]: + """Get the list of directories in a branch.""" + stdout = check_output(["git", "ls-tree", "-d", "--name-only", ref]) + return report_output(stdout, "Branch contents") + + +def get_sorted_tags_list() -> List[str]: + """Get a list of sorted tags in descending order from the repository.""" + stdout = check_output(["git", "tag", "-l", "--sort=-v:refname"]) + return report_output(stdout, "Tags list") + + +def get_versions(ref: str, add: Optional[str], remove: Optional[str]) -> List[str]: + """Generate the file containing the list of all GitHub Pages builds.""" + # Get the directories (i.e. builds) from the GitHub Pages branch + try: + builds = set(get_branch_contents(ref)) + except CalledProcessError: + builds = set() + logging.warning(f"Cannot get {ref} contents") + + # Add and remove from the list of builds + if add: + builds.add(add) + if remove: + assert remove in builds, f"Build '{remove}' not in {sorted(builds)}" + builds.remove(remove) + + # Get a sorted list of tags + tags = get_sorted_tags_list() + + # Make the sorted versions list from main branches and tags + versions: List[str] = [] + for version in ["master", "main"] + tags: + if version in builds: + versions.append(version) + builds.remove(version) + + # Add in anything that is left to the bottom + versions += sorted(builds) + print(f"Sorted versions: {versions}") + return versions + + +def write_json(path: Path, repository: str, versions: str): + org, repo_name = repository.split("/") + struct = [ + dict(name=version, url=f"https://{org}.github.io/{repo_name}/{version}/") + for version in versions + ] + text = json.dumps(struct, indent=2) + print(f"JSON switcher:\n{text}") + path.write_text(text) + + +def main(args=None): + parser = ArgumentParser( + description="Make a versions.txt file from gh-pages directories" + ) + parser.add_argument( + "--add", + help="Add this directory to the list of existing directories", + ) + parser.add_argument( + "--remove", + help="Remove this directory from the list of existing directories", + ) + parser.add_argument( + "repository", + help="The GitHub org and repository name: ORG/REPO", + ) + parser.add_argument( + "output", + type=Path, + help="Path of write switcher.json to", + ) + args = parser.parse_args(args) + + # Write the versions file + versions = get_versions("origin/gh-pages", args.add, args.remove) + write_json(args.output, args.repository, versions) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index ebffb2fcb..0aae7fb58 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -133,7 +133,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: dist - path: dist/* + path: dist sdist: needs: container @@ -164,8 +164,7 @@ jobs: uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14 with: prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }} - files: | - dist/* + files: dist/* generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 09e6f3efa..a684d031b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,10 +43,10 @@ jobs: - name: Move to versioned directory # e.g. main or 0.1.2 - run: mv build/html ".github/pages/${GITHUB_REF##*/}" + run: mv build/html ".github/pages/${{ github.ref_name }}" - - name: Write versions.txt - run: sphinx_rtd_theme_github_versions .github/pages + - name: Write switcher.json + run: python .github/pages/make_switcher.py --add "${{ github.ref_name }}" ${{ github.repository }} .github/pages/switcher.json - name: Publish Docs to gh-pages if: github.event_name == 'push' diff --git a/.github/workflows/docs_clean.yml b/.github/workflows/docs_clean.yml index e0f7e4859..b80e4c220 100644 --- a/.github/workflows/docs_clean.yml +++ b/.github/workflows/docs_clean.yml @@ -32,10 +32,9 @@ jobs: - name: update index and push changes run: | - echo removing redundant documentation version ${{ env.remove_me }} rm -r ${{ env.remove_me }} - sed -i /${{ env.remove_me }}/d versions.txt + python make_switcher.py --remove ${{ env.remove_me }} ${{ github.repository }} switcher.json git config --global user.name 'GitHub Actions Docs Cleanup CI' - git config --global user.email 'GithubActionsCleanup@users.noreply.github.com' - git commit -am"removing redundant docs version ${{ env.remove_me }}" + git config --global user.email 'GithubActionsCleanup@noreply.github.com' + git commit -am"removing redundant docs version ${{ env.remove_me }}" git push diff --git a/.vscode/extensions.json b/.vscode/extensions.json index d173f8d6d..041f89441 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,8 +1,8 @@ { "recommendations": [ - "ms-vscode-remote.remote-containers" + "ms-vscode-remote.remote-containers", "ms-python.vscode-pylance", "ms-python.python", "ryanluker.vscode-coverage-gutters" ] -} +} \ No newline at end of file diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 8f7950d1d..000000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,163 +0,0 @@ -Contributing -============ - -Contributions and issues are most welcome! All issues and pull requests are -handled through GitHub_. Also, please check for any existing issues before -filing a new one. If you have a great idea but it involves big changes, please -file a ticket before making a pull request! We want to make sure you don't spend -your time coding something that might not fit the scope of the project. - -.. _GitHub: https://github.com/DiamondLightSource/python3-pip-skeleton/issues - -Running the tests ------------------ - -To run in a container -~~~~~~~~~~~~~~~~~~~~~ - -Use vscode devcontainer as follows:: - - $ git clone git://github.com/DiamondLightSource/python3-pip-skeleton.git - $ vscode python3-pip-skeleton - Click on 'Reopen in Container' when prompted - In a vscode Terminal: - $ tox -p - - -To run locally -~~~~~~~~~~~~~~ - -Get the source source code and run the unit tests directly -on your workstation as follows:: - - $ git clone git://github.com/DiamondLightSource/python3-pip-skeleton.git - $ cd python3-pip-skeleton - $ virtualenv .venv - $ source .venv/bin/activate - $ pip install -e .[dev] - $ tox -p - -In both cases tox -p runs in parallel the following checks: - - - Build Sphinx Documentation - - run pytest on all tests in ./tests - - run mypy linting on all files in ./src ./tests - - run pre-commit checks: - - - run flake8 style checks against all source - - run black formatting checks against all source - -While 100% code coverage does not make a library bug-free, it significantly -reduces the number of easily caught bugs! Please make sure coverage remains the -same or is improved by a pull request! - -Code Styling ------------- - -The code in this repository conforms to standards set by the following tools: - -- black_ for code formatting -- flake8_ for style checks -- isort_ for import ordering -- mypy_ for static type checking - -flake8 and black and isort are run by pre-commit_. You can run the above checks on -all files with this command:: - - $ tox -e pre-commit,mypy - -Or you can install a pre-commit hook that will run each time you do a ``git -commit`` on just the files that have changed. Note that mypy is not in -the pre-commit because it is a little slow :: - - $ pre-commit install - -.. _black: https://github.com/psf/black -.. _flake8: https://flake8.pycqa.org/en/latest/ -.. _isort: https://github.com/PyCQA/isort -.. _mypy: https://github.com/python/mypy -.. _pre-commit: https://pre-commit.com/ - -Docstrings are pre-processed using the Sphinx Napoleon extension. As such, -google-style_ is considered as standard for this repository. Please use type -hints in the function signature for types. For example:: - - def func(arg1: str, arg2: int) -> bool: - """Summary line. - - Extended description of function. - - Args: - arg1: Description of arg1 - arg2: Description of arg2 - - Returns: - Description of return value - """ - return True - -.. _google-style: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/index.html#google-vs-numpy - -Documentation -------------- - -Documentation is contained in the ``docs`` directory and extracted from -docstrings of the API. - -Docs follow the underlining convention:: - - Headling 1 (page title) - ======================= - - Heading 2 - --------- - - Heading 3 - ~~~~~~~~~ - -You can build the docs from the project directory by running:: - - $ tox -e docs - $ firefox build/html/index.html - -Release Process ---------------- - -To make a new release, please follow this checklist: - -- Choose a new PEP440 compliant release number (see https://peps.python.org/pep-0440/) -- Go to the GitHub release_ page -- Choose ``Draft New Release`` -- Click ``Choose Tag`` and supply the new tag you chose (click create new tag) -- Click ``Generate release notes``, review and edit these notes -- Choose a title and click ``Publish Release`` - -Note that tagging and pushing to the main branch has the same effect except that -you will not get the option to edit the release notes. - -.. _release: https://github.com/DiamondLightSource/python3-pip-skeleton/releases - - -Checking Dependencies ---------------------- - -To see a graph of the python package dependency tree type:: - - pipdeptree - -Updating the tools ------------------- - -This module is merged with the python3-pip-skeleton_. This is a generic -Python project structure which provides a means to keep tools and -techniques in sync between multiple Python projects. To update to the -latest version of the skeleton, run:: - - $ git pull https://github.com/DiamondLightSource/python3-pip-skeleton main - -Any merge conflicts will indicate an area where something has changed that -conflicts with the setup of the current module. Check the `closed pull requests -`_ -of the skeleton module for more details. - -.. _python3-pip-skeleton: https://DiamondLightSource.github.io/python3-pip-skeleton diff --git a/Dockerfile b/Dockerfile index 056d144e9..b8bfe7278 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # This file is for use as a devcontainer and a runtime container -# -# The devcontainer should use the build target and run as root with podman +# +# The devcontainer should use the build target and run as root with podman # or docker with user namespaces. # FROM python:3.10 as build diff --git a/README.rst b/README.rst index 95d590c31..0450bd2b2 100644 --- a/README.rst +++ b/README.rst @@ -4,9 +4,9 @@ python3-pip-skeleton |code_ci| |docs_ci| |coverage| |pypi_version| |license| .. note:: - + This project contains template code only. For documentation on how to - adopt this skeleton project see + adopt this skeleton project see https://DiamondLightSource.github.io/python3-pip-skeleton-cli This is where you should write a short paragraph that describes what your module does, @@ -21,9 +21,17 @@ Releases https://github.com/DiamondLightSource/python3-pip-skeleton/releas This is where you should put some images or code snippets that illustrate some relevant examples. If it is a library then you might put some -introductory code here. +introductory code here: + +.. code-block:: python + + from python3_pip_skeleton import __version__ + + print(f"Hello python3_pip_skeleton {__version__}") + +Or if it is a commandline tool then you might put some example commands here:: -Or if it is a commandline tool then you might put some example commands here. + $ python -m python3_pip_skeleton --version .. |code_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/workflows/Code%20CI/badge.svg?branch=main :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions?query=workflow%3A%22Code+CI%22 diff --git a/docs/_static/theme_overrides.css b/docs/_static/theme_overrides.css deleted file mode 100644 index 5fd9b7214..000000000 --- a/docs/_static/theme_overrides.css +++ /dev/null @@ -1,34 +0,0 @@ -/* override table width restrictions */ -@media screen and (min-width: 639px) { - .wy-table-responsive table td { - /* !important prevents the common CSS stylesheets from - overriding this as on RTD they are loaded after this stylesheet */ - white-space: normal !important; - } -} - -/* override table padding */ -.rst-content table.docutils th, .rst-content table.docutils td { - padding: 4px 6px; -} - -/* Add two-column option */ -@media only screen and (min-width: 1000px) { - .columns { - padding-left: 10px; - padding-right: 10px; - float: left; - width: 50%; - min-height: 145px; - } -} - -.endcolumns { - clear: both -} - -/* Hide toctrees within columns and captions from all toctrees. - This is what makes the include trick in index.rst work */ -.columns .toctree-wrapper, .toctree-wrapper .caption-text { - display: none; -} diff --git a/docs/conf.py b/docs/conf.py index bee41d4b9..0b6dd5bb9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,6 +4,9 @@ # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html +from pathlib import Path +from subprocess import check_output + import python3_pip_skeleton # -- General configuration ------------------------------------------------ @@ -16,9 +19,12 @@ # The short X.Y version. if "+" in release: - # Not on a tag - version = "main" + # Not on a tag, use branch name + root = Path(__file__).absolute().parent.parent + git_branch = check_output("git branch --show-current".split(), cwd=root) + version = git_branch.decode().strip() else: + branch = "main" version = release extensions = [ @@ -32,6 +38,10 @@ "sphinx.ext.viewcode", # Adds the inheritance-diagram generation directive "sphinx.ext.inheritance_diagram", + # Add a copy button to each code block + "sphinx_copybutton", + # For the card element + "sphinx_design", ] # If true, Sphinx will warn about all references where the target cannot @@ -50,7 +60,6 @@ ("py:class", "'bool'"), ("py:class", "'object'"), ("py:class", "'id'"), - ("py:class", "apischema.utils.UndefinedType"), ("py:class", "typing_extensions.Literal"), ] @@ -94,27 +103,65 @@ # Common links that should be available on every page rst_epilog = """ -.. _Diamond Light Source: - http://www.diamond.ac.uk +.. _Diamond Light Source: http://www.diamond.ac.uk +.. _black: https://github.com/psf/black +.. _flake8: https://flake8.pycqa.org/en/latest/ +.. _isort: https://github.com/PyCQA/isort +.. _mypy: http://mypy-lang.org/ +.. _pre-commit: https://pre-commit.com/ """ -# Ignore localhost links for period check that links in docs are valid +# Ignore localhost links for periodic check that links in docs are valid linkcheck_ignore = [r"http://localhost:\d+/"] +# Set copy-button to ignore python and bash prompts +# https://sphinx-copybutton.readthedocs.io/en/latest/use.html#using-regexp-prompt-identifiers +copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " +copybutton_prompt_is_regexp = True + # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = "sphinx_rtd_theme_github_versions" - -# Options for the sphinx rtd theme, use DLS blue -html_theme_options = dict(style_nav_header_background="rgb(7, 43, 93)") - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] +html_theme = "pydata_sphinx_theme" +github_repo = project +github_user = "DiamondLightSource" + +# Theme options for pydata_sphinx_theme +html_theme_options = dict( + logo=dict( + text=project, + ), + use_edit_page_button=True, + github_url=f"https://github.com/{github_user}/{github_repo}", + icon_links=[ + dict( + name="PyPI", + url=f"https://pypi.org/project/{project}", + icon="fas fa-cube", + ) + ], + switcher=dict( + json_url=f"https://{github_user}.github.io/{github_repo}/switcher.json", + version_match=version, + ), + navbar_end=["theme-switcher", "icon-links", "version-switcher"], + external_links=[ + dict( + name="Release Notes", + url=f"https://github.com/{github_user}/{github_repo}/releases", + ) + ], +) + +# A dictionary of values to pass into the template engine’s context for all pages +html_context = dict( + github_user=github_user, + github_repo=project, + github_version=version, + doc_path="docs", +) # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. html_show_sphinx = False @@ -122,9 +169,6 @@ # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. html_show_copyright = False -# Add some CSS classes for columns and other tweaks in a custom css file -html_css_files = ["theme_overrides.css"] - # Logo html_logo = "images/dls-logo.svg" html_favicon = "images/dls-favicon.ico" diff --git a/docs/explanations/decisions.rst b/docs/developer/explanations/decisions.rst similarity index 100% rename from docs/explanations/decisions.rst rename to docs/developer/explanations/decisions.rst diff --git a/docs/explanations/decisions/0001-record-architecture-decisions.rst b/docs/developer/explanations/decisions/0001-record-architecture-decisions.rst similarity index 100% rename from docs/explanations/decisions/0001-record-architecture-decisions.rst rename to docs/developer/explanations/decisions/0001-record-architecture-decisions.rst diff --git a/docs/developer/how-to/build-docs.rst b/docs/developer/how-to/build-docs.rst new file mode 100644 index 000000000..9540de1c6 --- /dev/null +++ b/docs/developer/how-to/build-docs.rst @@ -0,0 +1,20 @@ +Build the docs using sphinx +=========================== + +You can build the `sphinx`_ based docs from the project directory by running:: + + $ tox -e docs + +This will build the static docs on the ``docs`` directory, which includes API +docs that pull in docstrings from the code. + +.. seealso:: + + `documentation_standards` + +The docs will be built into the ``build/html`` directory, and can be opened +locally with a web browse:: + + $ firefox build/html/index.html + +.. _sphinx: https://www.sphinx-doc.org/ \ No newline at end of file diff --git a/docs/developer/how-to/contribute.rst b/docs/developer/how-to/contribute.rst new file mode 100644 index 000000000..65b992f08 --- /dev/null +++ b/docs/developer/how-to/contribute.rst @@ -0,0 +1 @@ +.. include:: ../../../.github/CONTRIBUTING.rst diff --git a/docs/developer/how-to/lint.rst b/docs/developer/how-to/lint.rst new file mode 100644 index 000000000..1086c3c40 --- /dev/null +++ b/docs/developer/how-to/lint.rst @@ -0,0 +1,38 @@ +Run linting using pre-commit +============================ + +Code linting is handled by black_, flake8_ and isort_ run under pre-commit_. + +Running pre-commit +------------------ + +You can run the above checks on all files with this command:: + + $ tox -e pre-commit + +Or you can install a pre-commit hook that will run each time you do a ``git +commit`` on just the files that have changed:: + + $ pre-commit install + +Fixing issues +------------- + +If black reports an issue you can tell it to reformat all the files in the +repository:: + + $ black . + +Likewise with isort:: + + $ isort . + +If you get any flake8 issues you will have to fix those manually. + +VSCode support +-------------- + +The ``.vscode/settings.json`` will run black and isort formatters as well as +flake8 checking on save. Issues will be highlighted in the editor window. + + diff --git a/docs/developer/how-to/make-release.rst b/docs/developer/how-to/make-release.rst new file mode 100644 index 000000000..747e44a22 --- /dev/null +++ b/docs/developer/how-to/make-release.rst @@ -0,0 +1,16 @@ +Make a release +============== + +To make a new release, please follow this checklist: + +- Choose a new PEP440 compliant release number (see https://peps.python.org/pep-0440/) +- Go to the GitHub release_ page +- Choose ``Draft New Release`` +- Click ``Choose Tag`` and supply the new tag you chose (click create new tag) +- Click ``Generate release notes``, review and edit these notes +- Choose a title and click ``Publish Release`` + +Note that tagging and pushing to the main branch has the same effect except that +you will not get the option to edit the release notes. + +.. _release: https://github.com/DiamondLightSource/python3-pip-skeleton/releases \ No newline at end of file diff --git a/docs/developer/how-to/run-tests.rst b/docs/developer/how-to/run-tests.rst new file mode 100644 index 000000000..d2e03644c --- /dev/null +++ b/docs/developer/how-to/run-tests.rst @@ -0,0 +1,12 @@ +Run the tests using pytest +========================== + +Testing is done with pytest_. It will find functions in the project that `look +like tests`_, and run them to check for errors. You can run it with:: + + $ tox -e pytest + +It will also report coverage to the commandline and to ``cov.xml``. + +.. _pytest: https://pytest.org/ +.. _look like tests: https://docs.pytest.org/explanation/goodpractices.html#test-discovery diff --git a/docs/developer/how-to/static-analysis.rst b/docs/developer/how-to/static-analysis.rst new file mode 100644 index 000000000..065920e1c --- /dev/null +++ b/docs/developer/how-to/static-analysis.rst @@ -0,0 +1,8 @@ +Run static analysis using mypy +============================== + +Static type analysis is done with mypy_. It checks type definition in source +files without running them, and highlights potential issues where types do not +match. You can run it with:: + + $ tox -e mypy diff --git a/docs/developer/how-to/update-tools.rst b/docs/developer/how-to/update-tools.rst new file mode 100644 index 000000000..c1075ee8c --- /dev/null +++ b/docs/developer/how-to/update-tools.rst @@ -0,0 +1,16 @@ +Update the tools +================ + +This module is merged with the python3-pip-skeleton_. This is a generic +Python project structure which provides a means to keep tools and +techniques in sync between multiple Python projects. To update to the +latest version of the skeleton, run:: + + $ git pull --rebase=false https://github.com/DiamondLightSource/python3-pip-skeleton + +Any merge conflicts will indicate an area where something has changed that +conflicts with the setup of the current module. Check the `closed pull requests +`_ +of the skeleton module for more details. + +.. _python3-pip-skeleton: https://DiamondLightSource.github.io/python3-pip-skeleton diff --git a/docs/developer/index.rst b/docs/developer/index.rst new file mode 100644 index 000000000..bf291875f --- /dev/null +++ b/docs/developer/index.rst @@ -0,0 +1,62 @@ +Developer Guide +=============== + +Documentation is split into four categories, also accessible from links in the +side-bar. + +.. grid:: 2 + :gutter: 4 + + .. grid-item-card:: :material-regular:`directions_run;3em` + + .. toctree:: + :caption: Tutorials + :maxdepth: 1 + + tutorials/dev-install + + +++ + + Tutorials for getting up and running as a developer. + + .. grid-item-card:: :material-regular:`task;3em` + + .. toctree:: + :caption: How-to Guides + :maxdepth: 1 + + how-to/contribute + how-to/build-docs + how-to/run-tests + how-to/static-analysis + how-to/lint + how-to/update-tools + how-to/make-release + + +++ + + Practical step-by-step guides for day-to-day dev tasks. + + .. grid-item-card:: :material-regular:`apartment;3em` + + .. toctree:: + :caption: Explanations + :maxdepth: 1 + + explanations/decisions + + +++ + + Explanations of how and why the architecture is why it is. + + .. grid-item-card:: :material-regular:`description;3em` + + .. toctree:: + :caption: Reference + :maxdepth: 1 + + reference/standards + + +++ + + Technical reference material on standards in use. diff --git a/docs/developer/reference/standards.rst b/docs/developer/reference/standards.rst new file mode 100644 index 000000000..b78a719e1 --- /dev/null +++ b/docs/developer/reference/standards.rst @@ -0,0 +1,64 @@ +Standards +========= + +This document defines the code and documentation standards used in this +repository. + +Code Standards +-------------- + +The code in this repository conforms to standards set by the following tools: + +- black_ for code formatting +- flake8_ for style checks +- isort_ for import ordering +- mypy_ for static type checking + +.. seealso:: + + How-to guides `../how-to/lint` and `../how-to/static-analysis` + +.. _documentation_standards: + +Documentation Standards +----------------------- + +Docstrings are pre-processed using the Sphinx Napoleon extension. As such, +google-style_ is considered as standard for this repository. Please use type +hints in the function signature for types. For example: + +.. code:: python + + def func(arg1: str, arg2: int) -> bool: + """Summary line. + + Extended description of function. + + Args: + arg1: Description of arg1 + arg2: Description of arg2 + + Returns: + Description of return value + """ + return True + +.. _google-style: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/index.html#google-vs-numpy + +Documentation is contained in the ``docs`` directory and extracted from +docstrings of the API. + +Docs follow the underlining convention:: + + Headling 1 (page title) + ======================= + + Heading 2 + --------- + + Heading 3 + ~~~~~~~~~ + +.. seealso:: + + How-to guide `../how-to/build-docs` \ No newline at end of file diff --git a/docs/developer/tutorials/dev-install.rst b/docs/developer/tutorials/dev-install.rst new file mode 100644 index 000000000..c26326839 --- /dev/null +++ b/docs/developer/tutorials/dev-install.rst @@ -0,0 +1,60 @@ +Developer install +================= + +These instructions will take you through the minimal steps required to get a dev +environment setup, so you can run the tests locally. + +Clone the repository +-------------------- + +First clone the repository locally using `Git +`_:: + + $ git clone git://github.com/DiamondLightSource/python3-pip-skeleton.git + +Install dependencies +-------------------- + +You can choose to either develop on the host machine using a `venv` (which +requires python 3.8 or later) or to run in a container under `VSCode +`_ + +.. tab-set:: + + .. tab-item:: Local virtualenv + + .. code:: + + $ cd python3-pip-skeleton + $ python3 -m venv venv + $ source venv/bin/activate + $ pip install -e .[dev] + + .. tab-item:: VSCode devcontainer + + .. code:: + + $ vscode python3-pip-skeleton + # Click on 'Reopen in Container' when prompted + # Open a new terminal + +See what was installed +---------------------- + +To see a graph of the python package dependency tree type:: + + $ pipdeptree + +Build and test +-------------- + +Now you have a development environment you can run the tests in a terminal:: + + $ tox -p + +This will run in parallel the following checks: + +- `../how-to/build-docs` +- `../how-to/run-tests` +- `../how-to/static-analysis` +- `../how-to/lint` diff --git a/docs/explanations.rst b/docs/explanations.rst deleted file mode 100644 index 1e3296731..000000000 --- a/docs/explanations.rst +++ /dev/null @@ -1,11 +0,0 @@ -:orphan: - -Explanations -============ - -Explanation of how the library works and why it works that way. - -.. toctree:: - :caption: Explanations - - explanations/decisions diff --git a/docs/genindex.rst b/docs/genindex.rst new file mode 100644 index 000000000..93eb8b294 --- /dev/null +++ b/docs/genindex.rst @@ -0,0 +1,5 @@ +API Index +========= + +.. + https://stackoverflow.com/a/42310803 diff --git a/docs/how-to.rst b/docs/how-to.rst deleted file mode 100644 index 700797cce..000000000 --- a/docs/how-to.rst +++ /dev/null @@ -1,11 +0,0 @@ -:orphan: - -How-to Guides -============= - -Practical step-by-step guides for the more experienced user. - -.. toctree:: - :caption: How-to Guides - - how-to/contributing diff --git a/docs/how-to/contributing.rst b/docs/how-to/contributing.rst deleted file mode 100644 index ac7b6bcf3..000000000 --- a/docs/how-to/contributing.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../CONTRIBUTING.rst diff --git a/docs/index.rst b/docs/index.rst index 9bde8adfb..df33c8e67 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,48 +1,29 @@ +:html_theme.sidebar_secondary.remove: + .. include:: ../README.rst :end-before: when included in index.rst - How the documentation is structured ----------------------------------- -Documentation is split into four categories, also accessible from links in the -side-bar. - -.. rst-class:: columns - -`tutorials` -~~~~~~~~~~~ - -.. include:: tutorials.rst - :start-after: ========= - -.. rst-class:: columns - -`how-to` -~~~~~~~~ - -.. include:: how-to.rst - :start-after: ============= - -.. rst-class:: columns - -`explanations` -~~~~~~~~~~~~~~ +The documentation is split into 2 sections: -.. include:: explanations.rst - :start-after: ============ +.. grid:: 2 -.. rst-class:: columns + .. grid-item-card:: :material-regular:`person;4em` + :link: user/index + :link-type: doc -`reference` -~~~~~~~~~~~ + The User Guide contains documentation on how to install and use python3-pip-skeleton. -.. include:: reference.rst - :start-after: ========= + .. grid-item-card:: :material-regular:`code;4em` + :link: developer/index + :link-type: doc -.. rst-class:: endcolumns + The Developer Guide contains documentation on how to develop and contribute changes back to python3-pip-skeleton. -About the documentation -~~~~~~~~~~~~~~~~~~~~~~~ +.. toctree:: + :hidden: -`Why is the documentation structured this way? `_ + user/index + developer/index diff --git a/docs/reference.rst b/docs/reference.rst deleted file mode 100644 index 84c8cf137..000000000 --- a/docs/reference.rst +++ /dev/null @@ -1,17 +0,0 @@ -:orphan: - -Reference -========= - -Technical reference material including APIs and release notes. - -.. toctree:: - :caption: Reference - - reference/api - Releases - Index - -.. - Index link above is a hack to make genindex.html a relative link - https://stackoverflow.com/a/31820846 diff --git a/docs/tutorials.rst b/docs/tutorials.rst deleted file mode 100644 index dfdef509c..000000000 --- a/docs/tutorials.rst +++ /dev/null @@ -1,11 +0,0 @@ -:orphan: - -Tutorials -========= - -Tutorials for installation, library and commandline usage. New users start here. - -.. toctree:: - :caption: Tutorials - - tutorials/installation diff --git a/docs/user/explanations/docs-structure.rst b/docs/user/explanations/docs-structure.rst new file mode 100644 index 000000000..f25a09baa --- /dev/null +++ b/docs/user/explanations/docs-structure.rst @@ -0,0 +1,18 @@ +About the documentation +----------------------- + + :material-regular:`format_quote;2em` + + The Grand Unified Theory of Documentation + + -- David Laing + +There is a secret that needs to be understood in order to write good software +documentation: there isn't one thing called *documentation*, there are four. + +They are: *tutorials*, *how-to guides*, *technical reference* and *explanation*. +They represent four different purposes or functions, and require four different +approaches to their creation. Understanding the implications of this will help +improve most documentation - often immensely. + +`More information on this topic. `_ diff --git a/docs/user/how-to/run-container.rst b/docs/user/how-to/run-container.rst new file mode 100644 index 000000000..84f857af7 --- /dev/null +++ b/docs/user/how-to/run-container.rst @@ -0,0 +1,15 @@ +Run in a container +================== + +Pre-built containers with python3-pip-skeleton and its dependencies already +installed are available on `Github Container Registry +`_. + +Starting the container +---------------------- + +To pull the container from github container registry and run:: + + $ docker run ghcr.io/DiamondLightSource/python3-pip-skeleton:main --version + +To get a released version, use a numbered release instead of ``main``. diff --git a/docs/user/index.rst b/docs/user/index.rst new file mode 100644 index 000000000..2c94a0c0b --- /dev/null +++ b/docs/user/index.rst @@ -0,0 +1,57 @@ +User Guide +========== + +Documentation is split into four categories, also accessible from links in the +side-bar. + +.. grid:: 2 + :gutter: 4 + + .. grid-item-card:: :material-regular:`directions_walk;3em` + + .. toctree:: + :caption: Tutorials + :maxdepth: 1 + + tutorials/installation + + +++ + + Tutorials for installation and typical usage. New users start here. + + .. grid-item-card:: :material-regular:`directions;3em` + + .. toctree:: + :caption: How-to Guides + :maxdepth: 1 + + how-to/run-container + + +++ + + Practical step-by-step guides for the more experienced user. + + .. grid-item-card:: :material-regular:`info;3em` + + .. toctree:: + :caption: Explanations + :maxdepth: 1 + + explanations/docs-structure + + +++ + + Explanations of how the library works and why it works that way. + + .. grid-item-card:: :material-regular:`menu_book;3em` + + .. toctree:: + :caption: Reference + :maxdepth: 1 + + reference/api + ../genindex + + +++ + + Technical reference material including APIs and release notes. diff --git a/docs/reference/api.rst b/docs/user/reference/api.rst similarity index 100% rename from docs/reference/api.rst rename to docs/user/reference/api.rst diff --git a/docs/tutorials/installation.rst b/docs/user/tutorials/installation.rst similarity index 56% rename from docs/tutorials/installation.rst rename to docs/user/tutorials/installation.rst index 399dc2c56..e90d3efb9 100644 --- a/docs/tutorials/installation.rst +++ b/docs/user/tutorials/installation.rst @@ -7,7 +7,7 @@ Check your version of python You will need python 3.8 or later. You can check your version of python by typing into a terminal:: - python3 --version + $ python3 --version Create a virtual environment @@ -16,30 +16,23 @@ Create a virtual environment It is recommended that you install into a “virtual environment” so this installation will not interfere with any existing Python software:: - python3 -m venv /path/to/venv - source /path/to/venv/bin/activate + $ python3 -m venv /path/to/venv + $ source /path/to/venv/bin/activate Installing the library ---------------------- -You can now use ``pip`` to install the library:: +You can now use ``pip`` to install the library and its dependencies:: - python3 -m pip install python3-pip-skeleton + $ python3 -m pip install python3-pip-skeleton If you require a feature that is not currently released you can also install from github:: - python3 -m pip install git+https://github.com/DiamondLightSource/python3-pip-skeleton.git + $ python3 -m pip install git+https://github.com/DiamondLightSource/python3-pip-skeleton.git The library should now be installed and the commandline interface on your path. You can check the version that has been installed by typing:: - python3-pip-skeleton --version - -Running in a container ----------------------- - -To pull the container from github container registry and run:: - - docker run ghcr.io/DiamondLightSource/python3-pip-skeleton:main --version + $ python3-pip-skeleton --version diff --git a/setup.cfg b/setup.cfg index 5d9ac2691..3daa1c9b2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,7 +20,7 @@ packages = find: # as per recommendation here https://hynek.me/articles/testing-packaging/ package_dir = =src - + setup_requires = setuptools_scm[toml]>=6.2 @@ -38,9 +38,11 @@ dev = mypy pipdeptree pre-commit + pydata-sphinx-theme pytest-cov setuptools_scm[toml]>=6.2 - sphinx-rtd-theme-github-versions + sphinx-copybutton + sphinx-design tox tox-direct types-mock diff --git a/src/python3_pip_skeleton/__main__.py b/src/python3_pip_skeleton/__main__.py index 1a97fb446..c680183b0 100644 --- a/src/python3_pip_skeleton/__main__.py +++ b/src/python3_pip_skeleton/__main__.py @@ -11,6 +11,6 @@ def main(args=None): args = parser.parse_args(args) -# test with: pipenv run python -m python3_pip_skeleton +# test with: python -m python3_pip_skeleton if __name__ == "__main__": main() From 4d21bc31ee9a9b8120cb21dfb519c40a48aa3cd8 Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Tue, 13 Sep 2022 08:51:26 +0000 Subject: [PATCH 10/76] Run sdist install in container workflow This saves another runner starting up just for this --- .github/workflows/code.yml | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 0aae7fb58..13711d46e 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -126,29 +126,20 @@ jobs: context: . labels: ${{ steps.meta.outputs.labels }} - - name: Check runtime + - name: Test cli works in runtime image run: for i in ${{ steps.meta.outputs.tags }}; do docker run ${i} --version; done + - name: Test cli works in sdist installed in local python + # ${GITHUB_REPOSITORY##*/} is the repo name without org + # Replace this with the cli command if different to the repo name + run: pip install dist/*.gz && ${GITHUB_REPOSITORY##*/} --version + - name: Upload build files uses: actions/upload-artifact@v3 with: name: dist path: dist - sdist: - needs: container - runs-on: ubuntu-latest - - steps: - - uses: actions/download-artifact@v3 - - - name: Install sdist in a venv and check cli works - # ${GITHUB_REPOSITORY##*/} is the repo name without org - # Replace this with the cli command if different to the repo name - run: | - pip install dist/*.gz - ${GITHUB_REPOSITORY##*/} --version - release: # upload to PyPI and make a release on every tag if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') From 52038569d52a5471e90f21b0d5ab5d685a18d19c Mon Sep 17 00:00:00 2001 From: Gary Yendell Date: Tue, 13 Sep 2022 09:44:58 +0100 Subject: [PATCH 11/76] Update CI badges --- README.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 0450bd2b2..a014631eb 100644 --- a/README.rst +++ b/README.rst @@ -33,12 +33,12 @@ Or if it is a commandline tool then you might put some example commands here:: $ python -m python3_pip_skeleton --version -.. |code_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/workflows/Code%20CI/badge.svg?branch=main - :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions?query=workflow%3A%22Code+CI%22 +.. |code_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/actions/workflows/code.yml/badge.svg?branch=main + :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions/workflows/code.yml :alt: Code CI -.. |docs_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/workflows/Docs%20CI/badge.svg?branch=main - :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions?query=workflow%3A%22Docs+CI%22 +.. |docs_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/actions/workflows/docs.yml/badge.svg?branch=main + :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions/workflows/docs.yml :alt: Docs CI .. |coverage| image:: https://codecov.io/gh/DiamondLightSource/python3-pip-skeleton/branch/main/graph/badge.svg From d96f15a97efae989aabac10b5f815bd1e3ea143c Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Mon, 3 Oct 2022 21:12:20 +0100 Subject: [PATCH 12/76] Update code.yml Fixing a bug that occurs when releasing. (This is already fixed in the skeleton-cli project but failed to get copied to skeleton). --- .github/workflows/code.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 13711d46e..89960f22c 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -127,7 +127,8 @@ jobs: labels: ${{ steps.meta.outputs.labels }} - name: Test cli works in runtime image - run: for i in ${{ steps.meta.outputs.tags }}; do docker run ${i} --version; done + # check that the first tag can run with --version parameter + run: docker run $(echo ${{ steps.meta.outputs.tags }} | sed -e 's/\s.*$//') --version - name: Test cli works in sdist installed in local python # ${GITHUB_REPOSITORY##*/} is the repo name without org From 68976f406d9c74bc2674897be2cefbd49dbaeba4 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Tue, 4 Oct 2022 11:03:29 +0100 Subject: [PATCH 13/76] Update .github/workflows/code.yml Co-authored-by: Tom C (DLS) <101418278+coretl@users.noreply.github.com> --- .github/workflows/code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 89960f22c..197738394 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -128,7 +128,7 @@ jobs: - name: Test cli works in runtime image # check that the first tag can run with --version parameter - run: docker run $(echo ${{ steps.meta.outputs.tags }} | sed -e 's/\s.*$//') --version + run: docker run $(echo ${{ steps.meta.outputs.tags }} | head -1) --version - name: Test cli works in sdist installed in local python # ${GITHUB_REPOSITORY##*/} is the repo name without org From 92f10b4dfd56e314255147a989c0103b910f7291 Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Fri, 14 Oct 2022 13:52:05 +0100 Subject: [PATCH 14/76] Fix make version switcher to use the right key Pin pydata-sphinx-theme to allow the build to complete https://github.com/pydata/pydata-sphinx-theme/issues/987 --- .github/pages/make_switcher.py | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/pages/make_switcher.py b/.github/pages/make_switcher.py index 5c65d7889..39c127726 100755 --- a/.github/pages/make_switcher.py +++ b/.github/pages/make_switcher.py @@ -59,7 +59,7 @@ def get_versions(ref: str, add: Optional[str], remove: Optional[str]) -> List[st def write_json(path: Path, repository: str, versions: str): org, repo_name = repository.split("/") struct = [ - dict(name=version, url=f"https://{org}.github.io/{repo_name}/{version}/") + dict(version=version, url=f"https://{org}.github.io/{repo_name}/{version}/") for version in versions ] text = json.dumps(struct, indent=2) diff --git a/setup.cfg b/setup.cfg index 3daa1c9b2..857492eb7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -38,7 +38,7 @@ dev = mypy pipdeptree pre-commit - pydata-sphinx-theme + pydata-sphinx-theme < 0.10.1 pytest-cov setuptools_scm[toml]>=6.2 sphinx-copybutton From d35ffdbd28a1cba3fda62503151bcd1da82efbd4 Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Fri, 14 Oct 2022 13:54:50 +0100 Subject: [PATCH 15/76] Add sphinx autobuild --- docs/conf.py | 1 - docs/developer/how-to/build-docs.rst | 18 ++++++++++++++++++ setup.cfg | 5 +++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0b6dd5bb9..c4c2126a2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,7 +24,6 @@ git_branch = check_output("git branch --show-current".split(), cwd=root) version = git_branch.decode().strip() else: - branch = "main" version = release extensions = [ diff --git a/docs/developer/how-to/build-docs.rst b/docs/developer/how-to/build-docs.rst index 9540de1c6..79e3f780c 100644 --- a/docs/developer/how-to/build-docs.rst +++ b/docs/developer/how-to/build-docs.rst @@ -17,4 +17,22 @@ locally with a web browse:: $ firefox build/html/index.html +Autobuild +--------- + +You can also run an autobuild process, which will watch your ``docs`` +directory for changes and rebuild whenever it sees changes, reloading any +browsers watching the pages:: + + $ tox -e docs autobuild + +You can view the pages at localhost:: + + $ firefox http://localhost:8000 + +If you are making changes to source code too, you can tell it to watch +changes in this directory too:: + + $ tox -e docs autobuild -- --watch src + .. _sphinx: https://www.sphinx-doc.org/ \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 857492eb7..2e9dacb83 100644 --- a/setup.cfg +++ b/setup.cfg @@ -41,6 +41,7 @@ dev = pydata-sphinx-theme < 0.10.1 pytest-cov setuptools_scm[toml]>=6.2 + sphinx-autobuild sphinx-copybutton sphinx-design tox @@ -122,5 +123,5 @@ allowlist_externals = pre-commit commands = pre-commit run --all-files {posargs} [testenv:docs] -allowlist_externals = sphinx-build -commands = sphinx-build -EWT --keep-going docs build/html {posargs} +allowlist_externals = sphinx-build sphinx-autobuild +commands = sphinx-{posargs:build -EW --keep-going} -T docs build/html From 7c11165980fe4ccc9260538c9490dfe0cdfe40b1 Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Wed, 5 Oct 2022 15:21:53 +0100 Subject: [PATCH 16/76] Use PyPA action for PyPI Publish Use the official Python Packaging Authority (PyPA) Action to publish to PyPI --- .github/workflows/code.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 197738394..93dd6e37f 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -162,7 +162,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Publish to PyPI - env: - TWINE_USERNAME: __token__ + uses: pypa/gh-action-pypi-publish@release/v1 + with: TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - run: pipx run twine upload dist/*.whl dist/*.tar.gz From 1acb1d47463edeec386cdd82a549e652c57f9b46 Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Wed, 5 Oct 2022 15:27:44 +0100 Subject: [PATCH 17/76] Fix password parameter --- .github/workflows/code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 93dd6e37f..690bb7cd1 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -164,4 +164,4 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + password: ${{ secrets.PYPI_TOKEN }} From 5ff0a302f73174dec5eed0942ef1abd369264b5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 17:00:48 +0000 Subject: [PATCH 18/76] Bump black from 22.8.0 to 22.10.0 Bumps [black](https://github.com/psf/black) from 22.8.0 to 22.10.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.8.0...22.10.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 2e9dacb83..bd277c9aa 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,7 +32,7 @@ setup_requires = [options.extras_require] # For development tests/docs dev = - black==22.8.0 + black==22.10.0 flake8-isort isort>5.0 mypy From 323424fb1d9d037e029ae45920770f656b2e991a Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Fri, 14 Oct 2022 15:31:24 +0100 Subject: [PATCH 19/76] Sanitize ref name for docs version Translate punctuation and unicode in branch names to _ --- .github/workflows/docs.yml | 8 +++++--- .github/workflows/docs_clean.yml | 13 ++++++++----- setup.cfg | 4 +++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a684d031b..f0e7ebb64 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -41,12 +41,14 @@ jobs: - name: Build docs run: tox -e docs + - name: Sanitize ref name for docs version + run: echo "DOCS_VERSION=${GITHUB_REF_NAME//[^A-Za-z0-9._-]/_}" >> $GITHUB_ENV + - name: Move to versioned directory - # e.g. main or 0.1.2 - run: mv build/html ".github/pages/${{ github.ref_name }}" + run: mv build/html .github/pages/$DOCS_VERSION - name: Write switcher.json - run: python .github/pages/make_switcher.py --add "${{ github.ref_name }}" ${{ github.repository }} .github/pages/switcher.json + run: python .github/pages/make_switcher.py --add $DOCS_VERSION ${{ github.repository }} .github/pages/switcher.json - name: Publish Docs to gh-pages if: github.event_name == 'push' diff --git a/.github/workflows/docs_clean.yml b/.github/workflows/docs_clean.yml index b80e4c220..d5425e42a 100644 --- a/.github/workflows/docs_clean.yml +++ b/.github/workflows/docs_clean.yml @@ -24,17 +24,20 @@ jobs: - name: removing documentation for branch ${{ github.event.ref }} if: ${{ github.event_name != 'workflow_dispatch' }} - run: echo "remove_me=${{ github.event.ref }}" >> $GITHUB_ENV + run: echo "REF_NAME=${{ github.event.ref }}" >> $GITHUB_ENV - name: manually removing documentation version ${{ github.event.inputs.version }} if: ${{ github.event_name == 'workflow_dispatch' }} - run: echo "remove_me=${{ github.event.inputs.version }}" >> $GITHUB_ENV + run: echo "REF_NAME=${{ github.event.inputs.version }}" >> $GITHUB_ENV + + - name: Sanitize ref name for docs version + run: echo "DOCS_VERSION=${REF_NAME//[^A-Za-z0-9._-]/_}" >> $GITHUB_ENV - name: update index and push changes run: | - rm -r ${{ env.remove_me }} - python make_switcher.py --remove ${{ env.remove_me }} ${{ github.repository }} switcher.json + rm -r ${{ env.DOCS_VERSION }} + python make_switcher.py --remove $DOCS_VERSION ${{ github.repository }} switcher.json git config --global user.name 'GitHub Actions Docs Cleanup CI' git config --global user.email 'GithubActionsCleanup@noreply.github.com' - git commit -am"removing redundant docs version ${{ env.remove_me }}" + git commit -am "Removing redundant docs version $DOCS_VERSION" git push diff --git a/setup.cfg b/setup.cfg index bd277c9aa..87c5b596e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -123,5 +123,7 @@ allowlist_externals = pre-commit commands = pre-commit run --all-files {posargs} [testenv:docs] -allowlist_externals = sphinx-build sphinx-autobuild +allowlist_externals = + sphinx-build + sphinx-autobuild commands = sphinx-{posargs:build -EW --keep-going} -T docs build/html From 964446a43cda17b235a5577dc586d89c0054f9af Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Tue, 18 Oct 2022 08:43:27 +0100 Subject: [PATCH 20/76] move requirements assests to lockfiles zip --- .containerignore | 7 ------- .dockerignore | 10 ++++++++++ .github/workflows/code.yml | 11 ++++++++++- .github/workflows/container_tests.sh | 3 ++- Dockerfile | 16 ++++++++++------ 5 files changed, 32 insertions(+), 15 deletions(-) delete mode 100644 .containerignore create mode 100644 .dockerignore diff --git a/.containerignore b/.containerignore deleted file mode 100644 index eb7d5ae15..000000000 --- a/.containerignore +++ /dev/null @@ -1,7 +0,0 @@ -Dockerfile -build/ -dist/ -.mypy_cache -.tox -.venv* -venv* diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..4fb4c9efe --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +build/ +dist/ +.mypy_cache +.tox +.venv* +venv* +.devcontainer.json +.pre-commit-config.yaml +.vscode +README.rst diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 690bb7cd1..d63228904 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -110,6 +110,7 @@ jobs: run: | docker run --name test build bash /project/.github/workflows/container_tests.sh docker cp test:/project/dist . + docker cp test:/project/lockfiles . docker cp test:/project/cov.xml . - name: Upload coverage to Codecov @@ -141,6 +142,12 @@ jobs: name: dist path: dist + - name: Upload lock files + uses: actions/upload-artifact@v3 + with: + name: lockfiles + path: lockfiles + release: # upload to PyPI and make a release on every tag if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') @@ -156,7 +163,9 @@ jobs: uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14 with: prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }} - files: dist/* + files: | + dist/ + lockfiles/ generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/container_tests.sh b/.github/workflows/container_tests.sh index 5f9215974..c36bbd9a0 100644 --- a/.github/workflows/container_tests.sh +++ b/.github/workflows/container_tests.sh @@ -6,7 +6,8 @@ source /venv/bin/activate touch requirements_dev.txt pip install -r requirements_dev.txt -e .[dev] -pip freeze --exclude-editable > dist/requirements_dev.txt +mkdir -p lockfiles +pip freeze --exclude-editable > lockfiles/requirements_dev.txt pipdeptree diff --git a/Dockerfile b/Dockerfile index b8bfe7278..5e04e438d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,29 +17,33 @@ RUN apt-get update && apt-get upgrade -y && \ && busybox --install COPY . /project +WORKDIR /project -RUN cd /project && \ - pip install --upgrade pip build && \ +# make the wheel outside of the venv so 'build' does not dirty requirements.txt +RUN pip install --upgrade pip build && \ export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) && \ python -m build --sdist --wheel && \ touch requirements.txt +# set up a virtual environment and put it in PATH RUN python -m venv /venv ENV PATH=/venv/bin:$PATH ENV TOX_DIRECT=1 -RUN cd /project && \ - pip install --upgrade pip && \ +# install the wheel and generate the requirements file +RUN pip install --upgrade pip && \ pip install -r requirements.txt dist/*.whl && \ - pip freeze > dist/requirements.txt && \ + mkdir -p lockfiles && \ + pip freeze > lockfiles/requirements.txt && \ # we don't want to include our own wheel in requirements - remove with sed # and replace with a comment to avoid a zero length asset upload later - sed -i '/file:/s/^/# Requirements for /' dist/requirements.txt + sed -i '/file:/s/^/# Requirements for /' lockfiles/requirements.txt FROM python:3.10-slim as runtime # Add apt-get system dependecies for runtime here if needed +# copy the virtual environment from the build stage and put it in PATH COPY --from=build /venv/ /venv/ ENV PATH=/venv/bin:$PATH From b0426cef26f36c5cc379af879a8a40e1c558721f Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Tue, 18 Oct 2022 12:22:16 +0100 Subject: [PATCH 21/76] fix .dockerignore, build options --- .dockerignore | 2 -- .gitignore | 2 ++ Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.dockerignore b/.dockerignore index 4fb4c9efe..e2ed7105f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,7 +4,5 @@ dist/ .tox .venv* venv* -.devcontainer.json .pre-commit-config.yaml .vscode -README.rst diff --git a/.gitignore b/.gitignore index e0fba46ad..9fbb6bfe0 100644 --- a/.gitignore +++ b/.gitignore @@ -64,4 +64,6 @@ target/ .venv* venv* +# further build artifacts +lockfiles/ diff --git a/Dockerfile b/Dockerfile index 5e04e438d..55020416a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,7 @@ WORKDIR /project # make the wheel outside of the venv so 'build' does not dirty requirements.txt RUN pip install --upgrade pip build && \ export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) && \ - python -m build --sdist --wheel && \ + python -m build && \ touch requirements.txt # set up a virtual environment and put it in PATH From a8d55dd788dc3b7ed7eba0278683475604d1d2d3 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Tue, 1 Nov 2022 08:25:50 +0000 Subject: [PATCH 22/76] add check for dirty repo when building wheel --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 55020416a..c96bee056 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ WORKDIR /project # make the wheel outside of the venv so 'build' does not dirty requirements.txt RUN pip install --upgrade pip build && \ export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) && \ + git diff && \ python -m build && \ touch requirements.txt From 081e205c8530f819115e9d8a99be7c3b4d112c45 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Tue, 1 Nov 2022 08:34:20 +0000 Subject: [PATCH 23/76] fix dockerignore to not dirty repo --- .dockerignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.dockerignore b/.dockerignore index e2ed7105f..a6fab0eac 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,5 +4,3 @@ dist/ .tox .venv* venv* -.pre-commit-config.yaml -.vscode From 9da307f5c84f03f563ae16645d6f29cb6b9d00da Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Wed, 2 Nov 2022 07:59:43 +0000 Subject: [PATCH 24/76] fix Github Release assets spec --- .github/workflows/code.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index d63228904..3aa05f1b5 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -164,8 +164,8 @@ jobs: with: prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }} files: | - dist/ - lockfiles/ + dist/* + lockfiles/* generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From dd95a77887f0ae9cf7a8ee04749e85a2af848d3e Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Fri, 4 Nov 2022 12:29:53 +0000 Subject: [PATCH 25/76] Improve tox-direct handling - Environment variable no longer needs to be set - All commands run with tox-direct by default - All environment variables passed through --- Dockerfile | 1 - setup.cfg | 29 +++++++++++++---------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index c96bee056..df6249c9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,6 @@ RUN pip install --upgrade pip build && \ # set up a virtual environment and put it in PATH RUN python -m venv /venv ENV PATH=/venv/bin:$PATH -ENV TOX_DIRECT=1 # install the wheel and generate the requirements file RUN pip install --upgrade pip && \ diff --git a/setup.cfg b/setup.cfg index 87c5b596e..abe2919df 100644 --- a/setup.cfg +++ b/setup.cfg @@ -106,24 +106,21 @@ source = # NOTE that we pre-install all tools in the dev dependencies (including tox). # Hence the use of allowlist_externals instead of using the tox virtualenvs. # This ensures a match between developer time tools in the IDE and tox tools. -# Setting TOX_DIRECT=1 in the environment will make this even faster [tox:tox] skipsdist = True -[testenv:pytest] -allowlist_externals = pytest -commands = pytest {posargs} - -[testenv:mypy] -allowlist_externals = mypy -commands = mypy src tests {posargs} - -[testenv:pre-commit] -allowlist_externals = pre-commit -commands = pre-commit run --all-files {posargs} - -[testenv:docs] -allowlist_externals = +[testenv:{pre-commit,mypy,pytest,docs}] +# Don't create a virtualenv for the command, requires tox-direct plugin +direct = True +passenv = * +allowlist_externals = + pytest + pre-commit + mypy sphinx-build sphinx-autobuild -commands = sphinx-{posargs:build -EW --keep-going} -T docs build/html +commands = + pytest: pytest {posargs} + mypy: mypy src tests {posargs} + pre-commit: pre-commit run --all-files {posargs} + docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html From 4ccb60169da316ebd2b80f99d0131ad7b0043790 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Tue, 8 Nov 2022 09:37:20 +0000 Subject: [PATCH 26/76] Rely on the container less - Moved wheel and sdist creation to the dist job - Rely on the test matrix to run tests - Simplified container build to make minimal for build and runtime and use wheel from 'dist': only publish to GHCR for tagged builds - Create separate requirements-*.txt for each of the test matrix - Fix actions-gh-pages version and don't run it for dependabot - Move Dockerfile to .devcontainer and use as context to improve build times - Other minor improvements and simplifications --- .devcontainer/Dockerfile | 37 +++++ .../devcontainer.json | 12 +- .dockerignore | 6 - .../actions/install_requirements/action.yml | 58 +++++++ .github/workflows/code.yml | 153 ++++++++++-------- .github/workflows/container_tests.sh | 14 -- .github/workflows/docs.yml | 30 ++-- .github/workflows/docs_clean.yml | 4 +- .github/workflows/linkcheck.yml | 19 +-- Dockerfile | 52 ------ setup.cfg | 3 +- 11 files changed, 212 insertions(+), 176 deletions(-) create mode 100644 .devcontainer/Dockerfile rename .devcontainer.json => .devcontainer/devcontainer.json (81%) delete mode 100644 .dockerignore create mode 100644 .github/actions/install_requirements/action.yml delete mode 100644 .github/workflows/container_tests.sh delete mode 100644 Dockerfile diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..b6b4bef96 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,37 @@ +# This file is for use as a devcontainer and a runtime container +# +# The devcontainer should use the build target and run as root with podman +# or docker with user namespaces. +# +FROM python:3.11 as build + +ARG PIP_OPTIONS + +# Add any system dependencies for the developer/build environment here e.g. +# RUN apt-get update && apt-get upgrade -y && \ +# apt-get install -y --no-install-recommends \ +# desired-packages \ +# && rm -rf /var/lib/apt/lists/* + +# set up a virtual environment and put it in PATH +RUN python -m venv /venv +ENV PATH=/venv/bin:$PATH + +# Copy any required context for the pip install over +COPY . /context +WORKDIR /context + +# install python package into /venv +RUN pip install ${PIP_OPTIONS} + +FROM python:3.11-slim as runtime + +# Add apt-get system dependecies for runtime here if needed + +# copy the virtual environment from the build stage and put it in PATH +COPY --from=build /venv/ /venv/ +ENV PATH=/venv/bin:$PATH + +# change this entrypoint if it is not the same as the repo +ENTRYPOINT ["python3-pip-skeleton"] +CMD ["--version"] diff --git a/.devcontainer.json b/.devcontainer/devcontainer.json similarity index 81% rename from .devcontainer.json rename to .devcontainer/devcontainer.json index d0921df6d..1046ef9ef 100644 --- a/.devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,16 +4,17 @@ "build": { "dockerfile": "Dockerfile", "target": "build", - "context": ".", - "args": {} + // Only upgrade pip, we will install the project below + "args": { + "PIP_OPTIONS": "--upgrade pip" + } }, "remoteEnv": { "DISPLAY": "${localEnv:DISPLAY}" }, // Set *default* container specific settings.json values on container create. "settings": { - "python.defaultInterpreterPath": "/venv/bin/python", - "python.linting.enabled": true + "python.defaultInterpreterPath": "/venv/bin/python" }, // Add the IDs of extensions you want installed when the container is created. "extensions": [ @@ -24,6 +25,7 @@ "initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'", "runArgs": [ "--net=host", + "--security-opt=label=type:container_runtime_t", "-v=${localEnv:HOME}/.ssh:/root/.ssh", "-v=${localEnv:HOME}/.inputrc:/root/.inputrc" ], @@ -35,5 +37,5 @@ "workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind", "workspaceFolder": "${localWorkspaceFolder}", // After the container is created, install the python project in editable form - "postCreateCommand": "pip install $([ -f requirements_dev.txt ] && echo -r requirements_dev.txt ) -e .[dev]" + "postCreateCommand": "pip install -e .[dev]" } \ No newline at end of file diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index a6fab0eac..000000000 --- a/.dockerignore +++ /dev/null @@ -1,6 +0,0 @@ -build/ -dist/ -.mypy_cache -.tox -.venv* -venv* diff --git a/.github/actions/install_requirements/action.yml b/.github/actions/install_requirements/action.yml new file mode 100644 index 000000000..25a146d16 --- /dev/null +++ b/.github/actions/install_requirements/action.yml @@ -0,0 +1,58 @@ +name: Install requirements +description: Run pip install with requirements and upload resulting requirements +inputs: + requirements_file: + description: Name of requirements file to use and upload + required: true + install_options: + description: Parameters to pass to pip install + required: true + python_version: + description: Python version to install + default: "3.x" + +runs: + using: composite + + steps: + - name: Setup python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python_version }} + + - name: Pip install + run: | + touch ${{ inputs.requirements_file }} + # -c uses requirements.txt as constraints, see 'Validate requirements file' + pip install -c ${{ inputs.requirements_file }} ${{ inputs.install_options }} + shell: bash + + - name: Create lockfile + run: | + mkdir -p lockfiles + pip freeze --exclude-editable > lockfiles/${{ inputs.requirements_file }} + # delete the self referencing line and make sure it isn't blank + sed -i '/file:/d' lockfiles/${{ inputs.requirements_file }} + shell: bash + + - name: Upload lockfiles + uses: actions/upload-artifact@v3 + with: + name: lockfiles + path: lockfiles + + # This eliminates the class of problems where the requirements being given no + # longer match what the packages themselves dictate. E.g. In the rare instance + # where I install some-package which used to depend on vulnerable-dependency + # but now uses good-dependency (despite being nominally the same version) + # pip will install both if given a requirements file with -r + - name: If requirements file exists, check it matches pip installed packages + run: | + if [ -s ${{ inputs.requirements_file }} ]; then + if ! diff -u ${{ inputs.requirements_file }} lockfiles/${{ inputs.requirements_file }}; then + echo "Error: ${{ inputs.requirements_file }} need the above changes to be exhaustive" + exit 1 + fi + fi + shell: bash + diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 3aa05f1b5..200b07b6c 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -4,8 +4,11 @@ on: push: pull_request: schedule: - # Run every Monday at 8am to check latest versions of dependencies + # Run weekly to check latest versions of dependencies - cron: "0 8 * * WED" +env: + # The target python version, which must match the Dockerfile version + CONTAINER_PYTHON: "3.11" jobs: lint: @@ -17,16 +20,14 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Setup python - uses: actions/setup-python@v4 + - name: Install python packages + uses: ./.github/actions/install_requirements with: - python-version: "3.10" + requirements_file: requirements-dev-3.x.txt + install_options: -e .[dev] - name: Lint - run: | - touch requirements_dev.txt requirements.txt - pip install -r requirements.txt -r requirements_dev.txt -e .[dev] - tox -e pre-commit,mypy + run: tox -e pre-commit,mypy test: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository @@ -34,7 +35,13 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest"] # can add windows-latest, macos-latest - python: ["3.8", "3.9", "3.10"] + python: ["3.9", "3.10", "3.11"] + install: ["-e .[dev]"] + # Make one version be non-editable to test both paths of version code + include: + - os: "ubuntu-latest" + python: "3.8" + install: ".[dev]" runs-on: ${{ matrix.os }} env: @@ -45,18 +52,21 @@ jobs: - name: Checkout uses: actions/checkout@v3 with: + # Need this to get version number from last tag fetch-depth: 0 - - name: Setup python ${{ matrix.python }} - uses: actions/setup-python@v4 + - name: Install python packages + uses: ./.github/actions/install_requirements with: - python-version: ${{ matrix.python }} + python_version: ${{ matrix.python }} + requirements_file: requirements-test-${{ matrix.os }}-${{ matrix.python }}.txt + install_options: ${{ matrix.install }} - - name: Install with latest dependencies - run: pip install .[dev] + - name: List dependency tree + run: pipdeptree - name: Run tests - run: pytest tests + run: pytest - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 @@ -64,9 +74,46 @@ jobs: name: ${{ matrix.python }}/${{ matrix.os }} files: cov.xml - container: + dist: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository + runs-on: "ubuntu-latest" + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + # Need this to get version number from last tag + fetch-depth: 0 + + - name: Build sdist and wheel + run: | + export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) && \ + pipx run build + + - name: Upload sdist and wheel as artifacts + uses: actions/upload-artifact@v3 + with: + name: dist + path: dist + + - name: Check for packaging errors + run: pipx run twine check dist/* + + - name: Install python packages + uses: ./.github/actions/install_requirements + with: + python_version: ${{env.CONTAINER_PYTHON}} + requirements_file: requirements.txt + install_options: dist/*.whl + + - name: Test module --version works using the installed wheel + # If more than one module in src/ replace with module name to test + run: python -m $(ls src | head -1) --version + + container: + needs: [lint, dist, test] runs-on: ubuntu-latest + permissions: contents: read packages: write @@ -74,8 +121,15 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 + + # image names must be all lower case + - name: Generate image repo name + run: echo IMAGE_REPOSITORY=ghcr.io/$(tr '[:upper:]' '[:lower:]' <<< "${{ github.repository }}") >> $GITHUB_ENV + + - name: Download wheel and lockfiles + uses: actions/download-artifact@v3 with: - fetch-depth: 0 + path: .devcontainer - name: Log in to GitHub Docker Registry if: github.event_name != 'pull_request' @@ -89,74 +143,45 @@ jobs: id: meta uses: docker/metadata-action@v4 with: - images: ghcr.io/${{ github.repository }} + images: ${{ env.IMAGE_REPOSITORY }} tags: | - type=ref,event=branch type=ref,event=tag + type=raw,value=latest - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v2 - - name: Build developer image for testing - uses: docker/build-push-action@v3 - with: - tags: build:latest - context: . - target: build - load: true - - - name: Run tests in the container locked with requirements_dev.txt - run: | - docker run --name test build bash /project/.github/workflows/container_tests.sh - docker cp test:/project/dist . - docker cp test:/project/lockfiles . - docker cp test:/project/cov.xml . - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 - with: - name: 3.10-locked/ubuntu-latest - files: cov.xml - - name: Build runtime image uses: docker/build-push-action@v3 with: - push: ${{ github.event_name != 'pull_request' }} + build-args: | + PIP_OPTIONS=-r lockfiles/requirements.txt dist/*.whl + push: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }} + load: ${{ ! (github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) }} tags: ${{ steps.meta.outputs.tags }} - context: . - labels: ${{ steps.meta.outputs.labels }} + context: .devcontainer + # If you have a long docker build, uncomment the following to turn on caching + # For short build times this makes it a little slower + #cache-from: type=gha + #cache-to: type=gha,mode=max - name: Test cli works in runtime image - # check that the first tag can run with --version parameter - run: docker run $(echo ${{ steps.meta.outputs.tags }} | head -1) --version - - - name: Test cli works in sdist installed in local python - # ${GITHUB_REPOSITORY##*/} is the repo name without org - # Replace this with the cli command if different to the repo name - run: pip install dist/*.gz && ${GITHUB_REPOSITORY##*/} --version - - - name: Upload build files - uses: actions/upload-artifact@v3 - with: - name: dist - path: dist - - - name: Upload lock files - uses: actions/upload-artifact@v3 - with: - name: lockfiles - path: lockfiles + run: docker run ${{ env.IMAGE_REPOSITORY }} --version release: # upload to PyPI and make a release on every tag - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - needs: container + needs: [lint, dist, test] + if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }} runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v3 + - name: Fixup blank lockfiles + # Github release artifacts can't be blank + run: for f in lockfiles/*; do [ -s $f ] || echo '# No requirements' >> $f; done + - name: Github Release # We pin to the SHA, not the tag, for security reasons. # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions diff --git a/.github/workflows/container_tests.sh b/.github/workflows/container_tests.sh deleted file mode 100644 index c36bbd9a0..000000000 --- a/.github/workflows/container_tests.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -x - -cd /project -source /venv/bin/activate - -touch requirements_dev.txt -pip install -r requirements_dev.txt -e .[dev] -mkdir -p lockfiles -pip freeze --exclude-editable > lockfiles/requirements_dev.txt - -pipdeptree - -pytest tests diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f0e7ebb64..94fa2151e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,11 +7,6 @@ on: jobs: docs: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository - strategy: - fail-fast: false - matrix: - python: ["3.10"] - runs-on: ubuntu-latest steps: @@ -19,24 +14,21 @@ jobs: if: startsWith(github.ref, 'refs/tags') run: sleep 60 - - name: Install python version - uses: actions/setup-python@v4 + - name: Checkout + uses: actions/checkout@v3 with: - python-version: ${{ matrix.python }} + # Need this to get version number from last tag + fetch-depth: 0 - - name: Install Packages + - name: Install system packages # Can delete this if you don't use graphviz in your docs run: sudo apt-get install graphviz - - name: checkout - uses: actions/checkout@v3 + - name: Install python packages + uses: ./.github/actions/install_requirements with: - fetch-depth: 0 - - - name: Install dependencies - run: | - touch requirements_dev.txt - pip install -r requirements_dev.txt -e .[dev] + requirements_file: requirements-dev-3.x.txt + install_options: -e .[dev] - name: Build docs run: tox -e docs @@ -51,10 +43,10 @@ jobs: run: python .github/pages/make_switcher.py --add $DOCS_VERSION ${{ github.repository }} .github/pages/switcher.json - name: Publish Docs to gh-pages - if: github.event_name == 'push' + if: github.event_name == 'push' && github.actor != 'dependabot[bot]' # We pin to the SHA, not the tag, for security reasons. # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions - uses: peaceiris/actions-gh-pages@068dc23d9710f1ba62e86896f84735d869951305 # v3.8.0 + uses: peaceiris/actions-gh-pages@de7ea6f8efb354206b205ef54722213d99067935 # v3.9.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: .github/pages diff --git a/.github/workflows/docs_clean.yml b/.github/workflows/docs_clean.yml index d5425e42a..a67e18815 100644 --- a/.github/workflows/docs_clean.yml +++ b/.github/workflows/docs_clean.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - - name: checkout + - name: Checkout uses: actions/checkout@v3 with: ref: gh-pages @@ -35,7 +35,7 @@ jobs: - name: update index and push changes run: | - rm -r ${{ env.DOCS_VERSION }} + rm -r $DOCS_VERSION python make_switcher.py --remove $DOCS_VERSION ${{ github.repository }} switcher.json git config --global user.name 'GitHub Actions Docs Cleanup CI' git config --global user.email 'GithubActionsCleanup@noreply.github.com' diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index e68385603..42d199c4f 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -1,8 +1,9 @@ name: Link Check on: + workflow_dispatch: schedule: - # Run every Monday at 8am to check URL links still resolve + # Run weekly to check URL links still resolve - cron: "0 8 * * WED" jobs: @@ -17,18 +18,12 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Install python version - uses: actions/setup-python@v4 + - name: Install python packages + uses: ./.github/actions/install_requirements with: - python-version: ${{ matrix.python }} - - - name: Install dependencies - run: | - touch requirements_dev.txt - pip install -r requirements_dev.txt -e .[dev] + requirements_file: requirements-dev-3.x.txt + install_options: -e .[dev] - name: Check links - run: tox -e docs -- -b linkcheck + run: tox -e docs build -- -b linkcheck diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index df6249c9a..000000000 --- a/Dockerfile +++ /dev/null @@ -1,52 +0,0 @@ -# This file is for use as a devcontainer and a runtime container -# -# The devcontainer should use the build target and run as root with podman -# or docker with user namespaces. -# -FROM python:3.10 as build - -# Add any system dependencies for the developer/build environment here -RUN apt-get update && apt-get upgrade -y && \ - apt-get install -y --no-install-recommends \ - build-essential \ - busybox \ - git \ - net-tools \ - vim \ - && rm -rf /var/lib/apt/lists/* \ - && busybox --install - -COPY . /project -WORKDIR /project - -# make the wheel outside of the venv so 'build' does not dirty requirements.txt -RUN pip install --upgrade pip build && \ - export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) && \ - git diff && \ - python -m build && \ - touch requirements.txt - -# set up a virtual environment and put it in PATH -RUN python -m venv /venv -ENV PATH=/venv/bin:$PATH - -# install the wheel and generate the requirements file -RUN pip install --upgrade pip && \ - pip install -r requirements.txt dist/*.whl && \ - mkdir -p lockfiles && \ - pip freeze > lockfiles/requirements.txt && \ - # we don't want to include our own wheel in requirements - remove with sed - # and replace with a comment to avoid a zero length asset upload later - sed -i '/file:/s/^/# Requirements for /' lockfiles/requirements.txt - -FROM python:3.10-slim as runtime - -# Add apt-get system dependecies for runtime here if needed - -# copy the virtual environment from the build stage and put it in PATH -COPY --from=build /venv/ /venv/ -ENV PATH=/venv/bin:$PATH - -# change this entrypoint if it is not the same as the repo -ENTRYPOINT ["python3-pip-skeleton"] -CMD ["--version"] diff --git a/setup.cfg b/setup.cfg index abe2919df..ba377343e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,6 +12,7 @@ classifiers = Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 [options] python_requires = >=3.8 @@ -50,8 +51,6 @@ dev = [options.packages.find] where = src -# Don't include our tests directory in the distribution -exclude = tests # Specify any package data to be included in the wheel below. # [options.package_data] From fa99c26a72861597d419620622d859df9d65a722 Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Mon, 14 Nov 2022 13:08:36 +0000 Subject: [PATCH 27/76] Mount ssh & inputrc in mounts list --- .devcontainer/devcontainer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1046ef9ef..7c7d6da12 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -25,11 +25,11 @@ "initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'", "runArgs": [ "--net=host", - "--security-opt=label=type:container_runtime_t", - "-v=${localEnv:HOME}/.ssh:/root/.ssh", - "-v=${localEnv:HOME}/.inputrc:/root/.inputrc" + "--security-opt=label=type:container_runtime_t" ], "mounts": [ + "source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind", + "source=${localEnv:HOME}/.inputrc,target=/root/.inputrc,type=bind", // map in home directory - not strictly necessary but useful "source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached" ], From c5f583f6cce94d157d45a3288e62332ace63097a Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Fri, 11 Nov 2022 15:44:26 +0000 Subject: [PATCH 28/76] Moved config to pyproject.toml --- .vscode/extensions.json | 3 +- pyproject.toml | 108 ++++++++++++++++++++++++++ setup.cfg | 125 ------------------------------ tests/test_boilerplate_removed.py | 14 ++-- 4 files changed, 116 insertions(+), 134 deletions(-) delete mode 100644 setup.cfg diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 041f89441..fe4a5809b 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,6 +3,7 @@ "ms-vscode-remote.remote-containers", "ms-python.vscode-pylance", "ms-python.python", - "ryanluker.vscode-coverage-gutters" + "ryanluker.vscode-coverage-gutters", + "tamasfe.even-better-toml" ] } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 1b8c998a7..1c7104559 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,5 +2,113 @@ requires = ["setuptools>=64", "setuptools_scm[toml]>=6.2", "wheel"] build-backend = "setuptools.build_meta" +[project] +name = "python3-pip-skeleton" +classifiers = [ + "Development Status :: 3 - Alpha", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", +] +description = "One line description of your module" +dependencies = [] # Add project dependencies here, e.g. ["click", "numpy"] +dynamic = ["version"] +license.file = "LICENSE" +readme = "README.rst" +requires-python = ">=3.8" + +[project.optional-dependencies] +dev = [ + "black", + "isort", + "mypy", + "flake8", + "flake8-isort", + "Flake8-pyproject", + "pipdeptree", + "pre-commit", + "pydata-sphinx-theme", + "pytest-cov", + "setuptools_scm[toml]>=6.2", + "sphinx-autobuild", + "sphinx-copybutton", + "sphinx-design", + "tox", + "tox-direct", + "types-mock", +] + +[project.scripts] +python3-pip-skeleton = "python3_pip_skeleton.__main__:main" + +[project.urls] +GitHub = "https://github.com/DiamondLightSource/python3-pip-skeleton" + +[[project.authors]] # Further authors may be added by duplicating this section +email = "email@address.com" +name = "Firstname Lastname" + + [tool.setuptools_scm] write_to = "src/python3_pip_skeleton/_version.py" + +[tool.mypy] +ignore_missing_imports = true # Ignore missing stubs in imported modules + +[tool.isort] +float_to_top = true +profile = "black" + +[tool.flake8] +extend-ignore = [ + "E203", # See https://github.com/PyCQA/pycodestyle/issues/373 + "F811", # support typing.overload decorator + "F722", # allow Annotated[typ, some_func("some string")] +] +max-line-length = 88 # Respect black's line length (default 88), +exclude = [".tox", "venv"] + + +[tool.pytest.ini_options] +# Run pytest with all our checkers, and don't spam us with massive tracebacks on error +addopts = """ + --tb=native -vv --doctest-modules --doctest-glob="*.rst" + --cov=python3_pip_skeleton --cov-report term --cov-report xml:cov.xml + """ +# https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings +filterwarnings = "error" +# Doctest python code in docs, python code in src docstrings, test functions in tests +testpaths = "docs src tests" + +[tool.coverage.run] +data_file = "/tmp/python3_pip_skeleton.coverage" + +[tool.coverage.paths] +# Tests are run from installed location, map back to the src directory +source = ["src", "**/site-packages/"] + +# tox must currently be configured via an embedded ini string +# See: https://github.com/tox-dev/tox/issues/999 +[tool.tox] +legacy_tox_ini = """ +[tox] +skipsdist=True + +[testenv:{pre-commit,mypy,pytest,docs}] +# Don't create a virtualenv for the command, requires tox-direct plugin +direct = True +passenv = * +allowlist_externals = + pytest + pre-commit + mypy + sphinx-build + sphinx-autobuild +commands = + pytest: pytest {posargs} + mypy: mypy src tests {posargs} + pre-commit: pre-commit run --all-files {posargs} + docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html +""" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index ba377343e..000000000 --- a/setup.cfg +++ /dev/null @@ -1,125 +0,0 @@ -[metadata] -name = python3-pip-skeleton -description = One line description of your module -url = https://github.com/DiamondLightSource/python3-pip-skeleton -author = Firstname Lastname -author_email = email@address.com -license = Apache License 2.0 -long_description = file: README.rst -long_description_content_type = text/x-rst -classifiers = - License :: OSI Approved :: Apache Software License - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - -[options] -python_requires = >=3.8 -packages = find: -# =src is interpreted as {"": "src"} -# as per recommendation here https://hynek.me/articles/testing-packaging/ -package_dir = - =src - -setup_requires = - setuptools_scm[toml]>=6.2 - -# Specify any package dependencies below. -# install_requires = -# numpy -# scipy - -[options.extras_require] -# For development tests/docs -dev = - black==22.10.0 - flake8-isort - isort>5.0 - mypy - pipdeptree - pre-commit - pydata-sphinx-theme < 0.10.1 - pytest-cov - setuptools_scm[toml]>=6.2 - sphinx-autobuild - sphinx-copybutton - sphinx-design - tox - tox-direct - types-mock - -[options.packages.find] -where = src - -# Specify any package data to be included in the wheel below. -# [options.package_data] -# python3_pip_skeleton = -# subpackage/*.yaml - -[options.entry_points] -# Include a command line script -console_scripts = - python3-pip-skeleton = python3_pip_skeleton.__main__:main - -[mypy] -# Ignore missing stubs for modules we use -ignore_missing_imports = True - -[isort] -profile=black -float_to_top=true - -[flake8] -# Make flake8 respect black's line length (default 88), -max-line-length = 88 -extend-ignore = - E203, # See https://github.com/PyCQA/pycodestyle/issues/373 - F811, # support typing.overload decorator - F722, # allow Annotated[typ, some_func("some string")] -exclude = - .tox - venv - -[tool:pytest] -# Run pytest with all our checkers, and don't spam us with massive tracebacks on error -addopts = - --tb=native -vv --doctest-modules --doctest-glob="*.rst" - --cov=python3_pip_skeleton --cov-report term --cov-report xml:cov.xml -# https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings -filterwarnings = error -# Doctest python code in docs, python code in src docstrings, test functions in tests -testpaths = - docs src tests - -[coverage:run] -data_file = /tmp/python3_pip_skeleton.coverage - -[coverage:paths] -# Tests are run from installed location, map back to the src directory -source = - src - **/site-packages/ - -# Use tox to provide parallel linting and testing -# NOTE that we pre-install all tools in the dev dependencies (including tox). -# Hence the use of allowlist_externals instead of using the tox virtualenvs. -# This ensures a match between developer time tools in the IDE and tox tools. -[tox:tox] -skipsdist = True - -[testenv:{pre-commit,mypy,pytest,docs}] -# Don't create a virtualenv for the command, requires tox-direct plugin -direct = True -passenv = * -allowlist_externals = - pytest - pre-commit - mypy - sphinx-build - sphinx-autobuild -commands = - pytest: pytest {posargs} - mypy: mypy src tests {posargs} - pre-commit: pre-commit run --all-files {posargs} - docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html diff --git a/tests/test_boilerplate_removed.py b/tests/test_boilerplate_removed.py index f5204fa97..b823c53b6 100644 --- a/tests/test_boilerplate_removed.py +++ b/tests/test_boilerplate_removed.py @@ -2,7 +2,7 @@ This file checks that all the example boilerplate text has been removed. It can be deleted when all the contained tests pass """ -import configparser +from importlib.metadata import metadata from pathlib import Path ROOT = Path(__file__).parent.parent @@ -24,14 +24,12 @@ def assert_not_contains_text(path: str, text: str, explanation: str): skeleton_check(text in contents, f"Please change ./{path} {explanation}") -# setup.cfg -def test_module_description(): - conf = configparser.ConfigParser() - conf.read("setup.cfg") - description = conf["metadata"]["description"] +# pyproject.toml +def test_module_summary(): + summary = metadata("python3-pip-skeleton")["summary"] skeleton_check( - "One line description of your module" in description, - "Please change description in ./setup.cfg " + "One line description of your module" in summary, + "Please change project.description in ./pyproject.toml " "to be a one line description of your module", ) From a08124fd6d4950732098ab3af7e3c781690ec7c2 Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Thu, 17 Nov 2022 05:20:59 +0000 Subject: [PATCH 29/76] add version label to container registry push --- .github/workflows/code.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 200b07b6c..a3a1c4870 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -160,6 +160,7 @@ jobs: push: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }} load: ${{ ! (github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) }} tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} context: .devcontainer # If you have a long docker build, uncomment the following to turn on caching # For short build times this makes it a little slower From d97fd677d6e7e666aaf6c8d1e079d338e75e00db Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Fri, 11 Nov 2022 16:06:36 +0000 Subject: [PATCH 30/76] Use importlib.metadata to get package version --- pyproject.toml | 1 - src/python3_pip_skeleton/__init__.py | 12 +++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1c7104559..0bcc80db8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,6 @@ dev = [ "pre-commit", "pydata-sphinx-theme", "pytest-cov", - "setuptools_scm[toml]>=6.2", "sphinx-autobuild", "sphinx-copybutton", "sphinx-design", diff --git a/src/python3_pip_skeleton/__init__.py b/src/python3_pip_skeleton/__init__.py index 0fe6655ff..ef94dff17 100644 --- a/src/python3_pip_skeleton/__init__.py +++ b/src/python3_pip_skeleton/__init__.py @@ -1,12 +1,6 @@ -try: - # Use live version from git - from setuptools_scm import get_version +from importlib.metadata import version - # Warning: If the install is nested to the same depth, this will always succeed - __version__ = get_version(root="../../", relative_to=__file__) - del get_version -except (ImportError, LookupError): - # Use installed version - from ._version import __version__ +__version__ = version("python3-pip-skeleton") +del version __all__ = ["__version__"] From 7383739e7f5ae5cc4309eded64774c7c4bf58c1d Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Thu, 17 Nov 2022 12:02:43 +0000 Subject: [PATCH 31/76] Make twine check strict --- .github/workflows/code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index a3a1c4870..5ff244200 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -97,7 +97,7 @@ jobs: path: dist - name: Check for packaging errors - run: pipx run twine check dist/* + run: pipx run twine check --strict dist/* - name: Install python packages uses: ./.github/actions/install_requirements From 15a1d441d72fc2132bae767d0a947dccfe22ba33 Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Thu, 24 Nov 2022 14:44:08 +0000 Subject: [PATCH 32/76] Don't check switcher if not published - pydata-sphinx-theme 0.11 started checking switcher - this meant you couldn't bootstrap a gh-pages build - pydata-sphinx-theme 0.12 put in an option not to check - but we want checking if the file exists - so only check if we can get the json file - and suggest user turns pages on if we can't --- docs/conf.py | 17 ++++++++++++++++- pyproject.toml | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index c4c2126a2..6bd4d2306 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,9 +4,12 @@ # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html +import sys from pathlib import Path from subprocess import check_output +import requests + import python3_pip_skeleton # -- General configuration ------------------------------------------------ @@ -126,6 +129,17 @@ html_theme = "pydata_sphinx_theme" github_repo = project github_user = "DiamondLightSource" +switcher_json = f"https://{github_user}.github.io/{github_repo}/switcher.json" +# Don't check switcher if it doesn't exist, but warn in a non-failing way +check_switcher = requests.get(switcher_json).ok +if not check_switcher: + print( + "*** Can't read version switcher, is GitHub pages enabled? \n" + " Once Docs CI job has successfully run once, set the " + "Github pages source branch to be 'gh-pages' at:\n" + f" https://github.com/{github_user}/{github_repo}/settings/pages", + file=sys.stderr, + ) # Theme options for pydata_sphinx_theme html_theme_options = dict( @@ -142,9 +156,10 @@ ) ], switcher=dict( - json_url=f"https://{github_user}.github.io/{github_repo}/switcher.json", + json_url=switcher_json, version_match=version, ), + check_switcher=check_switcher, navbar_end=["theme-switcher", "icon-links", "version-switcher"], external_links=[ dict( diff --git a/pyproject.toml b/pyproject.toml index 0bcc80db8..5e06a4f06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ dev = [ "Flake8-pyproject", "pipdeptree", "pre-commit", - "pydata-sphinx-theme", + "pydata-sphinx-theme>=0.12", "pytest-cov", "sphinx-autobuild", "sphinx-copybutton", From 6f0604bf457831bc4824de810461ccbd19fd854c Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Fri, 25 Nov 2022 13:43:30 +0000 Subject: [PATCH 33/76] Don't use flake8==6 until plugins catch up https://github.com/john-hen/Flake8-pyproject/issues/12 --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5e06a4f06..bf1da9b47 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,8 @@ dev = [ "black", "isort", "mypy", - "flake8", + # https://github.com/john-hen/Flake8-pyproject/issues/12 + "flake8<6", "flake8-isort", "Flake8-pyproject", "pipdeptree", From 7a688851d9c4491d420b92c624da16408cabddf1 Mon Sep 17 00:00:00 2001 From: Tom Cobb Date: Mon, 28 Nov 2022 11:45:00 +0000 Subject: [PATCH 34/76] Remove flake8 constraint Also shrink dep list where intermediate modules are covered by others --- pyproject.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bf1da9b47..0397a22d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,10 +22,7 @@ requires-python = ">=3.8" [project.optional-dependencies] dev = [ "black", - "isort", "mypy", - # https://github.com/john-hen/Flake8-pyproject/issues/12 - "flake8<6", "flake8-isort", "Flake8-pyproject", "pipdeptree", @@ -35,7 +32,6 @@ dev = [ "sphinx-autobuild", "sphinx-copybutton", "sphinx-design", - "tox", "tox-direct", "types-mock", ] From d4633ab1f059eebbd76f08ddfec979b36f81396c Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Fri, 18 Nov 2022 17:26:38 +0000 Subject: [PATCH 35/76] Add agreed upon extensions to customizations --- .devcontainer/devcontainer.json | 16 +++++++++++----- .vscode/extensions.json | 6 +++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7c7d6da12..7f5c7e3be 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -16,11 +16,17 @@ "settings": { "python.defaultInterpreterPath": "/venv/bin/python" }, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-python.python", - "ms-python.vscode-pylance" - ], + "customizations": { + "vscode": { + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python", + "tamasfe.even-better-toml", + "redhat.vscode-yaml", + "ryanluker.vscode-coverage-gutters" + ] + } + }, // Make sure the files we are mapping into the container exist on the host "initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'", "runArgs": [ diff --git a/.vscode/extensions.json b/.vscode/extensions.json index fe4a5809b..819229919 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,9 +1,9 @@ { "recommendations": [ "ms-vscode-remote.remote-containers", - "ms-python.vscode-pylance", "ms-python.python", - "ryanluker.vscode-coverage-gutters", - "tamasfe.even-better-toml" + "tamasfe.even-better-toml", + "redhat.vscode-yaml", + "ryanluker.vscode-coverage-gutters" ] } \ No newline at end of file From f916925ab167a0aa79d7c34e63ebe68d06631aab Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Fri, 25 Nov 2022 16:29:06 +0000 Subject: [PATCH 36/76] Add common-utils to dev container features --- .devcontainer/devcontainer.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7f5c7e3be..6c707ab0e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,6 +12,13 @@ "remoteEnv": { "DISPLAY": "${localEnv:DISPLAY}" }, + // Add the URLs of features you want added when the container is built. + "features": { + "ghcr.io/devcontainers/features/common-utils:1": { + "username": "none", + "upgradePackages": false + } + }, // Set *default* container specific settings.json values on container create. "settings": { "python.defaultInterpreterPath": "/venv/bin/python" From 4981421ca3aab9b9b39ae8dcace211ab519d3187 Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Fri, 2 Dec 2022 15:48:42 +0000 Subject: [PATCH 37/76] Link to condatiners.dev for devcontainer spec --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6c707ab0e..f5e71fe9a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,4 +1,4 @@ -// For format details, see https://aka.ms/devcontainer.json +// For format details, see https://containers.dev/implementors/json_reference/ { "name": "Python 3 Developer Container", "build": { From 7300883bd8a3cb5ba2e338c728d320cbc5681922 Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Wed, 7 Dec 2022 13:36:36 +0000 Subject: [PATCH 38/76] Remove unused matrix from linkcheck CI --- .github/workflows/linkcheck.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 42d199c4f..02d8df4ca 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -8,11 +8,6 @@ on: jobs: docs: - strategy: - fail-fast: false - matrix: - python: ["3.10"] - runs-on: ubuntu-latest steps: From f67ddd4e6c86db2521c6855c8b6d4bf0aab20089 Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Wed, 30 Nov 2022 16:44:32 +0000 Subject: [PATCH 39/76] Add publish to anaconda step --- .github/workflows/code.yml | 38 +++++++++++++++++++++++++++++++++++++- README.rst | 7 ++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 5ff244200..7c671aaec 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -170,11 +170,42 @@ jobs: - name: Test cli works in runtime image run: docker run ${{ env.IMAGE_REPOSITORY }} --version + conda: + needs: [dist] + runs-on: ubuntu-latest + + steps: + - uses: actions/download-artifact@v3 + + - name: Create Conda recipe + run: | + mkdir -p conda/recipe + pipx run grayskull pypi -o conda/recipe dist/*.tar.gz + + - name: Install conda-build + run: conda install -y conda-build + + - name: Build Conda distribution + run: | + mkdir -p conda/build + conda build --output-folder conda/build conda/recipe/*/meta.yaml + + - name: Upload conda build + uses: actions/upload-artifact@v3 + with: + name: conda_build + path: | + conda/build/ + !conda/build/*/.cache + release: # upload to PyPI and make a release on every tag - needs: [lint, dist, test] + needs: [lint, dist, test, conda] if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }} runs-on: ubuntu-latest + env: + HAS_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN != '' }} + HAS_ANACONDA_TOKEN: ${{ secrets.ANACONDA_TOKEN != '' }} steps: - uses: actions/download-artifact@v3 @@ -197,6 +228,11 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Publish to PyPI + if: ${{ env.HAS_PYPI_TOKEN }} uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.PYPI_TOKEN }} + + - name: Publish to Anaconda + if: ${{ env.HAS_ANACONDA_TOKEN }} + run: pipx run --spec anaconda-client anaconda --token ${{ secrets.ANACONDA_TOKEN }} upload conda_build/noarch/*.tar.bz2 diff --git a/README.rst b/README.rst index a014631eb..78f7f140b 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ python3-pip-skeleton =========================== -|code_ci| |docs_ci| |coverage| |pypi_version| |license| +|code_ci| |docs_ci| |coverage| |pypi_version| |anaconda_version| |license| .. note:: @@ -14,6 +14,7 @@ how it does it, and why people should use it. ============== ============================================================== PyPI ``pip install python3-pip-skeleton`` +Conda ``conda install -c DiamondLightSource python3-pip-skeleton`` Source code https://github.com/DiamondLightSource/python3-pip-skeleton Documentation https://DiamondLightSource.github.io/python3-pip-skeleton Releases https://github.com/DiamondLightSource/python3-pip-skeleton/releases @@ -49,6 +50,10 @@ Or if it is a commandline tool then you might put some example commands here:: :target: https://pypi.org/project/python3-pip-skeleton :alt: Latest PyPI version +.. |anaconda_version| image:: https://anaconda.org/DiamondLightSource/python3-pip-skeleton/badges/version.svg + :target: https://anaconda.org/DiamondLightSource/python3-pip-skeleton + :alt: Latest Anaconda version + .. |license| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg :target: https://opensource.org/licenses/Apache-2.0 :alt: Apache License From e2e7d86d53048ab88c30cd311ac51dcce2c2a8d2 Mon Sep 17 00:00:00 2001 From: Garry O'Donnell Date: Tue, 20 Dec 2022 10:41:01 +0000 Subject: [PATCH 40/76] Remove conda build & publish from CI --- .github/workflows/code.yml | 35 +---------------------------------- README.rst | 7 +------ 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 7c671aaec..cf957a4f6 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -170,42 +170,13 @@ jobs: - name: Test cli works in runtime image run: docker run ${{ env.IMAGE_REPOSITORY }} --version - conda: - needs: [dist] - runs-on: ubuntu-latest - - steps: - - uses: actions/download-artifact@v3 - - - name: Create Conda recipe - run: | - mkdir -p conda/recipe - pipx run grayskull pypi -o conda/recipe dist/*.tar.gz - - - name: Install conda-build - run: conda install -y conda-build - - - name: Build Conda distribution - run: | - mkdir -p conda/build - conda build --output-folder conda/build conda/recipe/*/meta.yaml - - - name: Upload conda build - uses: actions/upload-artifact@v3 - with: - name: conda_build - path: | - conda/build/ - !conda/build/*/.cache - release: # upload to PyPI and make a release on every tag - needs: [lint, dist, test, conda] + needs: [lint, dist, test] if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }} runs-on: ubuntu-latest env: HAS_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN != '' }} - HAS_ANACONDA_TOKEN: ${{ secrets.ANACONDA_TOKEN != '' }} steps: - uses: actions/download-artifact@v3 @@ -232,7 +203,3 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.PYPI_TOKEN }} - - - name: Publish to Anaconda - if: ${{ env.HAS_ANACONDA_TOKEN }} - run: pipx run --spec anaconda-client anaconda --token ${{ secrets.ANACONDA_TOKEN }} upload conda_build/noarch/*.tar.bz2 diff --git a/README.rst b/README.rst index 78f7f140b..a014631eb 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ python3-pip-skeleton =========================== -|code_ci| |docs_ci| |coverage| |pypi_version| |anaconda_version| |license| +|code_ci| |docs_ci| |coverage| |pypi_version| |license| .. note:: @@ -14,7 +14,6 @@ how it does it, and why people should use it. ============== ============================================================== PyPI ``pip install python3-pip-skeleton`` -Conda ``conda install -c DiamondLightSource python3-pip-skeleton`` Source code https://github.com/DiamondLightSource/python3-pip-skeleton Documentation https://DiamondLightSource.github.io/python3-pip-skeleton Releases https://github.com/DiamondLightSource/python3-pip-skeleton/releases @@ -50,10 +49,6 @@ Or if it is a commandline tool then you might put some example commands here:: :target: https://pypi.org/project/python3-pip-skeleton :alt: Latest PyPI version -.. |anaconda_version| image:: https://anaconda.org/DiamondLightSource/python3-pip-skeleton/badges/version.svg - :target: https://anaconda.org/DiamondLightSource/python3-pip-skeleton - :alt: Latest Anaconda version - .. |license| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg :target: https://opensource.org/licenses/Apache-2.0 :alt: Apache License From 8eb1194091b92adbf07f19090f9f59a1e8086b0b Mon Sep 17 00:00:00 2001 From: Callum Forrester Date: Thu, 5 Jan 2023 09:05:51 +0000 Subject: [PATCH 41/76] Stop checking switcher in docs build --- docs/conf.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 6bd4d2306..7022f617c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -130,9 +130,8 @@ github_repo = project github_user = "DiamondLightSource" switcher_json = f"https://{github_user}.github.io/{github_repo}/switcher.json" -# Don't check switcher if it doesn't exist, but warn in a non-failing way -check_switcher = requests.get(switcher_json).ok -if not check_switcher: +switcher_exists = requests.get(switcher_json).ok +if not switcher_exists: print( "*** Can't read version switcher, is GitHub pages enabled? \n" " Once Docs CI job has successfully run once, set the " @@ -142,6 +141,14 @@ ) # Theme options for pydata_sphinx_theme +# We don't check switcher because there are 3 possible states for a repo: +# 1. New project, docs are not published so there is no switcher +# 2. Existing project with latest skeleton, switcher exists and works +# 3. Existing project with old skeleton that makes broken switcher, +# switcher exists but is broken +# Point 3 makes checking switcher difficult, because the updated skeleton +# will fix the switcher at the end of the docs workflow, but never gets a chance +# to complete as the docs build warns and fails. html_theme_options = dict( logo=dict( text=project, @@ -159,7 +166,7 @@ json_url=switcher_json, version_match=version, ), - check_switcher=check_switcher, + check_switcher=False, navbar_end=["theme-switcher", "icon-links", "version-switcher"], external_links=[ dict( From 0f6456ec5ea49753f95e8b4a456456fc4912b458 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 16:10:46 +0000 Subject: [PATCH 42/76] Bump softprops/action-gh-release from 0.1.14 to 0.1.15 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 0.1.14 to 0.1.15. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/1e07f4398721186383de40550babbdf2b84acfc5...de2c0eb89ae2a093876385947365aca7b0e5f844) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index cf957a4f6..14802fef7 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -188,7 +188,7 @@ jobs: - name: Github Release # We pin to the SHA, not the tag, for security reasons. # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions - uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14 + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15 with: prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }} files: | From b9bf30b9c5f8e9884af62259297495326e6c43c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 16:06:56 +0000 Subject: [PATCH 43/76] Bump peaceiris/actions-gh-pages from 3.9.0 to 3.9.1 Bumps [peaceiris/actions-gh-pages](https://github.com/peaceiris/actions-gh-pages) from 3.9.0 to 3.9.1. - [Release notes](https://github.com/peaceiris/actions-gh-pages/releases) - [Changelog](https://github.com/peaceiris/actions-gh-pages/blob/main/CHANGELOG.md) - [Commits](https://github.com/peaceiris/actions-gh-pages/compare/de7ea6f8efb354206b205ef54722213d99067935...64b46b4226a4a12da2239ba3ea5aa73e3163c75b) --- updated-dependencies: - dependency-name: peaceiris/actions-gh-pages dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 94fa2151e..c510d577a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -46,7 +46,7 @@ jobs: if: github.event_name == 'push' && github.actor != 'dependabot[bot]' # We pin to the SHA, not the tag, for security reasons. # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions - uses: peaceiris/actions-gh-pages@de7ea6f8efb354206b205ef54722213d99067935 # v3.9.0 + uses: peaceiris/actions-gh-pages@64b46b4226a4a12da2239ba3ea5aa73e3163c75b # v3.9.1 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: .github/pages From db76a312c5195d4f46feaa3ea5b1b3d4617dd9dc Mon Sep 17 00:00:00 2001 From: tizayi Date: Mon, 9 Jan 2023 14:04:56 +0000 Subject: [PATCH 44/76] simplify local container workflow --- .devcontainer/devcontainer.json | 2 +- .github/workflows/code.yml | 5 +++-- .devcontainer/Dockerfile => Dockerfile | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) rename .devcontainer/Dockerfile => Dockerfile (98%) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f5e71fe9a..7a30e9bee 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ { "name": "Python 3 Developer Container", "build": { - "dockerfile": "Dockerfile", + "dockerfile": "../Dockerfile", "target": "build", // Only upgrade pip, we will install the project below "args": { diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 14802fef7..9686f0d42 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -129,7 +129,7 @@ jobs: - name: Download wheel and lockfiles uses: actions/download-artifact@v3 with: - path: .devcontainer + path: artifacts/ - name: Log in to GitHub Docker Registry if: github.event_name != 'pull_request' @@ -161,7 +161,8 @@ jobs: load: ${{ ! (github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - context: .devcontainer + context: artifacts/ + file: ./Dockerfile # If you have a long docker build, uncomment the following to turn on caching # For short build times this makes it a little slower #cache-from: type=gha diff --git a/.devcontainer/Dockerfile b/Dockerfile similarity index 98% rename from .devcontainer/Dockerfile rename to Dockerfile index b6b4bef96..31d05606f 100644 --- a/.devcontainer/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ # FROM python:3.11 as build -ARG PIP_OPTIONS +ARG PIP_OPTIONS=. # Add any system dependencies for the developer/build environment here e.g. # RUN apt-get update && apt-get upgrade -y && \ From db2f8e3410c9190dbd10a5b48b0948da9b35478c Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Wed, 18 Jan 2023 14:16:09 +0000 Subject: [PATCH 45/76] add how to do pin requirements doc --- docs/developer/how-to/pin-requirements.rst | 74 ++++++++++++++++++++++ docs/developer/index.rst | 1 + 2 files changed, 75 insertions(+) create mode 100644 docs/developer/how-to/pin-requirements.rst diff --git a/docs/developer/how-to/pin-requirements.rst b/docs/developer/how-to/pin-requirements.rst new file mode 100644 index 000000000..89639623a --- /dev/null +++ b/docs/developer/how-to/pin-requirements.rst @@ -0,0 +1,74 @@ +Pinning Requirements +==================== + +Introduction +------------ + +By design this project only defines dependencies in one place, i.e. in +the ``requires`` table in ``pyproject.toml``. + +In the ``requires`` table it is possible to pin versions of some dependencies +as needed. For library projects it is best to leave pinning to a minimum so +that your library can be used by the widest range of applications. + +When CI builds the project it will use the latest compatible set of +dependencies available (after applying your pins and any dependencies' pins). + +This approach means that there is a possibility that a future build may +break because an updated release of a dependency has made a breaking change. + +The correct way to fix such an issue is to work out the minimum pinning in +``requires`` that will resolve the problem. However this can be quite hard to +do and may be time consuming when simply trying to release a minor update. + +For this reason we provide a mechanism for locking all dependencies to +the same version as a previous successful release. This is a quick fix that +should guarantee a successful CI build. + +Finding the lock files +---------------------- + +Every release of the project will have a set of requirements files published +as release assets. + +For example take a look at the release page for python3-pip-skeleton-cli here: +https://github.com/DiamondLightSource/python3-pip-skeleton-cli/releases/tag/3.3.0 + +There is a list of requirements*.txt files showing as assets on the release. + +There is one file for each time the CI installed the project into a virtual +environment. There are multiple of these as the CI creates a number of +different environments. + +The files are created using ``pip freeze`` and will contain a full list +of the dependencies and sub-dependencies with pinned versions. + +You can download any of these files by clicking on them. It is best to use +the one that ran with the lowest Python version as this is more likely to +be compatible with all the versions of Python in the test matrix. +i.e. ``requirements-test-ubuntu-latest-3.8.txt`` in this example. + +Applying the lock file +---------------------- + +To apply a lockfile: + +- copy the requirements file you have downloaded to the root of your + repository +- rename it to requirements.txt +- commit it into the repo +- push the changes + +The CI looks for a requirements.txt in the root and will pass it to pip +when installing each of the test environments. pip will then install exactly +the same set of packages as the previous release. + +Removing dependency locking from CI +----------------------------------- + +Once the reasons for locking the build have been resolved it is a good idea +to go back to an unlocked build. This is because you get an early indication +of any incoming problems. + +To restore unlocked builds in CI simply remove requirements.txt from the root +of the repo and push. diff --git a/docs/developer/index.rst b/docs/developer/index.rst index bf291875f..08d01270d 100644 --- a/docs/developer/index.rst +++ b/docs/developer/index.rst @@ -32,6 +32,7 @@ side-bar. how-to/lint how-to/update-tools how-to/make-release + how-to/pin-requirements +++ From dace85fd1d8ed0885e52be6ce2588cc6937134ff Mon Sep 17 00:00:00 2001 From: Giles Knap Date: Thu, 19 Jan 2023 14:23:01 +0000 Subject: [PATCH 46/76] add local container testing docs --- docs/developer/how-to/test-container.rst | 25 ++++++++++++++++++++++++ docs/developer/index.rst | 1 + 2 files changed, 26 insertions(+) create mode 100644 docs/developer/how-to/test-container.rst diff --git a/docs/developer/how-to/test-container.rst b/docs/developer/how-to/test-container.rst new file mode 100644 index 000000000..a4a43a6ff --- /dev/null +++ b/docs/developer/how-to/test-container.rst @@ -0,0 +1,25 @@ +Container Local Build and Test +============================== + +CI builds a runtime container for the project. The local tests +checks available via ``tox -p`` do not verify this because not +all developers will have docker installed locally. + +If CI is failing to build the container, then it is best to fix and +test the problem locally. This would require that you have docker +or podman installed on your local workstation. + +In the following examples the command ``docker`` is interchangeable with +``podman`` depending on which container cli you have installed. + +To build the container and call it ``test``:: + + cd + docker build -t test . + +To verify that the container runs:: + + docker run -it test --help + +You can pass any other command line parameters to your application +instead of --help. diff --git a/docs/developer/index.rst b/docs/developer/index.rst index 08d01270d..8a6369b9c 100644 --- a/docs/developer/index.rst +++ b/docs/developer/index.rst @@ -33,6 +33,7 @@ side-bar. how-to/update-tools how-to/make-release how-to/pin-requirements + how-to/test-container +++ From c4a3e7c18acaad5dc2e016b93ca739c7f7486b6a Mon Sep 17 00:00:00 2001 From: AlexWells Date: Wed, 25 Jan 2023 11:24:13 +0000 Subject: [PATCH 47/76] Fix reference to non-existent setup.cfg file --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index f8fcdb4f2..f65cb376b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,7 +15,7 @@ ], "console": "integratedTerminal", "env": { - // The default config in setup.cfg's "[tool:pytest]" adds coverage. + // The default config in pyproject.toml's "[tool.pytest.ini_options]" adds coverage. // Cannot have coverage and debugging at the same time. // https://github.com/microsoft/vscode-python/issues/693 "PYTEST_ADDOPTS": "--no-cov" From ea63670bd91e27958085c31d36ee4bc72f71d306 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Fri, 27 Jan 2023 15:40:17 +0000 Subject: [PATCH 48/76] changed to use '[dev]' instead of [dev] in the docs --- .devcontainer/devcontainer.json | 4 ++-- docs/developer/tutorials/dev-install.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7a30e9bee..44de8d36a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -50,5 +50,5 @@ "workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind", "workspaceFolder": "${localWorkspaceFolder}", // After the container is created, install the python project in editable form - "postCreateCommand": "pip install -e .[dev]" -} \ No newline at end of file + "postCreateCommand": "pip install -e '.[dev]'" +} diff --git a/docs/developer/tutorials/dev-install.rst b/docs/developer/tutorials/dev-install.rst index c26326839..7b50cc458 100644 --- a/docs/developer/tutorials/dev-install.rst +++ b/docs/developer/tutorials/dev-install.rst @@ -28,7 +28,7 @@ requires python 3.8 or later) or to run in a container under `VSCode $ cd python3-pip-skeleton $ python3 -m venv venv $ source venv/bin/activate - $ pip install -e .[dev] + $ pip install -e '.[dev]' .. tab-item:: VSCode devcontainer From bfe204ab020181d1e162adc6dafc36a97cdb57c0 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Fri, 27 Jan 2023 11:07:39 +0000 Subject: [PATCH 49/76] Removed scheduled job in code.yaml and added keepalive-workflow --- .github/workflows/code.yml | 3 --- .github/workflows/linkcheck.yml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 9686f0d42..ab9cd60d0 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -3,9 +3,6 @@ name: Code CI on: push: pull_request: - schedule: - # Run weekly to check latest versions of dependencies - - cron: "0 8 * * WED" env: # The target python version, which must match the Dockerfile version CONTAINER_PYTHON: "3.11" diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 02d8df4ca..6b64fdea9 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -22,3 +22,6 @@ jobs: - name: Check links run: tox -e docs build -- -b linkcheck + + - name: Keepalive Workflow + uses: gautamkrishnar/keepalive-workflow@v1 \ No newline at end of file From 2fd923e1409d32751126b6a3b6159b20302a5df2 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Mon, 6 Feb 2023 11:54:01 +0000 Subject: [PATCH 50/76] Added the link to autogenerate precommit --- docs/developer/how-to/lint.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/developer/how-to/lint.rst b/docs/developer/how-to/lint.rst index 1086c3c40..8f4e92dbb 100644 --- a/docs/developer/how-to/lint.rst +++ b/docs/developer/how-to/lint.rst @@ -15,6 +15,9 @@ commit`` on just the files that have changed:: $ pre-commit install +It is also possible to `automatically enable pre-commit on cloned repositories `_. +This will result in pre-commits being enabled on every repo your user clones from now on. + Fixing issues ------------- From 913fd74c8a15628f64a5823fc7255fcee1c695a2 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Fri, 20 Jan 2023 13:57:36 +0000 Subject: [PATCH 51/76] Made suggested changes --- .../0002-switched-to-pip-skeleton.rst | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst diff --git a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst new file mode 100644 index 000000000..41d90fd4a --- /dev/null +++ b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst @@ -0,0 +1,35 @@ +2. Adopt python3-pip-skeleton for project structure +=================================================== + +Date: 2022-02-18 + +Status +------ + +Accepted + +Context +------- + +We should use the following `pip-skeleton `_. +The skeleton will ensure consistency in developer +environments and package management. + +Decision +-------- + +We have switched to using the skeleton. + +Consequences +------------ + +This module will use a fixed set of tools as developed in python3-pip-skeleton +and can pull from this skeleton to update the packaging to the latest techniques. + +As such, the developer environment may have changed, the following could be +different: + +- linting +- formatting +- pip venv setup +- CI/CD From 9e4055eaa450b844a9dde1b207885d4cf3107194 Mon Sep 17 00:00:00 2001 From: AlexWells Date: Thu, 2 Mar 2023 13:16:56 +0000 Subject: [PATCH 52/76] Add explicit dependency on pytest --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 0397a22d9..977a64982 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ dev = [ "pipdeptree", "pre-commit", "pydata-sphinx-theme>=0.12", + "pytest", "pytest-cov", "sphinx-autobuild", "sphinx-copybutton", From d5ab1fb0a00b5dafc318eca86bdf27894bcfd87a Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Fri, 24 Mar 2023 14:41:47 +0000 Subject: [PATCH 53/76] Made changes --- .pre-commit-config.yaml | 2 +- docs/developer/how-to/build-docs.rst | 2 +- src/python3_pip_skeleton/__main__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5e270b08d..aa2a4cb2c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 + rev: v4.4.0 hooks: - id: check-added-large-files - id: check-yaml diff --git a/docs/developer/how-to/build-docs.rst b/docs/developer/how-to/build-docs.rst index 79e3f780c..0174fc82d 100644 --- a/docs/developer/how-to/build-docs.rst +++ b/docs/developer/how-to/build-docs.rst @@ -13,7 +13,7 @@ docs that pull in docstrings from the code. `documentation_standards` The docs will be built into the ``build/html`` directory, and can be opened -locally with a web browse:: +locally with a web browser:: $ firefox build/html/index.html diff --git a/src/python3_pip_skeleton/__main__.py b/src/python3_pip_skeleton/__main__.py index c680183b0..e348a31e4 100644 --- a/src/python3_pip_skeleton/__main__.py +++ b/src/python3_pip_skeleton/__main__.py @@ -7,7 +7,7 @@ def main(args=None): parser = ArgumentParser() - parser.add_argument("--version", action="version", version=__version__) + parser.add_argument("-v", "--version", action="version", version=__version__) args = parser.parse_args(args) From 9cd95324f544e9bd7cd43479fdabe3b76ef6a504 Mon Sep 17 00:00:00 2001 From: Joshua Appleby Date: Tue, 4 Apr 2023 07:46:53 +0000 Subject: [PATCH 54/76] Add python 3.7 support --- .github/workflows/code.yml | 4 ++-- pyproject.toml | 7 +++++-- src/python3_pip_skeleton/__init__.py | 7 ++++++- tests/test_boilerplate_removed.py | 7 ++++++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index ab9cd60d0..fb468b23d 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -32,12 +32,12 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest"] # can add windows-latest, macos-latest - python: ["3.9", "3.10", "3.11"] + python: ["3.8", "3.9", "3.10", "3.11"] install: ["-e .[dev]"] # Make one version be non-editable to test both paths of version code include: - os: "ubuntu-latest" - python: "3.8" + python: "3.7" install: ".[dev]" runs-on: ${{ matrix.os }} diff --git a/pyproject.toml b/pyproject.toml index 977a64982..2aa5efc0d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,17 +7,20 @@ name = "python3-pip-skeleton" classifiers = [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ] description = "One line description of your module" -dependencies = [] # Add project dependencies here, e.g. ["click", "numpy"] +dependencies = [ + "typing-extensions;python_version<'3.8'", +] # Add project dependencies here, e.g. ["click", "numpy"] dynamic = ["version"] license.file = "LICENSE" readme = "README.rst" -requires-python = ">=3.8" +requires-python = ">=3.7" [project.optional-dependencies] dev = [ diff --git a/src/python3_pip_skeleton/__init__.py b/src/python3_pip_skeleton/__init__.py index ef94dff17..82cce3c2d 100644 --- a/src/python3_pip_skeleton/__init__.py +++ b/src/python3_pip_skeleton/__init__.py @@ -1,4 +1,9 @@ -from importlib.metadata import version +import sys + +if sys.version_info < (3, 8): + from importlib_metadata import version # noqa +else: + from importlib.metadata import version # noqa __version__ = version("python3-pip-skeleton") del version diff --git a/tests/test_boilerplate_removed.py b/tests/test_boilerplate_removed.py index b823c53b6..a0675d9c8 100644 --- a/tests/test_boilerplate_removed.py +++ b/tests/test_boilerplate_removed.py @@ -2,9 +2,14 @@ This file checks that all the example boilerplate text has been removed. It can be deleted when all the contained tests pass """ -from importlib.metadata import metadata +import sys from pathlib import Path +if sys.version_info < (3, 8): + from importlib_metadata import metadata # noqa +else: + from importlib.metadata import metadata # noqa + ROOT = Path(__file__).parent.parent From 64d2a03ba80d52b6d22ca541bb32eb6b455d83f9 Mon Sep 17 00:00:00 2001 From: Callum Forrester Date: Tue, 18 Apr 2023 16:16:32 +0100 Subject: [PATCH 55/76] Include link in dev install tutorial to epics-containers devcontainer page --- docs/developer/tutorials/dev-install.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/developer/tutorials/dev-install.rst b/docs/developer/tutorials/dev-install.rst index 7b50cc458..3a6627a14 100644 --- a/docs/developer/tutorials/dev-install.rst +++ b/docs/developer/tutorials/dev-install.rst @@ -34,9 +34,14 @@ requires python 3.8 or later) or to run in a container under `VSCode .. code:: - $ vscode python3-pip-skeleton + $ code python3-pip-skeleton # Click on 'Reopen in Container' when prompted # Open a new terminal + + .. note:: + + See the epics-containers_ documentation for more complex + use cases, such as integration with podman. See what was installed ---------------------- @@ -58,3 +63,6 @@ This will run in parallel the following checks: - `../how-to/run-tests` - `../how-to/static-analysis` - `../how-to/lint` + + +.. _epics-containers: https://epics-containers.github.io/main/user/tutorials/devcontainer.html \ No newline at end of file From 8d283aa235fd2dc95e3bda5d75bbb3e9133e118a Mon Sep 17 00:00:00 2001 From: AlexWells Date: Tue, 30 May 2023 12:23:29 +0100 Subject: [PATCH 56/76] Improve container build workflow This will test the container before it is pushed to GHCR --- .github/workflows/code.yml | 65 +++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index fb468b23d..4e5e7e233 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -115,6 +115,9 @@ jobs: contents: read packages: write + env: + TEST_TAG: "testing" + steps: - name: Checkout uses: actions/checkout@v3 @@ -136,42 +139,66 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Docker meta + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and export to Docker local cache + uses: docker/build-push-action@v4 + with: + # Note build-args, context, file, and target must all match between this + # step and the later build-push-action, otherwise the second build-push-action + # will attempt to build the image again + build-args: | + PIP_OPTIONS=-r lockfiles/requirements.txt dist/*.whl + context: artifacts/ + file: ./Dockerfile + target: runtime + load: true + tags: ${{ env.TEST_TAG }} + # If you have a long docker build (2+ minutes), uncomment the + # following to turn on caching. For short build times this + # makes it a little slower + #cache-from: type=gha + #cache-to: type=gha,mode=max + + - name: Test cli works in cached runtime image + run: docker run docker.io/library/${{ env.TEST_TAG }} --version + + - name: Create tags for publishing image id: meta uses: docker/metadata-action@v4 with: images: ${{ env.IMAGE_REPOSITORY }} tags: | type=ref,event=tag - type=raw,value=latest + type=raw,value=latest, enable=${{ github.ref_type == 'tag' }} + # type=edge,branch=main + # Add line above to generate image for every commit to given branch, + # and uncomment the end of if clause in next step - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v2 - - - name: Build runtime image + - name: Push cached image to container registry + if: github.ref_type == 'tag' # || github.ref_name == 'main' uses: docker/build-push-action@v3 + # This does not build the image again, it will find the image in the + # Docker cache and publish it with: + # Note build-args, context, file, and target must all match between this + # step and the previous build-push-action, otherwise this step will + # attempt to build the image again build-args: | PIP_OPTIONS=-r lockfiles/requirements.txt dist/*.whl - push: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }} - load: ${{ ! (github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} context: artifacts/ file: ./Dockerfile - # If you have a long docker build, uncomment the following to turn on caching - # For short build times this makes it a little slower - #cache-from: type=gha - #cache-to: type=gha,mode=max - - - name: Test cli works in runtime image - run: docker run ${{ env.IMAGE_REPOSITORY }} --version + target: runtime + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} release: # upload to PyPI and make a release on every tag needs: [lint, dist, test] - if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }} + if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }} runs-on: ubuntu-latest env: HAS_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN != '' }} From c68c75e2fa2578d2f2609abaf20a09b19b1be03e Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Fri, 2 Jun 2023 15:46:56 +0100 Subject: [PATCH 57/76] Changed coverage parameters --- .github/workflows/code.yml | 2 +- .vscode/settings.json | 7 +++++-- pyproject.toml | 3 +-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 4e5e7e233..cbc3e2801 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -63,7 +63,7 @@ jobs: run: pipdeptree - name: Run tests - run: pytest + run: tox -e pytest - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 diff --git a/.vscode/settings.json b/.vscode/settings.json index 2472acfd6..35402dc50 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,10 @@ "python.linting.flake8Enabled": true, "python.linting.mypyEnabled": true, "python.linting.enabled": true, - "python.testing.pytestArgs": [], + "python.testing.pytestArgs": [ + "--cov=python3_pip_skeleton", + "--cov-report xml:cov.xml" + ], "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true, "python.formatting.provider": "black", @@ -12,4 +15,4 @@ "editor.codeActionsOnSave": { "source.organizeImports": true } -} \ No newline at end of file +} diff --git a/pyproject.toml b/pyproject.toml index 2aa5efc0d..ec8e6931d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,7 +75,6 @@ exclude = [".tox", "venv"] # Run pytest with all our checkers, and don't spam us with massive tracebacks on error addopts = """ --tb=native -vv --doctest-modules --doctest-glob="*.rst" - --cov=python3_pip_skeleton --cov-report term --cov-report xml:cov.xml """ # https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings filterwarnings = "error" @@ -107,7 +106,7 @@ allowlist_externals = sphinx-build sphinx-autobuild commands = - pytest: pytest {posargs} + pytest: pytest --cov=python3_pip_skeleton --cov-report term --cov-report xml:cov.xml {posargs} mypy: mypy src tests {posargs} pre-commit: pre-commit run --all-files {posargs} docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html From f02b12ec81d82a39cb4022ffd6e8c3f3f80ac711 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Mon, 5 Jun 2023 08:58:00 +0100 Subject: [PATCH 58/76] Added vscode settings --- .vscode/settings.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 35402dc50..b8cc9ad67 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,10 +3,7 @@ "python.linting.flake8Enabled": true, "python.linting.mypyEnabled": true, "python.linting.enabled": true, - "python.testing.pytestArgs": [ - "--cov=python3_pip_skeleton", - "--cov-report xml:cov.xml" - ], + "python.testing.pytestArgs": ["--cov=python3_pip_skeleton", "--cov-report", "xml:cov.xml"], "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true, "python.formatting.provider": "black", From 3415f1c8b7c9305600d06a6be460cab081556950 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Tue, 20 Jun 2023 11:29:18 +0100 Subject: [PATCH 59/76] Slight changes to the sed command, and ensuring output is utf-8 on windows --- .github/actions/install_requirements/action.yml | 2 +- .github/pages/make_switcher.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/install_requirements/action.yml b/.github/actions/install_requirements/action.yml index 25a146d16..c5d4db43b 100644 --- a/.github/actions/install_requirements/action.yml +++ b/.github/actions/install_requirements/action.yml @@ -32,7 +32,7 @@ runs: mkdir -p lockfiles pip freeze --exclude-editable > lockfiles/${{ inputs.requirements_file }} # delete the self referencing line and make sure it isn't blank - sed -i '/file:/d' lockfiles/${{ inputs.requirements_file }} + sed -i'' -e '/file:/d' lockfiles/${{ inputs.requirements_file }} shell: bash - name: Upload lockfiles diff --git a/.github/pages/make_switcher.py b/.github/pages/make_switcher.py index 39c127726..d70367aec 100755 --- a/.github/pages/make_switcher.py +++ b/.github/pages/make_switcher.py @@ -64,7 +64,7 @@ def write_json(path: Path, repository: str, versions: str): ] text = json.dumps(struct, indent=2) print(f"JSON switcher:\n{text}") - path.write_text(text) + path.write_text(text, encoding="utf-8") def main(args=None): From 553608123944a5e8c6e7843754f350fb6b52bc7f Mon Sep 17 00:00:00 2001 From: AlexWells Date: Fri, 1 Sep 2023 13:47:50 +0100 Subject: [PATCH 60/76] Remove trailing spaces and rationalise newlines Some tools remove trailing whitespace by default on save, so may as well correct the originals. Ensures every file ends with an empty blank line. Again some tools do this automatically. --- .github/actions/install_requirements/action.yml | 1 - .github/pages/index.html | 2 +- .github/workflows/linkcheck.yml | 2 +- .gitignore | 1 - .vscode/extensions.json | 2 +- .vscode/launch.json | 2 +- .vscode/tasks.json | 2 +- docs/developer/how-to/build-docs.rst | 2 +- docs/developer/how-to/lint.rst | 2 -- docs/developer/how-to/make-release.rst | 2 +- docs/developer/reference/standards.rst | 2 +- docs/developer/tutorials/dev-install.rst | 10 +++++----- pyproject.toml | 4 ++-- 13 files changed, 15 insertions(+), 19 deletions(-) diff --git a/.github/actions/install_requirements/action.yml b/.github/actions/install_requirements/action.yml index c5d4db43b..20d7a3adf 100644 --- a/.github/actions/install_requirements/action.yml +++ b/.github/actions/install_requirements/action.yml @@ -55,4 +55,3 @@ runs: fi fi shell: bash - diff --git a/.github/pages/index.html b/.github/pages/index.html index 80f0a0091..c495f39f2 100644 --- a/.github/pages/index.html +++ b/.github/pages/index.html @@ -8,4 +8,4 @@ - \ No newline at end of file + diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 6b64fdea9..70cba115f 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -24,4 +24,4 @@ jobs: run: tox -e docs build -- -b linkcheck - name: Keepalive Workflow - uses: gautamkrishnar/keepalive-workflow@v1 \ No newline at end of file + uses: gautamkrishnar/keepalive-workflow@v1 diff --git a/.gitignore b/.gitignore index 9fbb6bfe0..62dcd9a8d 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,3 @@ venv* # further build artifacts lockfiles/ - diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 819229919..cda78d45e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -6,4 +6,4 @@ "redhat.vscode-yaml", "ryanluker.vscode-coverage-gutters" ] -} \ No newline at end of file +} diff --git a/.vscode/launch.json b/.vscode/launch.json index f65cb376b..3cda74327 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -22,4 +22,4 @@ }, } ] -} \ No newline at end of file +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 946e69d4b..c999e8646 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -13,4 +13,4 @@ "problemMatcher": [], } ] -} \ No newline at end of file +} diff --git a/docs/developer/how-to/build-docs.rst b/docs/developer/how-to/build-docs.rst index 0174fc82d..11a5e6386 100644 --- a/docs/developer/how-to/build-docs.rst +++ b/docs/developer/how-to/build-docs.rst @@ -35,4 +35,4 @@ changes in this directory too:: $ tox -e docs autobuild -- --watch src -.. _sphinx: https://www.sphinx-doc.org/ \ No newline at end of file +.. _sphinx: https://www.sphinx-doc.org/ diff --git a/docs/developer/how-to/lint.rst b/docs/developer/how-to/lint.rst index 8f4e92dbb..ffb6ee5af 100644 --- a/docs/developer/how-to/lint.rst +++ b/docs/developer/how-to/lint.rst @@ -37,5 +37,3 @@ VSCode support The ``.vscode/settings.json`` will run black and isort formatters as well as flake8 checking on save. Issues will be highlighted in the editor window. - - diff --git a/docs/developer/how-to/make-release.rst b/docs/developer/how-to/make-release.rst index 747e44a22..d8f92f854 100644 --- a/docs/developer/how-to/make-release.rst +++ b/docs/developer/how-to/make-release.rst @@ -13,4 +13,4 @@ To make a new release, please follow this checklist: Note that tagging and pushing to the main branch has the same effect except that you will not get the option to edit the release notes. -.. _release: https://github.com/DiamondLightSource/python3-pip-skeleton/releases \ No newline at end of file +.. _release: https://github.com/DiamondLightSource/python3-pip-skeleton/releases diff --git a/docs/developer/reference/standards.rst b/docs/developer/reference/standards.rst index b78a719e1..06c4af539 100644 --- a/docs/developer/reference/standards.rst +++ b/docs/developer/reference/standards.rst @@ -61,4 +61,4 @@ Docs follow the underlining convention:: .. seealso:: - How-to guide `../how-to/build-docs` \ No newline at end of file + How-to guide `../how-to/build-docs` diff --git a/docs/developer/tutorials/dev-install.rst b/docs/developer/tutorials/dev-install.rst index 3a6627a14..183b1893a 100644 --- a/docs/developer/tutorials/dev-install.rst +++ b/docs/developer/tutorials/dev-install.rst @@ -37,10 +37,10 @@ requires python 3.8 or later) or to run in a container under `VSCode $ code python3-pip-skeleton # Click on 'Reopen in Container' when prompted # Open a new terminal - - .. note:: - - See the epics-containers_ documentation for more complex + + .. note:: + + See the epics-containers_ documentation for more complex use cases, such as integration with podman. See what was installed @@ -65,4 +65,4 @@ This will run in parallel the following checks: - `../how-to/lint` -.. _epics-containers: https://epics-containers.github.io/main/user/tutorials/devcontainer.html \ No newline at end of file +.. _epics-containers: https://epics-containers.github.io/main/user/tutorials/devcontainer.html diff --git a/pyproject.toml b/pyproject.toml index ec8e6931d..c84d39364 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -99,8 +99,8 @@ skipsdist=True # Don't create a virtualenv for the command, requires tox-direct plugin direct = True passenv = * -allowlist_externals = - pytest +allowlist_externals = + pytest pre-commit mypy sphinx-build From e1504912eaf42d555468ba08f36234192ae59820 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Tue, 12 Sep 2023 14:49:29 +0100 Subject: [PATCH 61/76] Use ruff as a linter as a replacement for flake8/isort --- .github/pages/make_switcher.py | 2 +- .gitignore | 3 ++ .pre-commit-config.yaml | 6 +-- .vscode/extensions.json | 3 +- .vscode/settings.json | 15 ++++-- docs/conf.py | 67 +++++++++++++------------- docs/developer/how-to/lint.rst | 12 ++--- docs/developer/reference/standards.rst | 3 +- pyproject.toml | 29 +++++------ 9 files changed, 73 insertions(+), 67 deletions(-) diff --git a/.github/pages/make_switcher.py b/.github/pages/make_switcher.py index d70367aec..ae227ab7f 100755 --- a/.github/pages/make_switcher.py +++ b/.github/pages/make_switcher.py @@ -59,7 +59,7 @@ def get_versions(ref: str, add: Optional[str], remove: Optional[str]) -> List[st def write_json(path: Path, repository: str, versions: str): org, repo_name = repository.split("/") struct = [ - dict(version=version, url=f"https://{org}.github.io/{repo_name}/{version}/") + {"version": version, "url": f"https://{org}.github.io/{repo_name}/{version}/"} for version in versions ] text = json.dumps(struct, indent=2) diff --git a/.gitignore b/.gitignore index 62dcd9a8d..a37be99b3 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,6 @@ venv* # further build artifacts lockfiles/ + +# ruff cache +.ruff_cache/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aa2a4cb2c..5bc9f001c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,9 +15,9 @@ repos: entry: black --check --diff types: [python] - - id: flake8 - name: Run flake8 + - id: ruff + name: Run ruff stages: [commit] language: system - entry: flake8 + entry: ruff types: [python] diff --git a/.vscode/extensions.json b/.vscode/extensions.json index cda78d45e..a1227b348 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,6 +4,7 @@ "ms-python.python", "tamasfe.even-better-toml", "redhat.vscode-yaml", - "ryanluker.vscode-coverage-gutters" + "ryanluker.vscode-coverage-gutters", + "charliermarsh.Ruff" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index b8cc9ad67..f5b8508fb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,15 +1,22 @@ { "python.linting.pylintEnabled": false, - "python.linting.flake8Enabled": true, + "python.linting.flake8Enabled": false, "python.linting.mypyEnabled": true, "python.linting.enabled": true, - "python.testing.pytestArgs": ["--cov=python3_pip_skeleton", "--cov-report", "xml:cov.xml"], + "python.testing.pytestArgs": [ + "--cov=python3_pip_skeleton", + "--cov-report", + "xml:cov.xml" + ], "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true, "python.formatting.provider": "black", "python.languageServer": "Pylance", "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.organizeImports": true + "[python]": { + "editor.codeActionsOnSave": { + "source.fixAll.ruff": false, + "source.organizeImports.ruff": true + } } } diff --git a/docs/conf.py b/docs/conf.py index 7022f617c..821468047 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -98,17 +98,16 @@ # This means you can link things like `str` and `asyncio` to the relevant # docs in the python documentation. -intersphinx_mapping = dict(python=("https://docs.python.org/3/", None)) +intersphinx_mapping = {"python": ("https://docs.python.org/3/", None)} # A dictionary of graphviz graph attributes for inheritance diagrams. -inheritance_graph_attrs = dict(rankdir="TB") +inheritance_graph_attrs = {"rankdir": "TB"} # Common links that should be available on every page rst_epilog = """ .. _Diamond Light Source: http://www.diamond.ac.uk .. _black: https://github.com/psf/black -.. _flake8: https://flake8.pycqa.org/en/latest/ -.. _isort: https://github.com/PyCQA/isort +.. _ruff: https://beta.ruff.rs/docs/ .. _mypy: http://mypy-lang.org/ .. _pre-commit: https://pre-commit.com/ """ @@ -149,40 +148,40 @@ # Point 3 makes checking switcher difficult, because the updated skeleton # will fix the switcher at the end of the docs workflow, but never gets a chance # to complete as the docs build warns and fails. -html_theme_options = dict( - logo=dict( - text=project, - ), - use_edit_page_button=True, - github_url=f"https://github.com/{github_user}/{github_repo}", - icon_links=[ - dict( - name="PyPI", - url=f"https://pypi.org/project/{project}", - icon="fas fa-cube", - ) +html_theme_options = { + "logo": { + "text": project, + }, + "use_edit_page_button": True, + "github_url": f"https://github.com/{github_user}/{github_repo}", + "icon_links": [ + { + "name": "PyPI", + "url": f"https://pypi.org/project/{project}", + "icon": "fas fa-cube", + } ], - switcher=dict( - json_url=switcher_json, - version_match=version, - ), - check_switcher=False, - navbar_end=["theme-switcher", "icon-links", "version-switcher"], - external_links=[ - dict( - name="Release Notes", - url=f"https://github.com/{github_user}/{github_repo}/releases", - ) + "switcher": { + "json_url": switcher_json, + "version_match": version, + }, + "check_switcher": False, + "navbar_end": ["theme-switcher", "icon-links", "version-switcher"], + "external_links": [ + { + "name": "Release Notes", + "url": f"https://github.com/{github_user}/{github_repo}/releases", + } ], -) +} # A dictionary of values to pass into the template engine’s context for all pages -html_context = dict( - github_user=github_user, - github_repo=project, - github_version=version, - doc_path="docs", -) +html_context = { + "github_user": github_user, + "github_repo": project, + "github_version": version, + "doc_path": "docs", +} # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. html_show_sphinx = False diff --git a/docs/developer/how-to/lint.rst b/docs/developer/how-to/lint.rst index ffb6ee5af..2df258d8f 100644 --- a/docs/developer/how-to/lint.rst +++ b/docs/developer/how-to/lint.rst @@ -1,7 +1,7 @@ Run linting using pre-commit ============================ -Code linting is handled by black_, flake8_ and isort_ run under pre-commit_. +Code linting is handled by black_ and ruff_ run under pre-commit_. Running pre-commit ------------------ @@ -26,14 +26,14 @@ repository:: $ black . -Likewise with isort:: +Likewise with ruff:: - $ isort . + $ ruff --fix . -If you get any flake8 issues you will have to fix those manually. +Ruff may not be able to automatically fix all issues; in this case, you will have to fix those manually. VSCode support -------------- -The ``.vscode/settings.json`` will run black and isort formatters as well as -flake8 checking on save. Issues will be highlighted in the editor window. +The ``.vscode/settings.json`` will run black formatting as well as +ruff checking on save. Issues will be highlighted in the editor window. diff --git a/docs/developer/reference/standards.rst b/docs/developer/reference/standards.rst index 06c4af539..5a1fd4782 100644 --- a/docs/developer/reference/standards.rst +++ b/docs/developer/reference/standards.rst @@ -10,8 +10,7 @@ Code Standards The code in this repository conforms to standards set by the following tools: - black_ for code formatting -- flake8_ for style checks -- isort_ for import ordering +- ruff_ for style checks - mypy_ for static type checking .. seealso:: diff --git a/pyproject.toml b/pyproject.toml index c84d39364..b390e7da7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,13 +26,12 @@ requires-python = ">=3.7" dev = [ "black", "mypy", - "flake8-isort", - "Flake8-pyproject", "pipdeptree", "pre-commit", "pydata-sphinx-theme>=0.12", "pytest", "pytest-cov", + "ruff", "sphinx-autobuild", "sphinx-copybutton", "sphinx-design", @@ -57,20 +56,6 @@ write_to = "src/python3_pip_skeleton/_version.py" [tool.mypy] ignore_missing_imports = true # Ignore missing stubs in imported modules -[tool.isort] -float_to_top = true -profile = "black" - -[tool.flake8] -extend-ignore = [ - "E203", # See https://github.com/PyCQA/pycodestyle/issues/373 - "F811", # support typing.overload decorator - "F722", # allow Annotated[typ, some_func("some string")] -] -max-line-length = 88 # Respect black's line length (default 88), -exclude = [".tox", "venv"] - - [tool.pytest.ini_options] # Run pytest with all our checkers, and don't spam us with massive tracebacks on error addopts = """ @@ -111,3 +96,15 @@ commands = pre-commit: pre-commit run --all-files {posargs} docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html """ + + +[tool.ruff] +src = ["src", "tests"] +line-length = 88 +select = [ + "C4", # flake8-comprehensions - https://beta.ruff.rs/docs/rules/#flake8-comprehensions-c4 + "E", # pycodestyle errors - https://beta.ruff.rs/docs/rules/#error-e + "F", # pyflakes rules - https://beta.ruff.rs/docs/rules/#pyflakes-f + "W", # pycodestyle warnings - https://beta.ruff.rs/docs/rules/#warning-w + "I001", # isort +] From 2e53832e6c1b78e7f7927274bf05b080f280d3b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 15:54:19 +0000 Subject: [PATCH 62/76] Bump docker/build-push-action from 3 to 5 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3 to 5. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v3...v5) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/code.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index cbc3e2801..34e527a56 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -144,7 +144,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Build and export to Docker local cache - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: # Note build-args, context, file, and target must all match between this # step and the later build-push-action, otherwise the second build-push-action @@ -179,7 +179,7 @@ jobs: - name: Push cached image to container registry if: github.ref_type == 'tag' # || github.ref_name == 'main' - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 # This does not build the image again, it will find the image in the # Docker cache and publish it with: From 239f39fdc49aa4a5b8024c003427b7051fc1d273 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:31:46 +0000 Subject: [PATCH 63/76] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/code.yml | 8 ++++---- .github/workflows/docs.yml | 2 +- .github/workflows/docs_clean.yml | 2 +- .github/workflows/linkcheck.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 34e527a56..0f83a490e 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install python packages uses: ./.github/actions/install_requirements @@ -47,7 +47,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Need this to get version number from last tag fetch-depth: 0 @@ -77,7 +77,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Need this to get version number from last tag fetch-depth: 0 @@ -120,7 +120,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # image names must be all lower case - name: Generate image repo name diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c510d577a..d89a08624 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,7 +15,7 @@ jobs: run: sleep 60 - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Need this to get version number from last tag fetch-depth: 0 diff --git a/.github/workflows/docs_clean.yml b/.github/workflows/docs_clean.yml index a67e18815..e324640e7 100644 --- a/.github/workflows/docs_clean.yml +++ b/.github/workflows/docs_clean.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: gh-pages diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 70cba115f..d2a80410e 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install python packages uses: ./.github/actions/install_requirements From dfe03c27da2651538ff9a0dcb59ef1f3b149db86 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:31:35 +0000 Subject: [PATCH 64/76] Bump docker/login-action from 2 to 3 Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 0f83a490e..f7eb413d8 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -133,7 +133,7 @@ jobs: - name: Log in to GitHub Docker Registry if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} From 4de663b88e2918c138677959f0b783affcba6891 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:31:51 +0000 Subject: [PATCH 65/76] Bump docker/metadata-action from 4 to 5 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4 to 5. - [Release notes](https://github.com/docker/metadata-action/releases) - [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md) - [Commits](https://github.com/docker/metadata-action/compare/v4...v5) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index f7eb413d8..859b38066 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -167,7 +167,7 @@ jobs: - name: Create tags for publishing image id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ${{ env.IMAGE_REPOSITORY }} tags: | From 357e9274a92ec3d755580cf5dbb3650f2874354d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:31:41 +0000 Subject: [PATCH 66/76] Bump docker/setup-buildx-action from 2 to 3 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/code.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 859b38066..ae990294a 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -141,7 +141,7 @@ jobs: - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Build and export to Docker local cache uses: docker/build-push-action@v5 From 834445f74c8223b6f655cbc9508d94b1c29e1008 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Tue, 17 Oct 2023 10:58:46 +0100 Subject: [PATCH 67/76] Rename python3-pip-skeleton -> pandablocks --- .github/CONTRIBUTING.rst | 6 ++-- Dockerfile | 2 +- README.rst | 34 +++++++++---------- docs/conf.py | 8 ++--- .../0002-switched-to-pip-skeleton.rst | 6 ++-- docs/developer/how-to/make-release.rst | 2 +- docs/developer/tutorials/dev-install.rst | 6 ++-- docs/index.rst | 4 +-- docs/user/how-to/run-container.rst | 6 ++-- docs/user/reference/api.rst | 8 ++--- docs/user/tutorials/installation.rst | 6 ++-- pyproject.toml | 16 ++++----- .../__init__.py | 2 +- .../__main__.py | 2 +- tests/test_boilerplate_removed.py | 2 +- tests/test_cli.py | 4 +-- 16 files changed, 57 insertions(+), 57 deletions(-) rename src/{python3_pip_skeleton => pandablocks}/__init__.py (80%) rename src/{python3_pip_skeleton => pandablocks}/__main__.py (86%) diff --git a/.github/CONTRIBUTING.rst b/.github/CONTRIBUTING.rst index 19ab494ff..d0e619ece 100644 --- a/.github/CONTRIBUTING.rst +++ b/.github/CONTRIBUTING.rst @@ -7,7 +7,7 @@ filing a new one. If you have a great idea but it involves big changes, please file a ticket before making a pull request! We want to make sure you don't spend your time coding something that might not fit the scope of the project. -.. _GitHub: https://github.com/DiamondLightSource/python3-pip-skeleton/issues +.. _GitHub: https://github.com/PandABlocks/pandablocks/issues Issue or Discussion? -------------------- @@ -16,7 +16,7 @@ Github also offers discussions_ as a place to ask questions and share ideas. If your issue is open ended and it is not obvious when it can be "closed", please raise it as a discussion instead. -.. _discussions: https://github.com/DiamondLightSource/python3-pip-skeleton/discussions +.. _discussions: https://github.com/PandABlocks/pandablocks/discussions Code coverage ------------- @@ -32,4 +32,4 @@ The `Developer Guide`_ contains information on setting up a development environment, running the tests and what standards the code and documentation should follow. -.. _Developer Guide: https://diamondlightsource.github.io/python3-pip-skeleton/main/developer/how-to/contribute.html +.. _Developer Guide: https://diamondlightsource.github.io/pandablocks/main/developer/how-to/contribute.html diff --git a/Dockerfile b/Dockerfile index 31d05606f..d712d3b5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,5 +33,5 @@ COPY --from=build /venv/ /venv/ ENV PATH=/venv/bin:$PATH # change this entrypoint if it is not the same as the repo -ENTRYPOINT ["python3-pip-skeleton"] +ENTRYPOINT ["pandablocks"] CMD ["--version"] diff --git a/README.rst b/README.rst index a014631eb..958f836d8 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -python3-pip-skeleton +pandablocks =========================== |code_ci| |docs_ci| |coverage| |pypi_version| |license| @@ -13,10 +13,10 @@ This is where you should write a short paragraph that describes what your module how it does it, and why people should use it. ============== ============================================================== -PyPI ``pip install python3-pip-skeleton`` -Source code https://github.com/DiamondLightSource/python3-pip-skeleton -Documentation https://DiamondLightSource.github.io/python3-pip-skeleton -Releases https://github.com/DiamondLightSource/python3-pip-skeleton/releases +PyPI ``pip install pandablocks`` +Source code https://github.com/PandABlocks/pandablocks +Documentation https://PandABlocks.github.io/pandablocks +Releases https://github.com/PandABlocks/pandablocks/releases ============== ============================================================== This is where you should put some images or code snippets that illustrate @@ -25,28 +25,28 @@ introductory code here: .. code-block:: python - from python3_pip_skeleton import __version__ + from pandablocks import __version__ - print(f"Hello python3_pip_skeleton {__version__}") + print(f"Hello pandablocks {__version__}") Or if it is a commandline tool then you might put some example commands here:: - $ python -m python3_pip_skeleton --version + $ python -m pandablocks --version -.. |code_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/actions/workflows/code.yml/badge.svg?branch=main - :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions/workflows/code.yml +.. |code_ci| image:: https://github.com/PandABlocks/pandablocks/actions/workflows/code.yml/badge.svg?branch=main + :target: https://github.com/PandABlocks/pandablocks/actions/workflows/code.yml :alt: Code CI -.. |docs_ci| image:: https://github.com/DiamondLightSource/python3-pip-skeleton/actions/workflows/docs.yml/badge.svg?branch=main - :target: https://github.com/DiamondLightSource/python3-pip-skeleton/actions/workflows/docs.yml +.. |docs_ci| image:: https://github.com/PandABlocks/pandablocks/actions/workflows/docs.yml/badge.svg?branch=main + :target: https://github.com/PandABlocks/pandablocks/actions/workflows/docs.yml :alt: Docs CI -.. |coverage| image:: https://codecov.io/gh/DiamondLightSource/python3-pip-skeleton/branch/main/graph/badge.svg - :target: https://codecov.io/gh/DiamondLightSource/python3-pip-skeleton +.. |coverage| image:: https://codecov.io/gh/PandABlocks/pandablocks/branch/main/graph/badge.svg + :target: https://codecov.io/gh/PandABlocks/pandablocks :alt: Test Coverage -.. |pypi_version| image:: https://img.shields.io/pypi/v/python3-pip-skeleton.svg - :target: https://pypi.org/project/python3-pip-skeleton +.. |pypi_version| image:: https://img.shields.io/pypi/v/pandablocks.svg + :target: https://pypi.org/project/pandablocks :alt: Latest PyPI version .. |license| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg @@ -57,4 +57,4 @@ Or if it is a commandline tool then you might put some example commands here:: Anything below this line is used when viewing README.rst and will be replaced when included in index.rst -See https://DiamondLightSource.github.io/python3-pip-skeleton for more detailed documentation. +See https://PandABlocks.github.io/pandablocks for more detailed documentation. diff --git a/docs/conf.py b/docs/conf.py index 821468047..86a0fb979 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,15 +10,15 @@ import requests -import python3_pip_skeleton +import pandablocks # -- General configuration ------------------------------------------------ # General information about the project. -project = "python3-pip-skeleton" +project = "pandablocks" # The full version, including alpha/beta/rc tags. -release = python3_pip_skeleton.__version__ +release = pandablocks.__version__ # The short X.Y version. if "+" in release: @@ -127,7 +127,7 @@ # html_theme = "pydata_sphinx_theme" github_repo = project -github_user = "DiamondLightSource" +github_user = "PandABlocks" switcher_json = f"https://{github_user}.github.io/{github_repo}/switcher.json" switcher_exists = requests.get(switcher_json).ok if not switcher_exists: diff --git a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst index 41d90fd4a..d0e8452c1 100644 --- a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst +++ b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst @@ -1,4 +1,4 @@ -2. Adopt python3-pip-skeleton for project structure +2. Adopt pandablocks for project structure =================================================== Date: 2022-02-18 @@ -11,7 +11,7 @@ Accepted Context ------- -We should use the following `pip-skeleton `_. +We should use the following `pip-skeleton `_. The skeleton will ensure consistency in developer environments and package management. @@ -23,7 +23,7 @@ We have switched to using the skeleton. Consequences ------------ -This module will use a fixed set of tools as developed in python3-pip-skeleton +This module will use a fixed set of tools as developed in pandablocks and can pull from this skeleton to update the packaging to the latest techniques. As such, the developer environment may have changed, the following could be diff --git a/docs/developer/how-to/make-release.rst b/docs/developer/how-to/make-release.rst index d8f92f854..3a99eca5f 100644 --- a/docs/developer/how-to/make-release.rst +++ b/docs/developer/how-to/make-release.rst @@ -13,4 +13,4 @@ To make a new release, please follow this checklist: Note that tagging and pushing to the main branch has the same effect except that you will not get the option to edit the release notes. -.. _release: https://github.com/DiamondLightSource/python3-pip-skeleton/releases +.. _release: https://github.com/PandABlocks/pandablocks/releases diff --git a/docs/developer/tutorials/dev-install.rst b/docs/developer/tutorials/dev-install.rst index 183b1893a..3aa2cfb3e 100644 --- a/docs/developer/tutorials/dev-install.rst +++ b/docs/developer/tutorials/dev-install.rst @@ -10,7 +10,7 @@ Clone the repository First clone the repository locally using `Git `_:: - $ git clone git://github.com/DiamondLightSource/python3-pip-skeleton.git + $ git clone git://github.com/PandABlocks/pandablocks.git Install dependencies -------------------- @@ -25,7 +25,7 @@ requires python 3.8 or later) or to run in a container under `VSCode .. code:: - $ cd python3-pip-skeleton + $ cd pandablocks $ python3 -m venv venv $ source venv/bin/activate $ pip install -e '.[dev]' @@ -34,7 +34,7 @@ requires python 3.8 or later) or to run in a container under `VSCode .. code:: - $ code python3-pip-skeleton + $ code pandablocks # Click on 'Reopen in Container' when prompted # Open a new terminal diff --git a/docs/index.rst b/docs/index.rst index df33c8e67..0023bc4d4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,13 +14,13 @@ The documentation is split into 2 sections: :link: user/index :link-type: doc - The User Guide contains documentation on how to install and use python3-pip-skeleton. + The User Guide contains documentation on how to install and use pandablocks. .. grid-item-card:: :material-regular:`code;4em` :link: developer/index :link-type: doc - The Developer Guide contains documentation on how to develop and contribute changes back to python3-pip-skeleton. + The Developer Guide contains documentation on how to develop and contribute changes back to pandablocks. .. toctree:: :hidden: diff --git a/docs/user/how-to/run-container.rst b/docs/user/how-to/run-container.rst index 84f857af7..38adf765c 100644 --- a/docs/user/how-to/run-container.rst +++ b/docs/user/how-to/run-container.rst @@ -1,15 +1,15 @@ Run in a container ================== -Pre-built containers with python3-pip-skeleton and its dependencies already +Pre-built containers with pandablocks and its dependencies already installed are available on `Github Container Registry -`_. +`_. Starting the container ---------------------- To pull the container from github container registry and run:: - $ docker run ghcr.io/DiamondLightSource/python3-pip-skeleton:main --version + $ docker run ghcr.io/PandABlocks/pandablocks:main --version To get a released version, use a numbered release instead of ``main``. diff --git a/docs/user/reference/api.rst b/docs/user/reference/api.rst index 8544e1728..a432ecc97 100644 --- a/docs/user/reference/api.rst +++ b/docs/user/reference/api.rst @@ -1,14 +1,14 @@ API === -.. automodule:: python3_pip_skeleton +.. automodule:: pandablocks - ``python3_pip_skeleton`` + ``pandablocks`` ----------------------------------- -This is the internal API reference for python3_pip_skeleton +This is the internal API reference for pandablocks -.. data:: python3_pip_skeleton.__version__ +.. data:: pandablocks.__version__ :type: str Version number as calculated by https://github.com/pypa/setuptools_scm diff --git a/docs/user/tutorials/installation.rst b/docs/user/tutorials/installation.rst index e90d3efb9..4109cbe0e 100644 --- a/docs/user/tutorials/installation.rst +++ b/docs/user/tutorials/installation.rst @@ -25,14 +25,14 @@ Installing the library You can now use ``pip`` to install the library and its dependencies:: - $ python3 -m pip install python3-pip-skeleton + $ python3 -m pip install pandablocks If you require a feature that is not currently released you can also install from github:: - $ python3 -m pip install git+https://github.com/DiamondLightSource/python3-pip-skeleton.git + $ python3 -m pip install git+https://github.com/PandABlocks/pandablocks.git The library should now be installed and the commandline interface on your path. You can check the version that has been installed by typing:: - $ python3-pip-skeleton --version + $ pandablocks --version diff --git a/pyproject.toml b/pyproject.toml index b390e7da7..bd0154f7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=64", "setuptools_scm[toml]>=6.2", "wheel"] build-backend = "setuptools.build_meta" [project] -name = "python3-pip-skeleton" +name = "pandablocks" classifiers = [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: Apache Software License", @@ -40,18 +40,18 @@ dev = [ ] [project.scripts] -python3-pip-skeleton = "python3_pip_skeleton.__main__:main" +pandablocks = "pandablocks.__main__:main" [project.urls] -GitHub = "https://github.com/DiamondLightSource/python3-pip-skeleton" +GitHub = "https://github.com/PandABlocks/pandablocks" [[project.authors]] # Further authors may be added by duplicating this section -email = "email@address.com" -name = "Firstname Lastname" +email = "tom.cobb@diamond.ac.uk" +name = "Tom Cobb" [tool.setuptools_scm] -write_to = "src/python3_pip_skeleton/_version.py" +write_to = "src/pandablocks/_version.py" [tool.mypy] ignore_missing_imports = true # Ignore missing stubs in imported modules @@ -67,7 +67,7 @@ filterwarnings = "error" testpaths = "docs src tests" [tool.coverage.run] -data_file = "/tmp/python3_pip_skeleton.coverage" +data_file = "/tmp/pandablocks.coverage" [tool.coverage.paths] # Tests are run from installed location, map back to the src directory @@ -91,7 +91,7 @@ allowlist_externals = sphinx-build sphinx-autobuild commands = - pytest: pytest --cov=python3_pip_skeleton --cov-report term --cov-report xml:cov.xml {posargs} + pytest: pytest --cov=pandablocks --cov-report term --cov-report xml:cov.xml {posargs} mypy: mypy src tests {posargs} pre-commit: pre-commit run --all-files {posargs} docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html diff --git a/src/python3_pip_skeleton/__init__.py b/src/pandablocks/__init__.py similarity index 80% rename from src/python3_pip_skeleton/__init__.py rename to src/pandablocks/__init__.py index 82cce3c2d..457ddb1f8 100644 --- a/src/python3_pip_skeleton/__init__.py +++ b/src/pandablocks/__init__.py @@ -5,7 +5,7 @@ else: from importlib.metadata import version # noqa -__version__ = version("python3-pip-skeleton") +__version__ = version("pandablocks") del version __all__ = ["__version__"] diff --git a/src/python3_pip_skeleton/__main__.py b/src/pandablocks/__main__.py similarity index 86% rename from src/python3_pip_skeleton/__main__.py rename to src/pandablocks/__main__.py index e348a31e4..365999d52 100644 --- a/src/python3_pip_skeleton/__main__.py +++ b/src/pandablocks/__main__.py @@ -11,6 +11,6 @@ def main(args=None): args = parser.parse_args(args) -# test with: python -m python3_pip_skeleton +# test with: python -m pandablocks if __name__ == "__main__": main() diff --git a/tests/test_boilerplate_removed.py b/tests/test_boilerplate_removed.py index a0675d9c8..46777a129 100644 --- a/tests/test_boilerplate_removed.py +++ b/tests/test_boilerplate_removed.py @@ -31,7 +31,7 @@ def assert_not_contains_text(path: str, text: str, explanation: str): # pyproject.toml def test_module_summary(): - summary = metadata("python3-pip-skeleton")["summary"] + summary = metadata("pandablocks")["summary"] skeleton_check( "One line description of your module" in summary, "Please change project.description in ./pyproject.toml " diff --git a/tests/test_cli.py b/tests/test_cli.py index 2ff648c03..439600f82 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,9 +1,9 @@ import subprocess import sys -from python3_pip_skeleton import __version__ +from pandablocks import __version__ def test_cli_version(): - cmd = [sys.executable, "-m", "python3_pip_skeleton", "--version"] + cmd = [sys.executable, "-m", "pandablocks", "--version"] assert subprocess.check_output(cmd).decode().strip() == __version__ From 18d094c31f18577c472aa291893879e77d3b794f Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Tue, 17 Oct 2023 13:38:17 +0100 Subject: [PATCH 68/76] Moved files to match structure of the skeleton. Moved setup.cfg and Pipfile options into pyproject.toml --- Pipfile | 38 - Pipfile.lock | 866 ------------------ CHANGELOG.rst => docs/CHANGELOG.rst | 0 CONTRIBUTING.rst => docs/CONTRIBUTING.rst | 0 pandablocks/__init__.py | 3 - pandablocks/__main__.py | 6 - pyproject.toml | 27 +- setup.cfg | 70 -- setup.py | 17 - {examples => src/examples}/README.rst | 0 {examples => src/examples}/arm_and_hdf.py | 0 .../examples}/hdf_queue_reporting.py | 0 .../examples}/introspect_panda.py | 0 .../examples}/plot_counter_hdf.py | 0 {pandablocks => src/pandablocks}/_control.py | 0 {pandablocks => src/pandablocks}/_exchange.py | 0 .../pandablocks}/_version_git.py | 0 {pandablocks => src/pandablocks}/asyncio.py | 0 {pandablocks => src/pandablocks}/blocking.py | 0 {pandablocks => src/pandablocks}/cli.py | 0 {pandablocks => src/pandablocks}/commands.py | 0 .../pandablocks}/connections.py | 0 {pandablocks => src/pandablocks}/hdf.py | 0 {pandablocks => src/pandablocks}/responses.py | 0 .../pandablocks}/saves/tutorial.sav | 0 {pandablocks => src/pandablocks}/utils.py | 0 tests/test_boilerplate_removed.py | 64 -- 27 files changed, 18 insertions(+), 1073 deletions(-) delete mode 100644 Pipfile delete mode 100644 Pipfile.lock rename CHANGELOG.rst => docs/CHANGELOG.rst (100%) rename CONTRIBUTING.rst => docs/CONTRIBUTING.rst (100%) delete mode 100644 pandablocks/__init__.py delete mode 100644 pandablocks/__main__.py delete mode 100644 setup.cfg delete mode 100644 setup.py rename {examples => src/examples}/README.rst (100%) rename {examples => src/examples}/arm_and_hdf.py (100%) rename {examples => src/examples}/hdf_queue_reporting.py (100%) rename {examples => src/examples}/introspect_panda.py (100%) rename {examples => src/examples}/plot_counter_hdf.py (100%) rename {pandablocks => src/pandablocks}/_control.py (100%) rename {pandablocks => src/pandablocks}/_exchange.py (100%) rename {pandablocks => src/pandablocks}/_version_git.py (100%) rename {pandablocks => src/pandablocks}/asyncio.py (100%) rename {pandablocks => src/pandablocks}/blocking.py (100%) rename {pandablocks => src/pandablocks}/cli.py (100%) rename {pandablocks => src/pandablocks}/commands.py (100%) rename {pandablocks => src/pandablocks}/connections.py (100%) rename {pandablocks => src/pandablocks}/hdf.py (100%) rename {pandablocks => src/pandablocks}/responses.py (100%) rename {pandablocks => src/pandablocks}/saves/tutorial.sav (100%) rename {pandablocks => src/pandablocks}/utils.py (100%) delete mode 100644 tests/test_boilerplate_removed.py diff --git a/Pipfile b/Pipfile deleted file mode 100644 index c77deb445..000000000 --- a/Pipfile +++ /dev/null @@ -1,38 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -# Pinning black stops us having to allow pre-releases globally -black = "*" -# Pins to make lockfile usable on multiple Python versions and platforms -mypy = "*" -atomicwrites = "*" -typed-ast = "*" -# Test and docs dependencies -pytest-cov = "*" -pytest-mypy = "*" -flake8 = "==4.0.1" # https://github.com/tholo/pytest-flake8/issues/87 - will stop being an issue when we move to a new skeleton -pytest-flake8 = "*" -pytest-black = "*" -mock = "*" -types-mock = "*" -pytest-asyncio = "*" -flake8-isort = "*" -isort = ">5.0" -sphinx = "==4.3.2" -sphinx-rtd-theme = "*" - -[packages] -# All other package requirements from setup.cfg -pandablocks = {editable = true, extras = ["hdf5"], path = "."} -# Pins to make lockfile usable on multiple Python versions and platforms -numpy = "*" -typing-extensions = "*" - -[scripts] -tests = "python -m pytest" -docs = "sphinx-build -EWT --keep-going docs build/html" -# Delete any files that git ignore hides from us -gitclean = "git clean -fdX" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 1931d587f..000000000 --- a/Pipfile.lock +++ /dev/null @@ -1,866 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "54f1fb92311a238c4813c2f415a8b69a3a4c5e070442535412f5e8d8a168f217" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "click": { - "hashes": [ - "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", - "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" - ], - "version": "==8.1.3" - }, - "cycler": { - "hashes": [ - "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d", - "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8" - ], - "version": "==0.10.0" - }, - "fonttools": { - "hashes": [ - "sha256:1933415e0fbdf068815cb1baaa1f159e17830215f7e8624e5731122761627557", - "sha256:2b18a172120e32128a80efee04cff487d5d140fe7d817deb648b2eee023a40e4" - ], - "version": "==4.29.1" - }, - "h5py": { - "hashes": [ - "sha256:03d64fb86bb86b978928bad923b64419a23e836499ec6363e305ad28afd9d287", - "sha256:04e2e1e2fc51b8873e972a08d2f89625ef999b1f2d276199011af57bb9fc7851", - "sha256:0798a9c0ff45f17d0192e4d7114d734cac9f8b2b2c76dd1d923c4d0923f27bb6", - "sha256:0a047fddbe6951bce40e9cde63373c838a978c5e05a011a682db9ba6334b8e85", - "sha256:0d8de8cb619fc597da7cf8cdcbf3b7ff8c5f6db836568afc7dc16d21f59b2b49", - "sha256:1fcb11a2dc8eb7ddcae08afd8fae02ba10467753a857fa07a404d700a93f3d53", - "sha256:3fcf37884383c5da64846ab510190720027dca0768def34dd8dcb659dbe5cbf3", - "sha256:43fed4d13743cf02798a9a03a360a88e589d81285e72b83f47d37bb64ed44881", - "sha256:63beb8b7b47d0896c50de6efb9a1eaa81dbe211f3767e7dd7db159cea51ba37a", - "sha256:6776d896fb90c5938de8acb925e057e2f9f28755f67ec3edcbc8344832616c38", - "sha256:9e2ad2aa000f5b1e73b5dfe22f358ca46bf1a2b6ca394d9659874d7fc251731a", - "sha256:9e7535df5ee3dc3e5d1f408fdfc0b33b46bc9b34db82743c82cd674d8239b9ad", - "sha256:a9351d729ea754db36d175098361b920573fdad334125f86ac1dd3a083355e20", - "sha256:c038399ce09a58ff8d89ec3e62f00aa7cb82d14f34e24735b920e2a811a3a426", - "sha256:d77af42cb751ad6cc44f11bae73075a07429a5cf2094dfde2b1e716e059b3911", - "sha256:e5b7820b75f9519499d76cc708e27242ccfdd9dfb511d6deb98701961d0445aa", - "sha256:ed43e2cc4f511756fd664fb45d6b66c3cbed4e3bd0f70e29c37809b2ae013c44", - "sha256:f084bbe816907dfe59006756f8f2d16d352faff2d107f4ffeb1d8de126fc5dc7", - "sha256:f514b24cacdd983e61f8d371edac8c1b780c279d0acb8485639e97339c866073", - "sha256:f73307c876af49aa869ec5df1818e9bb0bdcfcf8a5ba773cc45a4fba5a286a5c" - ], - "version": "==3.7.0" - }, - "importlib-metadata": { - "hashes": [ - "sha256:175f4ee440a0317f6e8d81b7f8d4869f93316170a65ad2b007d2929186c8052c", - "sha256:e0bc84ff355328a4adfc5240c4f211e0ab386f80aa640d1b11f0618a1d282094" - ], - "markers": "python_version < '3.8'", - "version": "==4.11.1" - }, - "kiwisolver": { - "hashes": [ - "sha256:0cd53f403202159b44528498de18f9285b04482bab2a6fc3f5dd8dbb9352e30d", - "sha256:1e1bc12fb773a7b2ffdeb8380609f4f8064777877b2225dec3da711b421fda31", - "sha256:225e2e18f271e0ed8157d7f4518ffbf99b9450fca398d561eb5c4a87d0986dd9", - "sha256:232c9e11fd7ac3a470d65cd67e4359eee155ec57e822e5220322d7b2ac84fbf0", - "sha256:31dfd2ac56edc0ff9ac295193eeaea1c0c923c0355bf948fbd99ed6018010b72", - "sha256:33449715e0101e4d34f64990352bce4095c8bf13bed1b390773fc0a7295967b3", - "sha256:401a2e9afa8588589775fe34fc22d918ae839aaaf0c0e96441c0fdbce6d8ebe6", - "sha256:44a62e24d9b01ba94ae7a4a6c3fb215dc4af1dde817e7498d901e229aaf50e4e", - "sha256:50af681a36b2a1dee1d3c169ade9fdc59207d3c31e522519181e12f1b3ba7000", - "sha256:563c649cfdef27d081c84e72a03b48ea9408c16657500c312575ae9d9f7bc1c3", - "sha256:5989db3b3b34b76c09253deeaf7fbc2707616f130e166996606c284395da3f18", - "sha256:5a7a7dbff17e66fac9142ae2ecafb719393aaee6a3768c9de2fd425c63b53e21", - "sha256:5c3e6455341008a054cccee8c5d24481bcfe1acdbc9add30aa95798e95c65621", - "sha256:5f6ccd3dd0b9739edcf407514016108e2280769c73a85b9e59aa390046dbf08b", - "sha256:72c99e39d005b793fb7d3d4e660aed6b6281b502e8c1eaf8ee8346023c8e03bc", - "sha256:78751b33595f7f9511952e7e60ce858c6d64db2e062afb325985ddbd34b5c131", - "sha256:834ee27348c4aefc20b479335fd422a2c69db55f7d9ab61721ac8cd83eb78882", - "sha256:8be8d84b7d4f2ba4ffff3665bcd0211318aa632395a1a41553250484a871d454", - "sha256:950a199911a8d94683a6b10321f9345d5a3a8433ec58b217ace979e18f16e248", - "sha256:a357fd4f15ee49b4a98b44ec23a34a95f1e00292a139d6015c11f55774ef10de", - "sha256:a53d27d0c2a0ebd07e395e56a1fbdf75ffedc4a05943daf472af163413ce9598", - "sha256:acef3d59d47dd85ecf909c359d0fd2c81ed33bdff70216d3956b463e12c38a54", - "sha256:b38694dcdac990a743aa654037ff1188c7a9801ac3ccc548d3341014bc5ca278", - "sha256:b9edd0110a77fc321ab090aaa1cfcaba1d8499850a12848b81be2222eab648f6", - "sha256:c08e95114951dc2090c4a630c2385bef681cacf12636fb0241accdc6b303fd81", - "sha256:c5518d51a0735b1e6cee1fdce66359f8d2b59c3ca85dc2b0813a8aa86818a030", - "sha256:c8fd0f1ae9d92b42854b2979024d7597685ce4ada367172ed7c09edf2cef9cb8", - "sha256:ca3820eb7f7faf7f0aa88de0e54681bddcb46e485beb844fcecbcd1c8bd01689", - "sha256:cf8b574c7b9aa060c62116d4181f3a1a4e821b2ec5cbfe3775809474113748d4", - "sha256:d3155d828dec1d43283bd24d3d3e0d9c7c350cdfcc0bd06c0ad1209c1bbc36d0", - "sha256:f8d6f8db88049a699817fd9178782867bf22283e3813064302ac59f61d95be05", - "sha256:fd34fbbfbc40628200730bc1febe30631347103fc8d3d4fa012c21ab9c11eca9" - ], - "version": "==1.3.1" - }, - "matplotlib": { - "hashes": [ - "sha256:0abf8b51cc6d3ba34d1b15b26e329f23879848a0cf1216954c1f432ffc7e1af7", - "sha256:0e020a42f3338823a393dd2f80e39a2c07b9f941dfe2c778eb104eeb33d60bb5", - "sha256:13930a0c9bec0fd25f43c448b047a21af1353328b946f044a8fc3be077c6b1a8", - "sha256:153a0cf6a6ff4f406a0600d2034710c49988bacc6313d193b32716f98a697580", - "sha256:18f6e52386300db5cc4d1e9019ad9da2e80658bab018834d963ebb0aa5355095", - "sha256:2089b9014792dcc87bb1d620cde847913338abf7d957ef05587382b0cb76d44e", - "sha256:2eea16883aa7724c95eea0eb473ab585c6cf66f0e28f7f13e63deb38f4fd6d0f", - "sha256:38892a254420d95594285077276162a5e9e9c30b6da08bdc2a4d53331ad9a6fa", - "sha256:4b018ea6f26424a0852eb60eb406420d9f0d34f65736ea7bbfbb104946a66d86", - "sha256:65f877882b7ddede7090c7d87be27a0f4720fe7fc6fddd4409c06e1aa0f1ae8d", - "sha256:666d717a4798eb9c5d3ae83fe80c7bc6ed696b93e879cb01cb24a74155c73612", - "sha256:66b172610db0ececebebb09d146f54205f87c7b841454e408fba854764f91bdd", - "sha256:6db02c5605f063b67780f4d5753476b6a4944343284aa4e93c5e8ff6e9ec7f76", - "sha256:6e0e6b2111165522ad336705499b1f968c34a9e84d05d498ee5af0b5697d1efe", - "sha256:71a1851111f23f82fc43d2b6b2bfdd3f760579a664ebc939576fe21cc6133d01", - "sha256:7a7cb59ebd63a8ac4542ec1c61dd08724f82ec3aa7bb6b4b9e212d43c611ce3d", - "sha256:7baf23adb698d8c6ca7339c9dde00931bc47b2dd82fa912827fef9f93db77f5e", - "sha256:970aa97297537540369d05fe0fd1bb952593f9ab696c9b427c06990a83e2418b", - "sha256:9bac8eb1eccef540d7f4e844b6313d9f7722efd48c07e1b4bfec1056132127fd", - "sha256:a07ff2565da72a7b384a9e000b15b6b8270d81370af8a3531a16f6fbcee023cc", - "sha256:a0dcaf5648cecddc328e81a0421821a1f65a1d517b20746c94a1f0f5c36fb51a", - "sha256:a0ea10faa3bab0714d3a19c7e0921279a68d57552414d6eceaea99f97d7735db", - "sha256:a5b62d1805cc83d755972033c05cea78a1e177a159fc84da5c9c4ab6303ccbd9", - "sha256:a6cef5b31e27c31253c0f852b629a38d550ae66ec6850129c49d872f9ee428cb", - "sha256:a7bf8b05c214d32fb7ca7c001fde70b9b426378e897b0adbf77b85ea3569d56a", - "sha256:ac17a7e7b06ee426a4989f0b7f24ab1a592e39cdf56353a90f4e998bc0bf44d6", - "sha256:b3b687e905da32e5f2e5f16efa713f5d1fcd9fb8b8c697895de35c91fedeb086", - "sha256:b5e439d9e55d645f2a4dca63e2f66d68fe974c405053b132d61c7e98c25dfeb2", - "sha256:ba107add08e12600b072cf3c47aaa1ab85dd4d3c48107a5d3377d1bf80f8b235", - "sha256:d092b7ba63182d2dd427904e3eb58dd5c46ec67c5968de14a4b5007010a3a4cc", - "sha256:dc8c5c23e7056e126275dbf29efba817b3d94196690930d0968873ac3a94ab82", - "sha256:df0042cab69f4d246f4cb8fc297770ac4ae6ec2983f61836b04a117722037dcd", - "sha256:ee3d9ff16d749a9aa521bd7d86f0dbf256b2d2ac8ce31b19e4d2c86d2f2ff0b6", - "sha256:f23fbf70d2e80f4e03a83fc1206a8306d9bc50482fee4239f10676ce7e470c83", - "sha256:ff5d9fe518ad2de14ce82ab906b6ab5c2b0c7f4f984400ff8a7a905daa580a0a" - ], - "version": "==3.5.0" - }, - "numpy": { - "hashes": [ - "sha256:1dbe1c91269f880e364526649a52eff93ac30035507ae980d2fed33aaee633ac", - "sha256:357768c2e4451ac241465157a3e929b265dfac85d9214074985b1786244f2ef3", - "sha256:3820724272f9913b597ccd13a467cc492a0da6b05df26ea09e78b171a0bb9da6", - "sha256:4391bd07606be175aafd267ef9bea87cf1b8210c787666ce82073b05f202add1", - "sha256:4aa48afdce4660b0076a00d80afa54e8a97cd49f457d68a4342d188a09451c1a", - "sha256:58459d3bad03343ac4b1b42ed14d571b8743dc80ccbf27444f266729df1d6f5b", - "sha256:5c3c8def4230e1b959671eb959083661b4a0d2e9af93ee339c7dada6759a9470", - "sha256:5f30427731561ce75d7048ac254dbe47a2ba576229250fb60f0fb74db96501a1", - "sha256:643843bcc1c50526b3a71cd2ee561cf0d8773f062c8cbaf9ffac9fdf573f83ab", - "sha256:67c261d6c0a9981820c3a149d255a76918278a6b03b6a036800359aba1256d46", - "sha256:67f21981ba2f9d7ba9ade60c9e8cbaa8cf8e9ae51673934480e45cf55e953673", - "sha256:6aaf96c7f8cebc220cdfc03f1d5a31952f027dda050e5a703a0d1c396075e3e7", - "sha256:7c4068a8c44014b2d55f3c3f574c376b2494ca9cc73d2f1bd692382b6dffe3db", - "sha256:7c7e5fa88d9ff656e067876e4736379cc962d185d5cd808014a8a928d529ef4e", - "sha256:7f5ae4f304257569ef3b948810816bc87c9146e8c446053539947eedeaa32786", - "sha256:82691fda7c3f77c90e62da69ae60b5ac08e87e775b09813559f8901a88266552", - "sha256:8737609c3bbdd48e380d463134a35ffad3b22dc56295eff6f79fd85bd0eeeb25", - "sha256:9f411b2c3f3d76bba0865b35a425157c5dcf54937f82bbeb3d3c180789dd66a6", - "sha256:a6be4cb0ef3b8c9250c19cc122267263093eee7edd4e3fa75395dfda8c17a8e2", - "sha256:bcb238c9c96c00d3085b264e5c1a1207672577b93fa666c3b14a45240b14123a", - "sha256:bf2ec4b75d0e9356edea834d1de42b31fe11f726a81dfb2c2112bc1eaa508fcf", - "sha256:d136337ae3cc69aa5e447e78d8e1514be8c3ec9b54264e680cf0b4bd9011574f", - "sha256:d4bf4d43077db55589ffc9009c0ba0a94fa4908b9586d6ccce2e0b164c86303c", - "sha256:d6a96eef20f639e6a97d23e57dd0c1b1069a7b4fd7027482a4c5c451cd7732f4", - "sha256:d9caa9d5e682102453d96a0ee10c7241b72859b01a941a397fd965f23b3e016b", - "sha256:dd1c8f6bd65d07d3810b90d02eba7997e32abbdf1277a481d698969e921a3be0", - "sha256:e31f0bb5928b793169b87e3d1e070f2342b22d5245c755e2b81caa29756246c3", - "sha256:ecb55251139706669fdec2ff073c98ef8e9a84473e51e716211b41aa0f18e656", - "sha256:ee5ec40fdd06d62fe5d4084bef4fd50fd4bb6bfd2bf519365f569dc470163ab0", - "sha256:f17e562de9edf691a42ddb1eb4a5541c20dd3f9e65b09ded2beb0799c0cf29bb", - "sha256:fdffbfb6832cd0b300995a2b08b8f6fa9f6e856d562800fea9182316d99c4e8e" - ], - "index": "pypi", - "version": "==1.21.6" - }, - "packaging": { - "hashes": [ - "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", - "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" - ], - "version": "==21.3" - }, - "pandablocks": { - "editable": true, - "extras": [ - "hdf5" - ], - "path": "." - }, - "pillow": { - "hashes": [ - "sha256:01425106e4e8cee195a411f729cff2a7d61813b0b11737c12bd5991f5f14bcd5", - "sha256:031a6c88c77d08aab84fecc05c3cde8414cd6f8406f4d2b16fed1e97634cc8a4", - "sha256:083781abd261bdabf090ad07bb69f8f5599943ddb539d64497ed021b2a67e5a9", - "sha256:0d19d70ee7c2ba97631bae1e7d4725cdb2ecf238178096e8c82ee481e189168a", - "sha256:0e04d61f0064b545b989126197930807c86bcbd4534d39168f4aa5fda39bb8f9", - "sha256:12e5e7471f9b637762453da74e390e56cc43e486a88289995c1f4c1dc0bfe727", - "sha256:22fd0f42ad15dfdde6c581347eaa4adb9a6fc4b865f90b23378aa7914895e120", - "sha256:238c197fc275b475e87c1453b05b467d2d02c2915fdfdd4af126145ff2e4610c", - "sha256:3b570f84a6161cf8865c4e08adf629441f56e32f180f7aa4ccbd2e0a5a02cba2", - "sha256:463822e2f0d81459e113372a168f2ff59723e78528f91f0bd25680ac185cf797", - "sha256:4d98abdd6b1e3bf1a1cbb14c3895226816e666749ac040c4e2554231068c639b", - "sha256:5afe6b237a0b81bd54b53f835a153770802f164c5570bab5e005aad693dab87f", - "sha256:5b70110acb39f3aff6b74cf09bb4169b167e2660dabc304c1e25b6555fa781ef", - "sha256:5cbf3e3b1014dddc45496e8cf38b9f099c95a326275885199f427825c6522232", - "sha256:624b977355cde8b065f6d51b98497d6cd5fbdd4f36405f7a8790e3376125e2bb", - "sha256:63728564c1410d99e6d1ae8e3b810fe012bc440952168af0a2877e8ff5ab96b9", - "sha256:66cc56579fd91f517290ab02c51e3a80f581aba45fd924fcdee01fa06e635812", - "sha256:6c32cc3145928c4305d142ebec682419a6c0a8ce9e33db900027ddca1ec39178", - "sha256:8bb1e155a74e1bfbacd84555ea62fa21c58e0b4e7e6b20e4447b8d07990ac78b", - "sha256:95d5ef984eff897850f3a83883363da64aae1000e79cb3c321915468e8c6add5", - "sha256:a013cbe25d20c2e0c4e85a9daf438f85121a4d0344ddc76e33fd7e3965d9af4b", - "sha256:a787ab10d7bb5494e5f76536ac460741788f1fbce851068d73a87ca7c35fc3e1", - "sha256:a7d5e9fad90eff8f6f6106d3b98b553a88b6f976e51fce287192a5d2d5363713", - "sha256:aac00e4bc94d1b7813fe882c28990c1bc2f9d0e1aa765a5f2b516e8a6a16a9e4", - "sha256:b91c36492a4bbb1ee855b7d16fe51379e5f96b85692dc8210831fbb24c43e484", - "sha256:c03c07ed32c5324939b19e36ae5f75c660c81461e312a41aea30acdd46f93a7c", - "sha256:c5236606e8570542ed424849f7852a0ff0bce2c4c8d0ba05cc202a5a9c97dee9", - "sha256:c6b39294464b03457f9064e98c124e09008b35a62e3189d3513e5148611c9388", - "sha256:cb7a09e173903541fa888ba010c345893cd9fc1b5891aaf060f6ca77b6a3722d", - "sha256:d68cb92c408261f806b15923834203f024110a2e2872ecb0bd2a110f89d3c602", - "sha256:dc38f57d8f20f06dd7c3161c59ca2c86893632623f33a42d592f097b00f720a9", - "sha256:e98eca29a05913e82177b3ba3d198b1728e164869c613d76d0de4bde6768a50e", - "sha256:f217c3954ce5fd88303fc0c317af55d5e0204106d86dea17eb8205700d47dec2" - ], - "version": "==8.2.0" - }, - "pyparsing": { - "hashes": [ - "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", - "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" - ], - "version": "==3.0.9" - }, - "python-dateutil": { - "hashes": [ - "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", - "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" - ], - "version": "==2.8.2" - }, - "setuptools-scm": { - "hashes": [ - "sha256:031e13af771d6f892b941adb6ea04545bbf91ebc5ce68c78aaf3fff6e1fb4844", - "sha256:7930f720905e03ccd1e1d821db521bff7ec2ac9cf0ceb6552dd73d24a45d3b02" - ], - "version": "==7.0.5" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "version": "==1.16.0" - }, - "tomli": { - "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" - ], - "version": "==2.0.1" - }, - "typing-extensions": { - "hashes": [ - "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", - "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" - ], - "index": "pypi", - "version": "==4.4.0" - }, - "zipp": { - "hashes": [ - "sha256:3a7af91c3db40ec72dd9d154ae18e008c69efe8ca88dde4f9a731bb82fe2f9eb", - "sha256:972cfa31bc2fedd3fa838a51e9bc7e64b7fb725a8c00e7431554311f180e9980" - ], - "version": "==3.9.0" - } - }, - "develop": { - "alabaster": { - "hashes": [ - "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", - "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" - ], - "version": "==0.7.12" - }, - "atomicwrites": { - "hashes": [ - "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197", - "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a" - ], - "index": "pypi", - "version": "==1.4.0" - }, - "attrs": { - "hashes": [ - "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6", - "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c" - ], - "version": "==22.1.0" - }, - "babel": { - "hashes": [ - "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe", - "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6" - ], - "version": "==2.11.0" - }, - "black": { - "hashes": [ - "sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411", - "sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c", - "sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497", - "sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e", - "sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342", - "sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27", - "sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41", - "sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab", - "sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5", - "sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16", - "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e", - "sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c", - "sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe", - "sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3", - "sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec", - "sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3", - "sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd", - "sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c", - "sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4", - "sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90", - "sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869", - "sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747", - "sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875" - ], - "index": "pypi", - "version": "==22.8.0" - }, - "certifi": { - "hashes": [ - "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", - "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" - ], - "version": "==2022.12.7" - }, - "charset-normalizer": { - "hashes": [ - "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", - "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" - ], - "version": "==2.1.1" - }, - "click": { - "hashes": [ - "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", - "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" - ], - "version": "==8.1.3" - }, - "coverage": { - "extras": [ - "toml" - ], - "hashes": [ - "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79", - "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a", - "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f", - "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a", - "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa", - "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398", - "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba", - "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d", - "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf", - "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b", - "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518", - "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d", - "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795", - "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2", - "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e", - "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32", - "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745", - "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b", - "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e", - "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d", - "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f", - "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660", - "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62", - "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6", - "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04", - "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c", - "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5", - "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef", - "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc", - "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae", - "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578", - "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466", - "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4", - "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91", - "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0", - "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4", - "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b", - "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe", - "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b", - "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75", - "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b", - "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c", - "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72", - "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b", - "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f", - "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e", - "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53", - "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3", - "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84", - "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987" - ], - "version": "==6.5.0" - }, - "docutils": { - "hashes": [ - "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125", - "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61" - ], - "version": "==0.17.1" - }, - "filelock": { - "hashes": [ - "sha256:7565f628ea56bfcd8e54e42bdc55da899c85c1abfe1b5bcfd147e9188cebb3b2", - "sha256:8df285554452285f79c035efb0c861eb33a4bcfa5b7a137016e32e6a90f9792c" - ], - "version": "==3.8.2" - }, - "flake8": { - "hashes": [ - "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d", - "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d" - ], - "index": "pypi", - "version": "==4.0.1" - }, - "flake8-isort": { - "hashes": [ - "sha256:0951398c343c67f4933407adbbfb495d4df7c038650c5d05753a006efcfeb390", - "sha256:8c4ab431d87780d0c8336e9614e50ef11201bc848ef64ca017532dec39d4bf49" - ], - "index": "pypi", - "version": "==5.0.3" - }, - "idna": { - "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" - ], - "version": "==3.4" - }, - "imagesize": { - "hashes": [ - "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", - "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a" - ], - "version": "==1.4.1" - }, - "importlib-metadata": { - "hashes": [ - "sha256:175f4ee440a0317f6e8d81b7f8d4869f93316170a65ad2b007d2929186c8052c", - "sha256:e0bc84ff355328a4adfc5240c4f211e0ab386f80aa640d1b11f0618a1d282094" - ], - "markers": "python_version < '3.8'", - "version": "==4.11.1" - }, - "iniconfig": { - "hashes": [ - "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", - "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32" - ], - "version": "==1.1.1" - }, - "isort": { - "hashes": [ - "sha256:dd8bbc5c0990f2a095d754e50360915f73b4c26fc82733eb5bfc6b48396af4d2", - "sha256:e486966fba83f25b8045f8dd7455b0a0d1e4de481e1d7ce4669902d9fb85e622" - ], - "index": "pypi", - "version": "==5.11.2" - }, - "jinja2": { - "hashes": [ - "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", - "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" - ], - "version": "==3.1.2" - }, - "markupsafe": { - "hashes": [ - "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003", - "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88", - "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5", - "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7", - "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a", - "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603", - "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1", - "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135", - "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247", - "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6", - "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601", - "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77", - "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02", - "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e", - "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63", - "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f", - "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980", - "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b", - "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812", - "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff", - "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96", - "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1", - "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925", - "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a", - "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6", - "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e", - "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f", - "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4", - "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f", - "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3", - "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c", - "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a", - "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417", - "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a", - "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a", - "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37", - "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452", - "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933", - "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a", - "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7" - ], - "version": "==2.1.1" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "mock": { - "hashes": [ - "sha256:122fcb64ee37cfad5b3f48d7a7d51875d7031aaf3d8be7c42e2bee25044eee62", - "sha256:7d3fbbde18228f4ff2f1f119a45cdffa458b4c0dee32eb4d2bb2f82554bac7bc" - ], - "index": "pypi", - "version": "==4.0.3" - }, - "mypy": { - "hashes": [ - "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d", - "sha256:0c8f3be99e8a8bd403caa8c03be619544bc2c77a7093685dcf308c6b109426c6", - "sha256:0cca5adf694af539aeaa6ac633a7afe9bbd760df9d31be55ab780b77ab5ae8bf", - "sha256:1c8cd4fb70e8584ca1ed5805cbc7c017a3d1a29fb450621089ffed3e99d1857f", - "sha256:1f7d1a520373e2272b10796c3ff721ea1a0712288cafaa95931e66aa15798813", - "sha256:209ee89fbb0deed518605edddd234af80506aec932ad28d73c08f1400ef80a33", - "sha256:26efb2fcc6b67e4d5a55561f39176821d2adf88f2745ddc72751b7890f3194ad", - "sha256:37bd02ebf9d10e05b00d71302d2c2e6ca333e6c2a8584a98c00e038db8121f05", - "sha256:3a700330b567114b673cf8ee7388e949f843b356a73b5ab22dd7cff4742a5297", - "sha256:3c0165ba8f354a6d9881809ef29f1a9318a236a6d81c690094c5df32107bde06", - "sha256:3d80e36b7d7a9259b740be6d8d906221789b0d836201af4234093cae89ced0cd", - "sha256:4175593dc25d9da12f7de8de873a33f9b2b8bdb4e827a7cae952e5b1a342e243", - "sha256:4307270436fd7694b41f913eb09210faff27ea4979ecbcd849e57d2da2f65305", - "sha256:5e80e758243b97b618cdf22004beb09e8a2de1af481382e4d84bc52152d1c476", - "sha256:641411733b127c3e0dab94c45af15fea99e4468f99ac88b39efb1ad677da5711", - "sha256:652b651d42f155033a1967739788c436491b577b6a44e4c39fb340d0ee7f0d70", - "sha256:6d7464bac72a85cb3491c7e92b5b62f3dcccb8af26826257760a552a5e244aa5", - "sha256:74e259b5c19f70d35fcc1ad3d56499065c601dfe94ff67ae48b85596b9ec1461", - "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab", - "sha256:901c2c269c616e6cb0998b33d4adbb4a6af0ac4ce5cd078afd7bc95830e62c1c", - "sha256:98e781cd35c0acf33eb0295e8b9c55cdbef64fcb35f6d3aa2186f289bed6e80d", - "sha256:a12c56bf73cdab116df96e4ff39610b92a348cc99a1307e1da3c3768bbb5b135", - "sha256:ac6e503823143464538efda0e8e356d871557ef60ccd38f8824a4257acc18d93", - "sha256:b8472f736a5bfb159a5e36740847808f6f5b659960115ff29c7cecec1741c648", - "sha256:b86ce2c1866a748c0f6faca5232059f881cda6dda2a893b9a8373353cfe3715a", - "sha256:bc9ec663ed6c8f15f4ae9d3c04c989b744436c16d26580eaa760ae9dd5d662eb", - "sha256:c9166b3f81a10cdf9b49f2d594b21b31adadb3d5e9db9b834866c3258b695be3", - "sha256:d13674f3fb73805ba0c45eb6c0c3053d218aa1f7abead6e446d474529aafc372", - "sha256:de32edc9b0a7e67c2775e574cb061a537660e51210fbf6006b0b36ea695ae9bb", - "sha256:e62ebaad93be3ad1a828a11e90f0e76f15449371ffeecca4a0a0b9adc99abcef" - ], - "index": "pypi", - "version": "==0.991" - }, - "mypy-extensions": { - "hashes": [ - "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", - "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" - ], - "version": "==0.4.3" - }, - "packaging": { - "hashes": [ - "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", - "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" - ], - "version": "==21.3" - }, - "pathspec": { - "hashes": [ - "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93", - "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d" - ], - "version": "==0.10.1" - }, - "platformdirs": { - "hashes": [ - "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", - "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" - ], - "version": "==2.5.2" - }, - "pluggy": { - "hashes": [ - "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159", - "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3" - ], - "version": "==1.0.0" - }, - "py": { - "hashes": [ - "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", - "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" - ], - "version": "==1.11.0" - }, - "pycodestyle": { - "hashes": [ - "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20", - "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f" - ], - "version": "==2.8.0" - }, - "pyflakes": { - "hashes": [ - "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c", - "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e" - ], - "version": "==2.4.0" - }, - "pygments": { - "hashes": [ - "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1", - "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42" - ], - "version": "==2.13.0" - }, - "pyparsing": { - "hashes": [ - "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", - "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" - ], - "version": "==3.0.9" - }, - "pytest": { - "hashes": [ - "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7", - "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39" - ], - "version": "==7.1.3" - }, - "pytest-asyncio": { - "hashes": [ - "sha256:6d895b02432c028e6957d25fc936494e78c6305736e785d9fee408b1efbc7ff4", - "sha256:e0fe5dbea40516b661ef1bcfe0bd9461c2847c4ef4bb40012324f2454fb7d56d" - ], - "index": "pypi", - "version": "==0.17.2" - }, - "pytest-black": { - "hashes": [ - "sha256:1d339b004f764d6cd0f06e690f6dd748df3d62e6fe1a692d6a5500ac2c5b75a5" - ], - "index": "pypi", - "version": "==0.3.12" - }, - "pytest-cov": { - "hashes": [ - "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b", - "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470" - ], - "index": "pypi", - "version": "==4.0.0" - }, - "pytest-flake8": { - "hashes": [ - "sha256:ba4f243de3cb4c2486ed9e70752c80dd4b636f7ccb27d4eba763c35ed0cd316e", - "sha256:e0661a786f8cbf976c185f706fdaf5d6df0b1667c3bcff8e823ba263618627e7" - ], - "index": "pypi", - "version": "==1.1.1" - }, - "pytest-mypy": { - "hashes": [ - "sha256:1fa55723a4bf1d054fcba1c3bd694215a2a65cc95ab10164f5808afd893f3b11", - "sha256:6e68e8eb7ceeb7d1c83a1590912f784879f037b51adfb9c17b95c6b2fc57466b" - ], - "index": "pypi", - "version": "==0.8.1" - }, - "pytz": { - "hashes": [ - "sha256:2c0784747071402c6e99f0bafdb7da0fa22645f06554c7ae06bf6358897e9c91", - "sha256:48ce799d83b6f8aab2020e369b627446696619e79645419610b9facd909b3174" - ], - "version": "==2022.4" - }, - "requests": { - "hashes": [ - "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", - "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" - ], - "version": "==2.28.1" - }, - "snowballstemmer": { - "hashes": [ - "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", - "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" - ], - "version": "==2.2.0" - }, - "sphinx": { - "hashes": [ - "sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c", - "sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851" - ], - "index": "pypi", - "version": "==4.3.2" - }, - "sphinx-rtd-theme": { - "hashes": [ - "sha256:4d35a56f4508cfee4c4fb604373ede6feae2a306731d533f409ef5c3496fdbd8", - "sha256:eec6d497e4c2195fa0e8b2016b337532b8a699a68bcb22a512870e16925c6a5c" - ], - "index": "pypi", - "version": "==1.0.0" - }, - "sphinxcontrib-applehelp": { - "hashes": [ - "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", - "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" - ], - "version": "==1.0.2" - }, - "sphinxcontrib-devhelp": { - "hashes": [ - "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", - "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" - ], - "version": "==1.0.2" - }, - "sphinxcontrib-htmlhelp": { - "hashes": [ - "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07", - "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2" - ], - "version": "==2.0.0" - }, - "sphinxcontrib-jsmath": { - "hashes": [ - "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", - "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" - ], - "version": "==1.0.1" - }, - "sphinxcontrib-qthelp": { - "hashes": [ - "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", - "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" - ], - "version": "==1.0.3" - }, - "sphinxcontrib-serializinghtml": { - "hashes": [ - "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd", - "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952" - ], - "version": "==1.1.5" - }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" - ], - "version": "==0.10.2" - }, - "tomli": { - "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" - ], - "version": "==2.0.1" - }, - "typed-ast": { - "hashes": [ - "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2", - "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1", - "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6", - "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62", - "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac", - "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d", - "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc", - "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2", - "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97", - "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35", - "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6", - "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1", - "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4", - "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c", - "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e", - "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec", - "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f", - "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72", - "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47", - "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72", - "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe", - "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6", - "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3", - "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66" - ], - "index": "pypi", - "version": "==1.5.4" - }, - "types-mock": { - "hashes": [ - "sha256:4535fbb3912b88a247d43cdb41db0c8b2e187138986f6f01a989717e56105848", - "sha256:a849bc2d966063f4946013bf404822ee2b96f77a8dccda4174b70ab61c5293fe" - ], - "index": "pypi", - "version": "==4.0.15" - }, - "typing-extensions": { - "hashes": [ - "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", - "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" - ], - "index": "pypi", - "version": "==4.4.0" - }, - "urllib3": { - "hashes": [ - "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", - "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997" - ], - "version": "==1.26.12" - }, - "zipp": { - "hashes": [ - "sha256:3a7af91c3db40ec72dd9d154ae18e008c69efe8ca88dde4f9a731bb82fe2f9eb", - "sha256:972cfa31bc2fedd3fa838a51e9bc7e64b7fb725a8c00e7431554311f180e9980" - ], - "version": "==3.9.0" - } - } -} diff --git a/CHANGELOG.rst b/docs/CHANGELOG.rst similarity index 100% rename from CHANGELOG.rst rename to docs/CHANGELOG.rst diff --git a/CONTRIBUTING.rst b/docs/CONTRIBUTING.rst similarity index 100% rename from CONTRIBUTING.rst rename to docs/CONTRIBUTING.rst diff --git a/pandablocks/__init__.py b/pandablocks/__init__.py deleted file mode 100644 index 7cf448dad..000000000 --- a/pandablocks/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from pandablocks._version_git import __version__ - -__all__ = ["__version__"] diff --git a/pandablocks/__main__.py b/pandablocks/__main__.py deleted file mode 100644 index 4672f7385..000000000 --- a/pandablocks/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -from pandablocks.cli import cli - -# test with: -# pipenv run python -m pandablocks -if __name__ == "__main__": - cli() diff --git a/pyproject.toml b/pyproject.toml index bd0154f7a..230863c8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,6 +3,7 @@ requires = ["setuptools>=64", "setuptools_scm[toml]>=6.2", "wheel"] build-backend = "setuptools.build_meta" [project] +description = "A Python client to control and data ports of the PandABlocks TCP server" name = "pandablocks" classifiers = [ "Development Status :: 3 - Alpha", @@ -13,24 +14,30 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ] -description = "One line description of your module" -dependencies = [ - "typing-extensions;python_version<'3.8'", -] # Add project dependencies here, e.g. ["click", "numpy"] +dependencies = ["typing-extensions;python_version<'3.8'", "numpy", "click"] dynamic = ["version"] -license.file = "LICENSE" +license.file = "Apache License 2.0" readme = "README.rst" requires-python = ">=3.7" [project.optional-dependencies] +h5py = ["h5py", "matplotlib"] dev = [ + # A dev install will require [h5py] packages too + "h5py", + "matplotlib", + "black", "mypy", + "mock", + "types-mock", + "atomicwrites", + "typed-ast", "pipdeptree", "pre-commit", "pydata-sphinx-theme>=0.12", - "pytest", "pytest-cov", + "pytest-asyncio", "ruff", "sphinx-autobuild", "sphinx-copybutton", @@ -40,10 +47,10 @@ dev = [ ] [project.scripts] -pandablocks = "pandablocks.__main__:main" +pandablocks = "pandablocks.cli:cli" [project.urls] -GitHub = "https://github.com/PandABlocks/pandablocks" +GitHub = "https://github.com/PandABlocks/Pandablocks-client" [[project.authors]] # Further authors may be added by duplicating this section email = "tom.cobb@diamond.ac.uk" @@ -60,7 +67,9 @@ ignore_missing_imports = true # Ignore missing stubs in imported modules # Run pytest with all our checkers, and don't spam us with massive tracebacks on error addopts = """ --tb=native -vv --doctest-modules --doctest-glob="*.rst" + --cov=pandablocks --cov-report term --cov-report xml:cov.xml """ +asyncio_mode = "auto" # https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings filterwarnings = "error" # Doctest python code in docs, python code in src docstrings, test functions in tests @@ -71,7 +80,7 @@ data_file = "/tmp/pandablocks.coverage" [tool.coverage.paths] # Tests are run from installed location, map back to the src directory -source = ["src", "**/site-packages/"] +source = ["src/pandablocks", "**/site-packages/"] # tox must currently be configured via an embedded ini string # See: https://github.com/tox-dev/tox/issues/999 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 29e341b89..000000000 --- a/setup.cfg +++ /dev/null @@ -1,70 +0,0 @@ -[metadata] -name = pandablocks -description = A Python client to control and data ports of the PandABlocks TCP server -url = https://github.com/PandABlocks/PandABlocks-client -author = Tom Cobb -author_email = tom.cobb@diamond.ac.uk -license = Apache License 2.0 -long_description = file: README.rst -long_description_content_type = text/x-rst -classifiers = - Development Status :: 4 - Beta - License :: OSI Approved :: Apache Software License - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - -[options] -packages = find: -install_requires = - numpy - click - importlib-metadata <5.0 # 5.0 deprecated a lot of interfaces that various modules rely on - -[options.extras_require] -hdf5 = - matplotlib - h5py - -[options.entry_points] -# Include a command line script -console_scripts = - pandablocks = pandablocks.cli:cli - -[options.packages.find] -# Don't include our tests directory in the distribution -exclude = tests - -[options.package_data] -pandablocks = - saves/*.sav - -[mypy] -# Ignore missing stubs for modules we use -ignore_missing_imports = True - -[isort] -profile=black -float_to_top=true -skip=setup.py,conf.py,build - -[flake8] -# Make flake8 respect black's line length (default 88), -max-line-length = 88 -extend-ignore = - E203, # See https://github.com/PyCQA/pycodestyle/issues/373 - F811, # support typing.overload decorator - F722, # allow Annotated[typ, some_func("some string")] - -[tool:pytest] -# Run pytest with all our checkers, and don't spam us with massive tracebacks on error -addopts = - --tb=native -vv --flake8 --black --mypy --doctest-modules --doctest-glob="*.rst" - --cov=pandablocks --cov-report term --cov-report xml:cov.xml -# Enables all discovered async tests and fixtures to be automatically marked as async, even if -# they don't have a specific marker https://github.com/pytest-dev/pytest-asyncio#auto-mode -asyncio_mode = auto - -[coverage:run] -# This is covered in the versiongit test suite so exclude it here -omit = */_version_git.py diff --git a/setup.py b/setup.py deleted file mode 100644 index d11d75416..000000000 --- a/setup.py +++ /dev/null @@ -1,17 +0,0 @@ -import os -import sys - -from setuptools import setup - -# Place the directory containing _version_git on the path -for path, _, filenames in os.walk(os.path.dirname(os.path.abspath(__file__))): - if "_version_git.py" in filenames: - sys.path.append(path) - break - -from _version_git import __version__, get_cmdclass # type: ignore # noqa isort:skip - - -# Setup information is stored in setup.cfg but this function call -# is still necessary. -setup(cmdclass=get_cmdclass(), version=__version__) diff --git a/examples/README.rst b/src/examples/README.rst similarity index 100% rename from examples/README.rst rename to src/examples/README.rst diff --git a/examples/arm_and_hdf.py b/src/examples/arm_and_hdf.py similarity index 100% rename from examples/arm_and_hdf.py rename to src/examples/arm_and_hdf.py diff --git a/examples/hdf_queue_reporting.py b/src/examples/hdf_queue_reporting.py similarity index 100% rename from examples/hdf_queue_reporting.py rename to src/examples/hdf_queue_reporting.py diff --git a/examples/introspect_panda.py b/src/examples/introspect_panda.py similarity index 100% rename from examples/introspect_panda.py rename to src/examples/introspect_panda.py diff --git a/examples/plot_counter_hdf.py b/src/examples/plot_counter_hdf.py similarity index 100% rename from examples/plot_counter_hdf.py rename to src/examples/plot_counter_hdf.py diff --git a/pandablocks/_control.py b/src/pandablocks/_control.py similarity index 100% rename from pandablocks/_control.py rename to src/pandablocks/_control.py diff --git a/pandablocks/_exchange.py b/src/pandablocks/_exchange.py similarity index 100% rename from pandablocks/_exchange.py rename to src/pandablocks/_exchange.py diff --git a/pandablocks/_version_git.py b/src/pandablocks/_version_git.py similarity index 100% rename from pandablocks/_version_git.py rename to src/pandablocks/_version_git.py diff --git a/pandablocks/asyncio.py b/src/pandablocks/asyncio.py similarity index 100% rename from pandablocks/asyncio.py rename to src/pandablocks/asyncio.py diff --git a/pandablocks/blocking.py b/src/pandablocks/blocking.py similarity index 100% rename from pandablocks/blocking.py rename to src/pandablocks/blocking.py diff --git a/pandablocks/cli.py b/src/pandablocks/cli.py similarity index 100% rename from pandablocks/cli.py rename to src/pandablocks/cli.py diff --git a/pandablocks/commands.py b/src/pandablocks/commands.py similarity index 100% rename from pandablocks/commands.py rename to src/pandablocks/commands.py diff --git a/pandablocks/connections.py b/src/pandablocks/connections.py similarity index 100% rename from pandablocks/connections.py rename to src/pandablocks/connections.py diff --git a/pandablocks/hdf.py b/src/pandablocks/hdf.py similarity index 100% rename from pandablocks/hdf.py rename to src/pandablocks/hdf.py diff --git a/pandablocks/responses.py b/src/pandablocks/responses.py similarity index 100% rename from pandablocks/responses.py rename to src/pandablocks/responses.py diff --git a/pandablocks/saves/tutorial.sav b/src/pandablocks/saves/tutorial.sav similarity index 100% rename from pandablocks/saves/tutorial.sav rename to src/pandablocks/saves/tutorial.sav diff --git a/pandablocks/utils.py b/src/pandablocks/utils.py similarity index 100% rename from pandablocks/utils.py rename to src/pandablocks/utils.py diff --git a/tests/test_boilerplate_removed.py b/tests/test_boilerplate_removed.py deleted file mode 100644 index 46777a129..000000000 --- a/tests/test_boilerplate_removed.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -This file checks that all the example boilerplate text has been removed. -It can be deleted when all the contained tests pass -""" -import sys -from pathlib import Path - -if sys.version_info < (3, 8): - from importlib_metadata import metadata # noqa -else: - from importlib.metadata import metadata # noqa - -ROOT = Path(__file__).parent.parent - - -def skeleton_check(check: bool, text: str): - if ROOT.name == "python3-pip-skeleton" or str(ROOT) == "/project": - # In the skeleton module the check should fail - check = not check - text = f"Skeleton didn't raise: {text}" - if check: - raise AssertionError(text) - - -def assert_not_contains_text(path: str, text: str, explanation: str): - full_path = ROOT / path - if full_path.exists(): - contents = full_path.read_text().replace("\n", " ") - skeleton_check(text in contents, f"Please change ./{path} {explanation}") - - -# pyproject.toml -def test_module_summary(): - summary = metadata("pandablocks")["summary"] - skeleton_check( - "One line description of your module" in summary, - "Please change project.description in ./pyproject.toml " - "to be a one line description of your module", - ) - - -# README -def test_changed_README_intro(): - assert_not_contains_text( - "README.rst", - "This is where you should write a short paragraph", - "to include an intro on what your module does", - ) - - -def test_removed_adopt_skeleton(): - assert_not_contains_text( - "README.rst", - "This project contains template code only", - "remove the note at the start", - ) - - -def test_changed_README_body(): - assert_not_contains_text( - "README.rst", - "This is where you should put some images or code snippets", - "to include some features and why people should use it", - ) From 8c65af3f3130b8611a1e72232ae35095a325c2ad Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Tue, 17 Oct 2023 14:35:20 +0100 Subject: [PATCH 69/76] Fixed tests --- pyproject.toml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 230863c8f..c720497de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,11 +67,9 @@ ignore_missing_imports = true # Ignore missing stubs in imported modules # Run pytest with all our checkers, and don't spam us with massive tracebacks on error addopts = """ --tb=native -vv --doctest-modules --doctest-glob="*.rst" - --cov=pandablocks --cov-report term --cov-report xml:cov.xml + --cov=pandablocks --cov-report term --cov-report xml:cov.xml """ asyncio_mode = "auto" -# https://iscinumpy.gitlab.io/post/bound-version-constraints/#watch-for-warnings -filterwarnings = "error" # Doctest python code in docs, python code in src docstrings, test functions in tests testpaths = "docs src tests" @@ -80,7 +78,7 @@ data_file = "/tmp/pandablocks.coverage" [tool.coverage.paths] # Tests are run from installed location, map back to the src directory -source = ["src/pandablocks", "**/site-packages/"] +source = ["src", "**/site-packages/"] # tox must currently be configured via an embedded ini string # See: https://github.com/tox-dev/tox/issues/999 @@ -100,7 +98,7 @@ allowlist_externals = sphinx-build sphinx-autobuild commands = - pytest: pytest --cov=pandablocks --cov-report term --cov-report xml:cov.xml {posargs} + pytest: pytest {posargs} mypy: mypy src tests {posargs} pre-commit: pre-commit run --all-files {posargs} docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html From 5a3ce7202f50b8438365a5bfa998fbbccb7640a1 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Tue, 17 Oct 2023 14:40:01 +0100 Subject: [PATCH 70/76] Made ruff and mypy complient, moved 'examples' into src/pandablocks --- docs/conf.py | 14 +++++++------- src/pandablocks/_version_git.py | 2 +- src/pandablocks/commands.py | 13 ------------- src/{ => pandablocks}/examples/README.rst | 0 src/{ => pandablocks}/examples/arm_and_hdf.py | 0 .../examples/hdf_queue_reporting.py | 0 src/{ => pandablocks}/examples/introspect_panda.py | 1 - src/{ => pandablocks}/examples/plot_counter_hdf.py | 0 tests/conftest.py | 1 - tests/test_asyncio.py | 4 +++- tests/test_utils.py | 14 +++++++------- 11 files changed, 18 insertions(+), 31 deletions(-) rename src/{ => pandablocks}/examples/README.rst (100%) rename src/{ => pandablocks}/examples/arm_and_hdf.py (100%) rename src/{ => pandablocks}/examples/hdf_queue_reporting.py (100%) rename src/{ => pandablocks}/examples/introspect_panda.py (99%) rename src/{ => pandablocks}/examples/plot_counter_hdf.py (100%) diff --git a/docs/conf.py b/docs/conf.py index 502e9bf14..c44614a86 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -67,7 +67,7 @@ ("py:class", "'object'"), ("py:class", "'id'"), ("py:class", "typing_extensions.Literal"), - ("py:func", "int") + ("py:func", "int"), ] # Both the class’ and the __init__ method’s docstring are concatenated and @@ -103,14 +103,14 @@ # This means you can link things like `str` and `asyncio` to the relevant # docs in the python documentation. -intersphinx_mapping = dict( - python=("https://docs.python.org/3/", None), - numpy=("https://numpy.org/doc/stable/", None), - h5py=("https://docs.h5py.org/en/stable/", None), -) +intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), + "numpy": ("https://numpy.org/doc/stable/", None), + "h5py": ("https://docs.h5py.org/en/stable/", None), +} # A dictionary of graphviz graph attributes for inheritance diagrams. -inheritance_graph_attrs = dict(rankdir="TB") +inheritance_graph_attrs = {"rankdir": "TB"} # Common links that should be available on every page rst_epilog = """ diff --git a/src/pandablocks/_version_git.py b/src/pandablocks/_version_git.py index ec811d1bf..986383ecd 100644 --- a/src/pandablocks/_version_git.py +++ b/src/pandablocks/_version_git.py @@ -94,4 +94,4 @@ def make_release_tree(self, base_dir, files): for pkg in self.distribution.packages: make_version_static(base_dir, pkg) - return dict(build_py=BuildPy, sdist=Sdist) + return {"build_py": BuildPy, "sdist": Sdist} diff --git a/src/pandablocks/commands.py b/src/pandablocks/commands.py index abb063df9..d273a66ee 100644 --- a/src/pandablocks/commands.py +++ b/src/pandablocks/commands.py @@ -424,7 +424,6 @@ class GetFieldInfo(Command[Dict[str, FieldInfo]]): ] = field(init=False, repr=False, default_factory=dict) def __post_init__(self): - # Map a (type, subtype) to a method that returns the appropriate # subclasss of FieldInfo, and a list of all the Commands to request. # Note that fields that do not have additional attributes are not listed. @@ -472,7 +471,6 @@ def _get_desc(self, field_name: str) -> GetLine: def _uint( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, maximum = yield from _execute_commands( self._get_desc(field_name), GetLine(f"{self.block}1.{field_name}.MAX"), @@ -484,7 +482,6 @@ def _uint( def _scalar( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, units, scale, offset = yield from _execute_commands( self._get_desc(field_name), GetLine(f"{self.block}.{field_name}.UNITS"), @@ -501,7 +498,6 @@ def _scalar( def _subtype_time( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, units_labels = yield from _execute_commands( self._get_desc(field_name), GetMultiline(f"*ENUMS.{self.block}.{field_name}.UNITS"), @@ -514,7 +510,6 @@ def _subtype_time( def _enum( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, labels = yield from _execute_commands( self._get_desc(field_name), GetMultiline(f"*ENUMS.{self.block}.{field_name}"), @@ -527,7 +522,6 @@ def _enum( def _time( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, units, min = yield from _execute_commands( self._get_desc(field_name), GetMultiline(f"*ENUMS.{self.block}.{field_name}.UNITS"), @@ -541,7 +535,6 @@ def _time( def _bit_out( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, capture_word, offset = yield from _execute_commands( self._get_desc(field_name), GetLine(f"{self.block}1.{field_name}.CAPTURE_WORD"), @@ -557,7 +550,6 @@ def _bit_out( def _bit_mux( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, max_delay, labels = yield from _execute_commands( self._get_desc(field_name), GetLine(f"{self.block}1.{field_name}.MAX_DELAY"), @@ -573,7 +565,6 @@ def _bit_mux( def _pos_mux( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, labels = yield from _execute_commands( self._get_desc(field_name), GetMultiline(f"*ENUMS.{self.block}.{field_name}"), @@ -585,7 +576,6 @@ def _pos_mux( def _table( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - # Ignore the ROW_WORDS attribute as it's new and won't be present on all PandAs, # and there's no easy way to try it and catch an error while also running other # Get commands at the same time @@ -655,7 +645,6 @@ def _table( def _pos_out( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, capture_labels = yield from _execute_commands( self._get_desc(field_name), GetMultiline(f"*ENUMS.{self.block}.{field_name}.CAPTURE"), @@ -667,7 +656,6 @@ def _pos_out( def _ext_out( self, field_name: str, field_type: str, field_subtype: Optional[str] ) -> _FieldGeneratorType: - desc, capture_labels = yield from _execute_commands( self._get_desc(field_name), GetMultiline(f"*ENUMS.{self.block}.{field_name}.CAPTURE"), @@ -845,7 +833,6 @@ def execute(self) -> ExchangeGenerator[Changes]: multivalue_get_commands: List[Tuple[str, GetMultiline]] = [] for line in ex.multiline: if line[-1] == "<": - if self.get_multiline: field = line[0:-1] multivalue_get_commands.append((field, GetMultiline(field))) diff --git a/src/examples/README.rst b/src/pandablocks/examples/README.rst similarity index 100% rename from src/examples/README.rst rename to src/pandablocks/examples/README.rst diff --git a/src/examples/arm_and_hdf.py b/src/pandablocks/examples/arm_and_hdf.py similarity index 100% rename from src/examples/arm_and_hdf.py rename to src/pandablocks/examples/arm_and_hdf.py diff --git a/src/examples/hdf_queue_reporting.py b/src/pandablocks/examples/hdf_queue_reporting.py similarity index 100% rename from src/examples/hdf_queue_reporting.py rename to src/pandablocks/examples/hdf_queue_reporting.py diff --git a/src/examples/introspect_panda.py b/src/pandablocks/examples/introspect_panda.py similarity index 99% rename from src/examples/introspect_panda.py rename to src/pandablocks/examples/introspect_panda.py index 29b2a9eb3..15112c421 100644 --- a/src/examples/introspect_panda.py +++ b/src/pandablocks/examples/introspect_panda.py @@ -9,7 +9,6 @@ async def introspect(): # Create a client and connect the control and data ports async with AsyncioClient(sys.argv[1]) as client: - # Get the list of all blocks in the PandA block_info = await client.send(GetBlockInfo()) # Find and print all fields for each block diff --git a/src/examples/plot_counter_hdf.py b/src/pandablocks/examples/plot_counter_hdf.py similarity index 100% rename from src/examples/plot_counter_hdf.py rename to src/pandablocks/examples/plot_counter_hdf.py diff --git a/tests/conftest.py b/tests/conftest.py index 60f02aba5..afb76cf25 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -231,7 +231,6 @@ def fast_dump_expected(): class DummyServer: - # Flag for useful debug output when writing tests # for diagnosing mismatching sent data. debug = False diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py index 1d49d3685..8d0067542 100644 --- a/tests/test_asyncio.py +++ b/tests/test_asyncio.py @@ -36,9 +36,11 @@ async def test_asyncio_bad_put_raises(dummy_server_async): async def test_asyncio_data( dummy_server_async, fast_dump, fast_dump_expected, disarmed, flush_period ): + print(disarmed) + print(flush_period) if not disarmed: # simulate getting the data without the END marker as if arm was not pressed - fast_dump = map(lambda x: x.split(b"END")[0], fast_dump) + fast_dump = (x.split(b"END")[0] for x in fast_dump) fast_dump_expected = list(fast_dump_expected)[:-1] dummy_server_async.data = fast_dump events = [] diff --git a/tests/test_utils.py b/tests/test_utils.py index f11e7218e..e9424b34c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -230,13 +230,13 @@ def table_data_1() -> List[str]: @pytest.fixture def table_2_np_arrays() -> Dict[str, UnpackedArray]: - table: Dict[str, UnpackedArray] = dict( - REPEATS=np.array([1, 0], dtype=np.uint32), - TRIGGER=["Immediate", "Immediate"], - POSITION=np.array([-20, 2**31 - 1], dtype=np.int32), - TIME1=np.array([12, 2**32 - 1], dtype=np.uint32), - TIME2=np.array([32, 1], dtype=np.uint32), - ) + table: Dict[str, UnpackedArray] = { + "REPEATS": np.array([1, 0], dtype=np.uint32), + "TRIGGER": ["Immediate", "Immediate"], + "POSITION": np.array([-20, 2**31 - 1], dtype=np.int32), + "TIME1": np.array([12, 2**32 - 1], dtype=np.uint32), + "TIME2": np.array([32, 1], dtype=np.uint32), + } table["OUTA1"] = np.array([0, 1], dtype=np.uint8) table["OUTA2"] = np.array([1, 0], dtype=np.uint8) From 7339b85ee695fe7ae84aeeeabe29d79e0e26c480 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Wed, 18 Oct 2023 09:30:32 +0100 Subject: [PATCH 71/76] restored old __main__ --- src/pandablocks/__main__.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/pandablocks/__main__.py b/src/pandablocks/__main__.py index 365999d52..4672f7385 100644 --- a/src/pandablocks/__main__.py +++ b/src/pandablocks/__main__.py @@ -1,16 +1,6 @@ -from argparse import ArgumentParser +from pandablocks.cli import cli -from . import __version__ - -__all__ = ["main"] - - -def main(args=None): - parser = ArgumentParser() - parser.add_argument("-v", "--version", action="version", version=__version__) - args = parser.parse_args(args) - - -# test with: python -m pandablocks +# test with: +# pipenv run python -m pandablocks if __name__ == "__main__": - main() + cli() From 77a87f34dfc1cf128f08d715400466e679d813c0 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Wed, 18 Oct 2023 11:50:11 +0100 Subject: [PATCH 72/76] Restructured docs --- .github/CONTRIBUTING.rst | 35 ------- docs/CONTRIBUTING.rst | 10 +- docs/conf.py | 2 + docs/developer/how-to/contribute.rst | 2 +- docs/reference/api.rst | 92 ------------------ docs/tutorials/installation.rst | 47 --------- docs/{ => user}/explanations/performance.rst | 0 docs/{ => user}/explanations/sans-io.rst | 2 +- docs/{ => user}/how-to/introspect-panda.rst | 4 +- docs/{ => user}/how-to/library-hdf.rst | 4 +- docs/{ => user}/how-to/poll-changes.rst | 0 docs/user/index.rst | 10 ++ docs/user/reference/api.rst | 92 ++++++++++++++++-- docs/{ => user}/reference/appendix.rst | 0 docs/{ => user}/reference/changelog.rst | 0 docs/{ => user}/reference/contributing.rst | 0 docs/{ => user}/tutorials/commandline-hdf.rst | 2 +- docs/{ => user}/tutorials/control.rst | 0 docs/user/tutorials/installation.rst | 12 ++- docs/{ => user}/tutorials/load-save.rst | 2 +- docs/{ => user}/tutorials/tutorial_layout.png | Bin .../examples => examples}/README.rst | 0 .../examples => examples}/arm_and_hdf.py | 0 .../hdf_queue_reporting.py | 0 .../examples => examples}/introspect_panda.py | 0 .../examples => examples}/plot_counter_hdf.py | 0 26 files changed, 118 insertions(+), 198 deletions(-) delete mode 100644 .github/CONTRIBUTING.rst delete mode 100644 docs/reference/api.rst delete mode 100644 docs/tutorials/installation.rst rename docs/{ => user}/explanations/performance.rst (100%) rename docs/{ => user}/explanations/sans-io.rst (96%) rename docs/{ => user}/how-to/introspect-panda.rst (88%) rename docs/{ => user}/how-to/library-hdf.rst (94%) rename docs/{ => user}/how-to/poll-changes.rst (100%) rename docs/{ => user}/reference/appendix.rst (100%) rename docs/{ => user}/reference/changelog.rst (100%) rename docs/{ => user}/reference/contributing.rst (100%) rename docs/{ => user}/tutorials/commandline-hdf.rst (98%) rename docs/{ => user}/tutorials/control.rst (100%) rename docs/{ => user}/tutorials/load-save.rst (96%) rename docs/{ => user}/tutorials/tutorial_layout.png (100%) rename {src/pandablocks/examples => examples}/README.rst (100%) rename {src/pandablocks/examples => examples}/arm_and_hdf.py (100%) rename {src/pandablocks/examples => examples}/hdf_queue_reporting.py (100%) rename {src/pandablocks/examples => examples}/introspect_panda.py (100%) rename {src/pandablocks/examples => examples}/plot_counter_hdf.py (100%) diff --git a/.github/CONTRIBUTING.rst b/.github/CONTRIBUTING.rst deleted file mode 100644 index d0e619ece..000000000 --- a/.github/CONTRIBUTING.rst +++ /dev/null @@ -1,35 +0,0 @@ -Contributing to the project -=========================== - -Contributions and issues are most welcome! All issues and pull requests are -handled through GitHub_. Also, please check for any existing issues before -filing a new one. If you have a great idea but it involves big changes, please -file a ticket before making a pull request! We want to make sure you don't spend -your time coding something that might not fit the scope of the project. - -.. _GitHub: https://github.com/PandABlocks/pandablocks/issues - -Issue or Discussion? --------------------- - -Github also offers discussions_ as a place to ask questions and share ideas. If -your issue is open ended and it is not obvious when it can be "closed", please -raise it as a discussion instead. - -.. _discussions: https://github.com/PandABlocks/pandablocks/discussions - -Code coverage -------------- - -While 100% code coverage does not make a library bug-free, it significantly -reduces the number of easily caught bugs! Please make sure coverage remains the -same or is improved by a pull request! - -Developer guide ---------------- - -The `Developer Guide`_ contains information on setting up a development -environment, running the tests and what standards the code and documentation -should follow. - -.. _Developer Guide: https://diamondlightsource.github.io/pandablocks/main/developer/how-to/contribute.html diff --git a/docs/CONTRIBUTING.rst b/docs/CONTRIBUTING.rst index 309706435..b426da9a3 100644 --- a/docs/CONTRIBUTING.rst +++ b/docs/CONTRIBUTING.rst @@ -17,8 +17,9 @@ To get the source code and run the unit tests, run:: $ git clone git@github.com:PandABlocks/PandABlocks-client.git $ cd PandABlocks-client - $ pipenv install --dev - $ pipenv run tests + $ python3 -m venv /path/to/venv + $ source /path/to/venv/bin/activate + $ pytest While 100% code coverage does not make a library bug-free, it significantly reduces the number of easily caught bugs! Please make sure coverage remains the @@ -37,9 +38,8 @@ The code in this repository conforms to standards set by the following tools: .. _black: https://github.com/psf/black .. _flake8: http://flake8.pycqa.org/en/latest/ .. _isort: https://github.com/timothycrosley/isort -.. _mypy: https://github.com/python/mypy -These tests will be run on code when running ``pipenv run tests`` and also +These tests will be run on code when running ``pytest`` and also automatically at check in. Please read the tool documentation for details on how to fix the errors it reports. @@ -63,7 +63,7 @@ Docs follow the underlining convention:: You can build the docs from the project directory by running:: - $ pipenv run docs + $ tox -e docs $ firefox build/html/index.html Release Checklist diff --git a/docs/conf.py b/docs/conf.py index c44614a86..4be94a8bd 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -119,6 +119,8 @@ .. _ruff: https://beta.ruff.rs/docs/ .. _mypy: http://mypy-lang.org/ .. _pre-commit: https://pre-commit.com/ +.. _numpy: https://numpy.org/ +.. _h5py: https://www.h5py.org/ """ # Ignore localhost links for periodic check that links in docs are valid diff --git a/docs/developer/how-to/contribute.rst b/docs/developer/how-to/contribute.rst index 65b992f08..ac7b6bcf3 100644 --- a/docs/developer/how-to/contribute.rst +++ b/docs/developer/how-to/contribute.rst @@ -1 +1 @@ -.. include:: ../../../.github/CONTRIBUTING.rst +.. include:: ../../CONTRIBUTING.rst diff --git a/docs/reference/api.rst b/docs/reference/api.rst deleted file mode 100644 index b9071f801..000000000 --- a/docs/reference/api.rst +++ /dev/null @@ -1,92 +0,0 @@ -.. _API: - -API -=== - -The top level pandablocks module contains a number of packages that can be used -from code: - -- `pandablocks.commands`: The control commands that can be sent to a PandA -- `pandablocks.responses`: The control and data responses that will be received -- `pandablocks.connections`: Control and data connections that implements the parsing logic -- `pandablocks.asyncio`: An asyncio client that uses the control and data connections -- `pandablocks.blocking`: A blocking client that uses the control and data connections -- `pandablocks.hdf`: Some helpers for efficiently writing data responses to disk -- `pandablocks.utils`: General utility methods for use with pandablocks - - -.. automodule:: pandablocks.commands - :members: - - Commands - -------- - - There is a `Command` subclass for every sort of command that can be sent to - the `ControlConnection` of a PandA. Many common actions can be accomplished - with a simple `Get` or `Put`, but some convenience commands like - `GetBlockInfo`, `GetFieldInfo`, etc. are provided that parse output into - specific classes. - - -.. automodule:: pandablocks.responses - :members: - - Responses - --------- - - Classes used in responses from both the `ControlConnection` and - `DataConnection` of a PandA live in this package. - -.. automodule:: pandablocks.connections - :members: - - Connections - ----------- - - `Sans-IO ` connections for both the Control and Data ports - of PandA TCP server. - -.. automodule:: pandablocks.asyncio - :members: - - Asyncio Client - -------------- - - This is an `asyncio` wrapper to the `ControlConnection` and `DataConnection` - objects, allowing async calls to ``send(command)`` and iterate over - ``data()``. - -.. automodule:: pandablocks.blocking - :members: - - Blocking Client - --------------- - - This is a blocking wrapper to the `ControlConnection` and `DataConnection` - objects, allowing blocking calls to ``send(commands)`` and iterate over - ``data()``. - -.. automodule:: pandablocks.hdf - :members: - - HDF Writing - ----------- - - This package contains components needed to write PCAP data to and HDF file - in the most efficient way. The oneshot `write_hdf_files` is exposed in the - commandline interface. It assembles a short `Pipeline` of: - - `AsyncioClient` -> `FrameProcessor` -> `HDFWriter` - - The FrameProcessor and HDFWriter run in their own threads as most of the - heavy lifting is done by numpy_ and h5py_, so running in their own threads - gives multi-CPU benefits without hitting the limit of the GIL. - - .. seealso:: `library-hdf`, `performance` - -.. automodule:: pandablocks.utils - - Utilities - --------- - - This package contains general methods for working with pandablocks. diff --git a/docs/tutorials/installation.rst b/docs/tutorials/installation.rst deleted file mode 100644 index 5038e2f7c..000000000 --- a/docs/tutorials/installation.rst +++ /dev/null @@ -1,47 +0,0 @@ -Installation Tutorial -===================== - -.. note:: - - For installation inside DLS, please see the internal documentation on - ``dls-python3`` and ``pipenv``. Although these instructions will work - inside DLS, they are intended for external use. - -Check your version of python ----------------------------- - -You will need python 3.7 or later. You can check your version of python by -typing into a terminal:: - - python3 --version - -Create a virtual environment ----------------------------- - -It is recommended that you install into a “virtual environment” so this -installation will not interfere with any existing Python software:: - - python3 -m venv /path/to/venv - source /path/to/venv/bin/activate - - -Installing the library ----------------------- - -You can now use ``pip`` to install the library:: - - python3 -m pip install pandablocks - -If you need to write HDF files you should install the ``hdf5`` extra:: - - python3 -m pip install pandablocks[hdf5] - -If you require a feature that is not currently released you can also install -from github:: - - python3 -m pip install git+git://github.com/PandABlocks/PandABlocks-client.git - -The library should now be installed and the commandline interface on your path. -You can check the version that has been installed by typing:: - - pandablocks --version diff --git a/docs/explanations/performance.rst b/docs/user/explanations/performance.rst similarity index 100% rename from docs/explanations/performance.rst rename to docs/user/explanations/performance.rst diff --git a/docs/explanations/sans-io.rst b/docs/user/explanations/sans-io.rst similarity index 96% rename from docs/explanations/sans-io.rst rename to docs/user/explanations/sans-io.rst index 246c84449..e8f759686 100644 --- a/docs/explanations/sans-io.rst +++ b/docs/user/explanations/sans-io.rst @@ -48,7 +48,7 @@ Wrappers -------- Of course, these Connections are useless without connecting some I/O. To aid with -this, wrappers are included for use in `asyncio ` and blocking programs. They expose +this, wrappers are included for use in `asyncio ` and blocking programs. They expose slightly different APIs to make best use of the features of their respective concurrency frameworks. For example, to send multiple commands in fields with the `blocking` wrapper:: diff --git a/docs/how-to/introspect-panda.rst b/docs/user/how-to/introspect-panda.rst similarity index 88% rename from docs/how-to/introspect-panda.rst rename to docs/user/how-to/introspect-panda.rst index 44d65c19d..2bd129147 100644 --- a/docs/how-to/introspect-panda.rst +++ b/docs/user/how-to/introspect-panda.rst @@ -7,9 +7,9 @@ to list all blocks, and all fields inside each block, that exist. Call the following script, with the address of the PandA as the first and only command line argument: -.. literalinclude:: ../../examples/introspect_panda.py +.. literalinclude:: ../../../examples/introspect_panda.py -This script can be found in ``docs/examples/introspect_panda.py``. +This script can be found in ``examples/introspect_panda.py``. By examining the `BlockInfo` structure returned from `GetBlockInfo` for each Block the number and description may be acquired for every block. diff --git a/docs/how-to/library-hdf.rst b/docs/user/how-to/library-hdf.rst similarity index 94% rename from docs/how-to/library-hdf.rst rename to docs/user/how-to/library-hdf.rst index 6201e112f..54ebd97a0 100644 --- a/docs/how-to/library-hdf.rst +++ b/docs/user/how-to/library-hdf.rst @@ -13,7 +13,7 @@ Approach 1: Call the function directly If you need a one-shot configure and run application, you can use the function directly: -.. literalinclude:: ../../examples/arm_and_hdf.py +.. literalinclude:: ../../../examples/arm_and_hdf.py With the `AsyncioClient` as a `Context Manager `, this code sets up some fields of a PandA before taking a single acquisition. The code in @@ -36,7 +36,7 @@ means you can make decisions about when to start and stop acquisitions based on the `Data` objects that go past. For example, if we want to make a progress bar we could: -.. literalinclude:: ../../examples/hdf_queue_reporting.py +.. literalinclude:: ../../../examples/hdf_queue_reporting.py This time, after setting up the PandA, we create the `AsyncioClient.data` iterator ourselves. Each `Data` object we get is queued on the first `Pipeline` diff --git a/docs/how-to/poll-changes.rst b/docs/user/how-to/poll-changes.rst similarity index 100% rename from docs/how-to/poll-changes.rst rename to docs/user/how-to/poll-changes.rst diff --git a/docs/user/index.rst b/docs/user/index.rst index 2c94a0c0b..c315ff2d1 100644 --- a/docs/user/index.rst +++ b/docs/user/index.rst @@ -14,6 +14,9 @@ side-bar. :maxdepth: 1 tutorials/installation + tutorials/commandline-hdf + tutorials/control + tutorials/load-save +++ @@ -26,6 +29,9 @@ side-bar. :maxdepth: 1 how-to/run-container + how-to/introspect-panda + how-to/library-hdf + how-to/poll-changes +++ @@ -38,6 +44,8 @@ side-bar. :maxdepth: 1 explanations/docs-structure + explanations/performance + explanations/sans-io +++ @@ -50,6 +58,8 @@ side-bar. :maxdepth: 1 reference/api + reference/changelog + reference/contributing ../genindex +++ diff --git a/docs/user/reference/api.rst b/docs/user/reference/api.rst index a432ecc97..b9071f801 100644 --- a/docs/user/reference/api.rst +++ b/docs/user/reference/api.rst @@ -1,14 +1,92 @@ +.. _API: + API === -.. automodule:: pandablocks +The top level pandablocks module contains a number of packages that can be used +from code: + +- `pandablocks.commands`: The control commands that can be sent to a PandA +- `pandablocks.responses`: The control and data responses that will be received +- `pandablocks.connections`: Control and data connections that implements the parsing logic +- `pandablocks.asyncio`: An asyncio client that uses the control and data connections +- `pandablocks.blocking`: A blocking client that uses the control and data connections +- `pandablocks.hdf`: Some helpers for efficiently writing data responses to disk +- `pandablocks.utils`: General utility methods for use with pandablocks + + +.. automodule:: pandablocks.commands + :members: + + Commands + -------- + + There is a `Command` subclass for every sort of command that can be sent to + the `ControlConnection` of a PandA. Many common actions can be accomplished + with a simple `Get` or `Put`, but some convenience commands like + `GetBlockInfo`, `GetFieldInfo`, etc. are provided that parse output into + specific classes. + + +.. automodule:: pandablocks.responses + :members: + + Responses + --------- + + Classes used in responses from both the `ControlConnection` and + `DataConnection` of a PandA live in this package. + +.. automodule:: pandablocks.connections + :members: + + Connections + ----------- + + `Sans-IO ` connections for both the Control and Data ports + of PandA TCP server. + +.. automodule:: pandablocks.asyncio + :members: + + Asyncio Client + -------------- + + This is an `asyncio` wrapper to the `ControlConnection` and `DataConnection` + objects, allowing async calls to ``send(command)`` and iterate over + ``data()``. + +.. automodule:: pandablocks.blocking + :members: + + Blocking Client + --------------- + + This is a blocking wrapper to the `ControlConnection` and `DataConnection` + objects, allowing blocking calls to ``send(commands)`` and iterate over + ``data()``. + +.. automodule:: pandablocks.hdf + :members: + + HDF Writing + ----------- + + This package contains components needed to write PCAP data to and HDF file + in the most efficient way. The oneshot `write_hdf_files` is exposed in the + commandline interface. It assembles a short `Pipeline` of: + + `AsyncioClient` -> `FrameProcessor` -> `HDFWriter` - ``pandablocks`` - ----------------------------------- + The FrameProcessor and HDFWriter run in their own threads as most of the + heavy lifting is done by numpy_ and h5py_, so running in their own threads + gives multi-CPU benefits without hitting the limit of the GIL. -This is the internal API reference for pandablocks + .. seealso:: `library-hdf`, `performance` -.. data:: pandablocks.__version__ - :type: str +.. automodule:: pandablocks.utils + + Utilities + --------- - Version number as calculated by https://github.com/pypa/setuptools_scm + This package contains general methods for working with pandablocks. diff --git a/docs/reference/appendix.rst b/docs/user/reference/appendix.rst similarity index 100% rename from docs/reference/appendix.rst rename to docs/user/reference/appendix.rst diff --git a/docs/reference/changelog.rst b/docs/user/reference/changelog.rst similarity index 100% rename from docs/reference/changelog.rst rename to docs/user/reference/changelog.rst diff --git a/docs/reference/contributing.rst b/docs/user/reference/contributing.rst similarity index 100% rename from docs/reference/contributing.rst rename to docs/user/reference/contributing.rst diff --git a/docs/tutorials/commandline-hdf.rst b/docs/user/tutorials/commandline-hdf.rst similarity index 98% rename from docs/tutorials/commandline-hdf.rst rename to docs/user/tutorials/commandline-hdf.rst index fc433d2f7..28b5f0cec 100644 --- a/docs/tutorials/commandline-hdf.rst +++ b/docs/user/tutorials/commandline-hdf.rst @@ -51,7 +51,7 @@ mode so that you can read partial acquisitions before they are complete. In the repository ``examples/plot_counter_hdf.py`` is an example of reading the file, listing the datasets, and plotting the counters: -.. literalinclude:: ../../examples/plot_counter_hdf.py +.. literalinclude:: ../../../examples/plot_counter_hdf.py Running it on ``/tmp/panda-capture-1.h5`` will show the three counter values: diff --git a/docs/tutorials/control.rst b/docs/user/tutorials/control.rst similarity index 100% rename from docs/tutorials/control.rst rename to docs/user/tutorials/control.rst diff --git a/docs/user/tutorials/installation.rst b/docs/user/tutorials/installation.rst index 4109cbe0e..9bfd7feae 100644 --- a/docs/user/tutorials/installation.rst +++ b/docs/user/tutorials/installation.rst @@ -23,16 +23,20 @@ installation will not interfere with any existing Python software:: Installing the library ---------------------- -You can now use ``pip`` to install the library and its dependencies:: +You can now use ``pip`` to install the library:: - $ python3 -m pip install pandablocks + python3 -m pip install pandablocks + +If you need to write HDF files you should install the ``hdf5`` extra:: + + python3 -m pip install pandablocks[hdf5] If you require a feature that is not currently released you can also install from github:: - $ python3 -m pip install git+https://github.com/PandABlocks/pandablocks.git + python3 -m pip install git+git://github.com/PandABlocks/PandABlocks-client.git The library should now be installed and the commandline interface on your path. You can check the version that has been installed by typing:: - $ pandablocks --version + pandablocks --version diff --git a/docs/tutorials/load-save.rst b/docs/user/tutorials/load-save.rst similarity index 96% rename from docs/tutorials/load-save.rst rename to docs/user/tutorials/load-save.rst index 20a972c7b..5134c40f6 100644 --- a/docs/tutorials/load-save.rst +++ b/docs/user/tutorials/load-save.rst @@ -22,7 +22,7 @@ fields. e.g. the first few lines of the tutorial save file look like this: -.. literalinclude:: ../../pandablocks/saves/tutorial.sav +.. literalinclude:: ../../../src/pandablocks/saves/tutorial.sav :lines: 1-12 Load diff --git a/docs/tutorials/tutorial_layout.png b/docs/user/tutorials/tutorial_layout.png similarity index 100% rename from docs/tutorials/tutorial_layout.png rename to docs/user/tutorials/tutorial_layout.png diff --git a/src/pandablocks/examples/README.rst b/examples/README.rst similarity index 100% rename from src/pandablocks/examples/README.rst rename to examples/README.rst diff --git a/src/pandablocks/examples/arm_and_hdf.py b/examples/arm_and_hdf.py similarity index 100% rename from src/pandablocks/examples/arm_and_hdf.py rename to examples/arm_and_hdf.py diff --git a/src/pandablocks/examples/hdf_queue_reporting.py b/examples/hdf_queue_reporting.py similarity index 100% rename from src/pandablocks/examples/hdf_queue_reporting.py rename to examples/hdf_queue_reporting.py diff --git a/src/pandablocks/examples/introspect_panda.py b/examples/introspect_panda.py similarity index 100% rename from src/pandablocks/examples/introspect_panda.py rename to examples/introspect_panda.py diff --git a/src/pandablocks/examples/plot_counter_hdf.py b/examples/plot_counter_hdf.py similarity index 100% rename from src/pandablocks/examples/plot_counter_hdf.py rename to examples/plot_counter_hdf.py From f0fc5d1320329b7f72cde7e821a661333dadfc73 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Wed, 18 Oct 2023 11:57:15 +0100 Subject: [PATCH 73/76] Deleted unnecessary files --- .gitattributes | 1 - .gitlab-ci.yml | 4 - .gitremotes | 1 - .../0002-switched-to-pip-skeleton.rst | 2 +- docs/developer/how-to/make-release.rst | 2 +- docs/developer/tutorials/dev-install.rst | 2 +- docs/user/how-to/run-container.rst | 4 +- pyproject.toml | 2 +- src/pandablocks/_version_git.py | 97 ------------------- 9 files changed, 6 insertions(+), 109 deletions(-) delete mode 100644 .gitattributes delete mode 100644 .gitlab-ci.yml delete mode 100644 .gitremotes delete mode 100644 src/pandablocks/_version_git.py diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 41a139337..000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*/_version_git.py export-subst diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 1efd50249..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,4 +0,0 @@ -include: - - project: 'controls/reports/ci_templates' - ref: master - file: 'python3/dls_py3_template.yml' diff --git a/.gitremotes b/.gitremotes deleted file mode 100644 index 1871dce5a..000000000 --- a/.gitremotes +++ /dev/null @@ -1 +0,0 @@ -github git@github.com:PandABlocks/PandABlocks-client.git diff --git a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst index d0e8452c1..dc1aef6c4 100644 --- a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst +++ b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst @@ -11,7 +11,7 @@ Accepted Context ------- -We should use the following `pip-skeleton `_. +We should use the following `pip-skeleton `_. The skeleton will ensure consistency in developer environments and package management. diff --git a/docs/developer/how-to/make-release.rst b/docs/developer/how-to/make-release.rst index 3a99eca5f..df24c3407 100644 --- a/docs/developer/how-to/make-release.rst +++ b/docs/developer/how-to/make-release.rst @@ -13,4 +13,4 @@ To make a new release, please follow this checklist: Note that tagging and pushing to the main branch has the same effect except that you will not get the option to edit the release notes. -.. _release: https://github.com/PandABlocks/pandablocks/releases +.. _release: https://github.com/PandABlocks/PandABlocks-client/releases diff --git a/docs/developer/tutorials/dev-install.rst b/docs/developer/tutorials/dev-install.rst index 3aa2cfb3e..49ecac74c 100644 --- a/docs/developer/tutorials/dev-install.rst +++ b/docs/developer/tutorials/dev-install.rst @@ -10,7 +10,7 @@ Clone the repository First clone the repository locally using `Git `_:: - $ git clone git://github.com/PandABlocks/pandablocks.git + $ git clone git://github.com/PandABlocks/PandABlocks-client.git Install dependencies -------------------- diff --git a/docs/user/how-to/run-container.rst b/docs/user/how-to/run-container.rst index 38adf765c..7285ef9b9 100644 --- a/docs/user/how-to/run-container.rst +++ b/docs/user/how-to/run-container.rst @@ -3,13 +3,13 @@ Run in a container Pre-built containers with pandablocks and its dependencies already installed are available on `Github Container Registry -`_. +`_. Starting the container ---------------------- To pull the container from github container registry and run:: - $ docker run ghcr.io/PandABlocks/pandablocks:main --version + $ docker run ghcr.io/PandABlocks/PandABlocks-client:main --version To get a released version, use a numbered release instead of ``main``. diff --git a/pyproject.toml b/pyproject.toml index c720497de..5224b2861 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,7 +67,7 @@ ignore_missing_imports = true # Ignore missing stubs in imported modules # Run pytest with all our checkers, and don't spam us with massive tracebacks on error addopts = """ --tb=native -vv --doctest-modules --doctest-glob="*.rst" - --cov=pandablocks --cov-report term --cov-report xml:cov.xml + --cov=src/pandablocks --cov-report term --cov-report xml:cov.xml """ asyncio_mode = "auto" # Doctest python code in docs, python code in src docstrings, test functions in tests diff --git a/src/pandablocks/_version_git.py b/src/pandablocks/_version_git.py deleted file mode 100644 index 986383ecd..000000000 --- a/src/pandablocks/_version_git.py +++ /dev/null @@ -1,97 +0,0 @@ -# Compute a version number from a git repo or archive - -# This file is released into the public domain. Generated by: -# versiongit-1.0 (https://github.com/dls-controls/versiongit) -import os -import re -import sys -from subprocess import STDOUT, CalledProcessError, check_output - -# These will be filled in if git archive is run or by setup.py cmdclasses -GIT_REFS = "$Format:%D$" -GIT_SHA1 = "$Format:%h$" - -# Git describe gives us sha1, last version-like tag, and commits since then -CMD = "git describe --tags --dirty --always --long --match=[0-9]*[-.][0-9]*" - - -def get_version_from_git(path=None): - """Try to parse version from git describe, fallback to git archive tags""" - tag, plus, suffix = "0.0", "untagged", "" - if not GIT_SHA1.startswith("$"): - # git archive or the cmdclasses below have filled in these strings - sha1 = GIT_SHA1 - for ref_name in GIT_REFS.split(", "): - if ref_name.startswith("tag: "): - # git from 1.8.3 onwards labels archive tags "tag: TAGNAME" - tag, plus = ref_name[5:], "0" - else: - if path is None: - # If no path to git repo, choose the directory this file is in - path = os.path.dirname(os.path.abspath(__file__)) - # output is TAG-NUM-gHEX[-dirty] or HEX[-dirty] - try: - cmd_out = check_output(CMD.split(), stderr=STDOUT, cwd=path) - except Exception as e: - sys.stderr.write("%s: %s\n" % (type(e).__name__, str(e))) - if isinstance(e, CalledProcessError): - sys.stderr.write("-> %s" % e.output.decode()) - return "0.0+unknown", None, e - else: - out = cmd_out.decode().strip() - if out.endswith("-dirty"): - out = out[:-6] - suffix = ".dirty" - if "-" in out: - # There is a tag, extract it and the other pieces - match = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", out) - tag, plus, sha1 = match.groups() - else: - # No tag, just sha1 - sha1 = out - # Replace dashes in tag for dots - tag = tag.replace("-", ".") - if plus != "0" or suffix: - # Not on a tag, add additional info - tag = "%(tag)s+%(plus)s.g%(sha1)s%(suffix)s" % locals() - return tag, sha1, None - - -__version__, git_sha1, git_error = get_version_from_git() - - -def get_cmdclass(build_py=None, sdist=None): - """Create cmdclass dict to pass to setuptools.setup that will write a - _version_static.py file in our resultant sdist, wheel or egg""" - if build_py is None: - from setuptools.command.build_py import build_py - if sdist is None: - from setuptools.command.sdist import sdist - - def make_version_static(base_dir, pkg): - vg = os.path.join(base_dir, pkg.split(".")[0], "_version_git.py") - if os.path.isfile(vg): - lines = open(vg).readlines() - with open(vg, "w") as f: - for line in lines: - # Replace GIT_* with static versions - if line.startswith("GIT_SHA1 = "): - f.write("GIT_SHA1 = '%s'\n" % git_sha1) - elif line.startswith("GIT_REFS = "): - f.write("GIT_REFS = 'tag: %s'\n" % __version__) - else: - f.write(line) - - class BuildPy(build_py): - def run(self): - build_py.run(self) - for pkg in self.packages: - make_version_static(self.build_lib, pkg) - - class Sdist(sdist): - def make_release_tree(self, base_dir, files): - sdist.make_release_tree(self, base_dir, files) - for pkg in self.distribution.packages: - make_version_static(base_dir, pkg) - - return {"build_py": BuildPy, "sdist": Sdist} From 7e74ba699dd7acb46d50c47ce06310087c6f2517 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Thu, 19 Oct 2023 10:27:55 +0100 Subject: [PATCH 74/76] Changed logo back to panda --- docs/conf.py | 4 ++-- docs/images/dls-favicon.ico | Bin 99678 -> 0 bytes docs/images/dls-logo.svg | 11 ----------- 3 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 docs/images/dls-favicon.ico delete mode 100644 docs/images/dls-logo.svg diff --git a/docs/conf.py b/docs/conf.py index 4be94a8bd..16afa5272 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -201,5 +201,5 @@ html_show_copyright = True # Logo -html_logo = "images/dls-logo.svg" -html_favicon = "images/dls-favicon.ico" +html_logo = "images/PandA-logo-for-black-background.svg" +html_favicon = "images/PandA-logo.ico" diff --git a/docs/images/dls-favicon.ico b/docs/images/dls-favicon.ico deleted file mode 100644 index 9a11f508ef8aed28f14c5ce0d8408e1ec8b614a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99678 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 ZYRRh@^bCDh5vs@!z69bV>$COq{{Z);QUw42 diff --git a/docs/images/dls-logo.svg b/docs/images/dls-logo.svg deleted file mode 100644 index 0af1a1770..000000000 --- a/docs/images/dls-logo.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file From 919324991b99afa9d25a9c6a232f167f3d3a6b24 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Thu, 19 Oct 2023 11:47:43 +0100 Subject: [PATCH 75/76] Cleaned up after conversion --- .../0001-record-architecture-decisions.rst | 2 +- .../0002-switched-to-pip-skeleton.rst | 4 ++-- .../decisions/0003-make-library-sans-io.rst | 24 +++++++++++++++++++ docs/user/tutorials/installation.rst | 2 +- pyproject.toml | 6 ++--- tests/test_asyncio.py | 2 -- 6 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 docs/developer/explanations/decisions/0003-make-library-sans-io.rst diff --git a/docs/developer/explanations/decisions/0001-record-architecture-decisions.rst b/docs/developer/explanations/decisions/0001-record-architecture-decisions.rst index b2d3d0fe8..ef0a21e75 100644 --- a/docs/developer/explanations/decisions/0001-record-architecture-decisions.rst +++ b/docs/developer/explanations/decisions/0001-record-architecture-decisions.rst @@ -1,7 +1,7 @@ 1. Record architecture decisions ================================ -Date: 2022-02-18 +Date: 2023-10-18 Status ------ diff --git a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst index dc1aef6c4..b139da73f 100644 --- a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst +++ b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst @@ -1,7 +1,7 @@ 2. Adopt pandablocks for project structure -=================================================== +========================================== -Date: 2022-02-18 +Date: 2023-10-18 Status ------ diff --git a/docs/developer/explanations/decisions/0003-make-library-sans-io.rst b/docs/developer/explanations/decisions/0003-make-library-sans-io.rst new file mode 100644 index 000000000..a1a634ff3 --- /dev/null +++ b/docs/developer/explanations/decisions/0003-make-library-sans-io.rst @@ -0,0 +1,24 @@ +3. Sans-IO pandABlocks-client +============================= + +Date: 2021-08-02 (ADR created retroactively) + +Status +------ + +Accepted + +Context +------- + +Ensure PandABlocks-client works sans-io. + +Decision +-------- + +We will ensure pandablocks works sans-io `sans-io `. + +Consequences +------------ + +We have the option to use an asyncio client or a blocking client. \ No newline at end of file diff --git a/docs/user/tutorials/installation.rst b/docs/user/tutorials/installation.rst index 9bfd7feae..41131e63b 100644 --- a/docs/user/tutorials/installation.rst +++ b/docs/user/tutorials/installation.rst @@ -4,7 +4,7 @@ Installation Check your version of python ---------------------------- -You will need python 3.8 or later. You can check your version of python by +You will need python 3.7 or later. You can check your version of python by typing into a terminal:: $ python3 --version diff --git a/pyproject.toml b/pyproject.toml index 5224b2861..7fd9d918a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" description = "A Python client to control and data ports of the PandABlocks TCP server" name = "pandablocks" classifiers = [ - "Development Status :: 3 - Alpha", + "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", @@ -24,9 +24,7 @@ requires-python = ">=3.7" h5py = ["h5py", "matplotlib"] dev = [ # A dev install will require [h5py] packages too - "h5py", - "matplotlib", - + "pandablocks[h5py]", "black", "mypy", "mock", diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py index 8d0067542..9e3902a8d 100644 --- a/tests/test_asyncio.py +++ b/tests/test_asyncio.py @@ -36,8 +36,6 @@ async def test_asyncio_bad_put_raises(dummy_server_async): async def test_asyncio_data( dummy_server_async, fast_dump, fast_dump_expected, disarmed, flush_period ): - print(disarmed) - print(flush_period) if not disarmed: # simulate getting the data without the END marker as if arm was not pressed fast_dump = (x.split(b"END")[0] for x in fast_dump) From ddb7b019972960cbf8c9cc398a79526db021e77b Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Fri, 20 Oct 2023 09:42:25 +0100 Subject: [PATCH 76/76] Trying to get coverage working on 3.7 --- .github/workflows/code.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index ae990294a..0725d39cc 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -32,12 +32,12 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest"] # can add windows-latest, macos-latest - python: ["3.8", "3.9", "3.10", "3.11"] + python: ["3.7", "3.8", "3.9", "3.10", "3.11"] install: ["-e .[dev]"] # Make one version be non-editable to test both paths of version code include: - os: "ubuntu-latest" - python: "3.7" + python: "3.10" install: ".[dev]" runs-on: ${{ matrix.os }}