From 9e4e50c4733b105bd2b0eee9544bcaac577042e8 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Thu, 23 Jan 2025 09:29:34 +0000 Subject: [PATCH] fixed merge conflicts --- .copier-answers.yml | 3 +- .devcontainer/devcontainer.json | 10 ++--- .github/CONTRIBUTING.md | 2 +- .github/ISSUE_TEMPLATE/bug_report.md | 21 +++++++++++ .github/ISSUE_TEMPLATE/issue.md | 13 +++++++ .../pull_request_template.md | 8 ++++ .github/pages/make_switcher.py | 6 ++- .github/workflows/_container.yml | 8 +++- .github/workflows/_docs.yml | 4 +- .github/workflows/_pypi.yml | 2 + .github/workflows/_release.yml | 2 +- .github/workflows/ci.yml | 1 + .gitignore | 1 + .pre-commit-config.yaml | 1 + .vscode/settings.json | 3 +- Dockerfile | 8 ++-- README.md | 2 +- catalog-info.yaml | 10 ----- docs/_api.rst | 16 ++++++++ docs/_templates/custom-module-template.rst | 37 +++++++++++++++++++ docs/conf.py | 31 ++++++++++------ docs/how-to/contribute.md | 2 +- docs/reference.md | 2 +- pyproject.toml | 29 +++++++++------ src/pandablocks/__init__.py | 8 ++++ 25 files changed, 176 insertions(+), 54 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/issue.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/pull_request_template.md delete mode 100644 catalog-info.yaml create mode 100644 docs/_api.rst create mode 100644 docs/_templates/custom-module-template.rst diff --git a/.copier-answers.yml b/.copier-answers.yml index 107af3b94..09945dcbe 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,9 +1,8 @@ # Changes here will be overwritten by Copier -_commit: 2.0.1 +_commit: 2.6.0 _src_path: gh:DiamondLightSource/python-copier-template author_email: tom.cobb@diamond.ac.uk author_name: Tom Cobb -component_owner: group:default/sscc description: A Python client to control and data ports of the PandABlocks TCP server distribution_name: pandablocks docker: true diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 79b85ff41..979a89ce3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -28,11 +28,11 @@ } }, "features": { - // Some default things like git config - "ghcr.io/devcontainers/features/common-utils:2": { - "upgradePackages": false - } + // add in eternal history and other bash features + "ghcr.io/diamondlightsource/devcontainer-features/bash-config:1.0.0": {} }, + // Create the config folder for the bash-config feature + "initializeCommand": "mkdir -p ${localEnv:HOME}/.config/bash-config", "runArgs": [ // Allow the container to access the host X11 display and EPICS CA "--net=host", @@ -43,4 +43,4 @@ "workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind", // After the container is created, install the python project in editable form "postCreateCommand": "pip install $([ -f dev-requirements.txt ] && echo '-c dev-requirements.txt') -e '.[dev]' && pre-commit install" -} \ No newline at end of file +} diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 2ec8dfe69..5d853d1b6 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -24,4 +24,4 @@ It is recommended that developers use a [vscode devcontainer](https://code.visua This project was created using the [Diamond Light Source Copier Template](https://github.com/DiamondLightSource/python-copier-template) for Python projects. -For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/2.0.1/how-to.html). +For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/2.6.0/how-to.html). diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..aa65892f3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,21 @@ +--- +name: Bug Report +about: The template to use for reporting bugs and usability issues +title: " " +labels: 'bug' +assignees: '' + +--- + +Describe the bug, including a clear and concise description of the expected behavior, the actual behavior and the context in which you encountered it (ideally include details of your environment). + +## Steps To Reproduce +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + + +## Acceptance Criteria +- Specific criteria that will be used to judge if the issue is fixed diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md new file mode 100644 index 000000000..52c84dd85 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue.md @@ -0,0 +1,13 @@ +--- +name: Issue +about: The standard template to use for feature requests, design discussions and tasks +title: " " +labels: '' +assignees: '' + +--- + +A brief description of the issue, including specific stakeholders and the business case where appropriate + +## Acceptance Criteria +- Specific criteria that will be used to judge if the issue is fixed diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 000000000..8200afe5c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,8 @@ +Fixes #ISSUE + +### Instructions to reviewer on how to test: +1. Do thing x +2. Confirm thing y happens + +### Checks for reviewer +- [ ] Would the PR title make sense to a user on a set of release notes diff --git a/.github/pages/make_switcher.py b/.github/pages/make_switcher.py index 2b81e7696..65c92adf1 100755 --- a/.github/pages/make_switcher.py +++ b/.github/pages/make_switcher.py @@ -1,3 +1,5 @@ +"""Make switcher.json to allow docs to switch between different versions.""" + import json import logging from argparse import ArgumentParser @@ -53,7 +55,8 @@ def get_versions(ref: str, add: Optional[str]) -> list[str]: return versions -def write_json(path: Path, repository: str, versions: str): +def write_json(path: Path, repository: str, versions: list[str]): + """Write the JSON switcher to path.""" org, repo_name = repository.split("/") struct = [ {"version": version, "url": f"https://{org}.github.io/{repo_name}/{version}/"} @@ -65,6 +68,7 @@ def write_json(path: Path, repository: str, versions: str): def main(args=None): + """Parse args and write switcher.""" parser = ArgumentParser( description="Make a versions.json file from gh-pages directories" ) diff --git a/.github/workflows/_container.yml b/.github/workflows/_container.yml index 4857ee9e6..da5e4936f 100644 --- a/.github/workflows/_container.yml +++ b/.github/workflows/_container.yml @@ -25,7 +25,9 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build and export to Docker local cache - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 + env: + DOCKER_BUILD_RECORD_UPLOAD: false with: context: . # Need load and tags so we can test it below @@ -46,7 +48,9 @@ jobs: - name: Push cached image to container registry if: github.ref_type == 'tag' - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 + env: + DOCKER_BUILD_RECORD_UPLOAD: false # This does not build the image again, it will find the image in the # Docker cache and publish it with: diff --git a/.github/workflows/_docs.yml b/.github/workflows/_docs.yml index 40446e332..a1cafcaed 100644 --- a/.github/workflows/_docs.yml +++ b/.github/workflows/_docs.yml @@ -47,8 +47,8 @@ jobs: if: github.ref_type == 'tag' || github.ref_name == 'main' # 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@373f7f263a76c20808c831209c920827a82a2847 # v3.9.3 + uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: .github/pages - keep_files: true \ No newline at end of file + keep_files: true diff --git a/.github/workflows/_pypi.yml b/.github/workflows/_pypi.yml index 0c5258dbe..8032bbaac 100644 --- a/.github/workflows/_pypi.yml +++ b/.github/workflows/_pypi.yml @@ -15,3 +15,5 @@ jobs: - name: Publish to PyPI using trusted publishing uses: pypa/gh-action-pypi-publish@release/v1 + with: + attestations: false diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml index b49fa7dca..81b626438 100644 --- a/.github/workflows/_release.yml +++ b/.github/workflows/_release.yml @@ -23,7 +23,7 @@ jobs: - name: Create 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@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15 + uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9 with: prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }} files: "*" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27769757f..477362db1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,6 +39,7 @@ jobs: if: needs.check.outputs.branch-pr == '' uses: ./.github/workflows/_container.yml permissions: + contents: read packages: write docs: diff --git a/.gitignore b/.gitignore index 2593ec752..0f33bf297 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ cov.xml # Sphinx documentation docs/_build/ +docs/_api # PyBuilder target/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5a4cbf7b4..60fc23f9a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,6 +5,7 @@ repos: - id: check-added-large-files - id: check-yaml - id: check-merge-conflict + - id: end-of-file-fixer - repo: local hooks: diff --git a/.vscode/settings.json b/.vscode/settings.json index c129d991b..101c75fa7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,7 +5,8 @@ "editor.codeActionsOnSave": { "source.organizeImports": "explicit" }, + "files.insertFinalNewline": true, "[python]": { "editor.defaultFormatter": "charliermarsh.ruff", }, -} \ No newline at end of file +} diff --git a/Dockerfile b/Dockerfile index bd0faa784..60c45c52a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # The devcontainer should use the developer target and run as root with podman # or docker with user namespaces. ARG PYTHON_VERSION=3.11 -FROM python:${PYTHON_VERSION} as developer +FROM python:${PYTHON_VERSION} AS developer # Add any system dependencies for the developer/build environment here RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -13,13 +13,13 @@ RUN python -m venv /venv ENV PATH=/venv/bin:$PATH # The build stage installs the context into the venv -FROM developer as build +FROM developer AS build COPY . /context WORKDIR /context -RUN pip install . +RUN touch dev-requirements.txt && pip install -c dev-requirements.txt . # The runtime stage copies the built venv into a slim runtime container -FROM python:${PYTHON_VERSION}-slim as runtime +FROM python:${PYTHON_VERSION}-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 diff --git a/README.md b/README.md index 8ee45994f..dea0c98fe 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![CI](https://github.com/PandABlocks/PandABlocks-client/actions/workflows/ci.yml/badge.svg)](https://github.com/PandABlocks/PandABlocks-client/actions/workflows/ci.yml) [![Coverage](https://codecov.io/gh/PandABlocks/PandABlocks-client/branch/main/graph/badge.svg)](https://codecov.io/gh/PandABlocks/PandABlocks-client) [![PyPI](https://img.shields.io/pypi/v/pandablocks.svg)](https://pypi.org/project/pandablocks) -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) # pandablocks diff --git a/catalog-info.yaml b/catalog-info.yaml deleted file mode 100644 index 56087e66e..000000000 --- a/catalog-info.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: pandablocks - title: PandABlocks-client - description: A Python client to control and data ports of the PandABlocks TCP server -spec: - type: documentation - lifecycle: experimental - owner: group:default/sscc diff --git a/docs/_api.rst b/docs/_api.rst new file mode 100644 index 000000000..dcf290e66 --- /dev/null +++ b/docs/_api.rst @@ -0,0 +1,16 @@ +:orphan: + +.. + This page is not included in the TOC tree, but must exist so that the + autosummary pages are generated for pandablocks and all its + subpackages + +API +=== + +.. autosummary:: + :toctree: _api + :template: custom-module-template.rst + :recursive: + + pandablocks diff --git a/docs/_templates/custom-module-template.rst b/docs/_templates/custom-module-template.rst new file mode 100644 index 000000000..9aeca5401 --- /dev/null +++ b/docs/_templates/custom-module-template.rst @@ -0,0 +1,37 @@ +{{ ('``' + fullname + '``') | underline }} + +{%- set filtered_members = [] %} +{%- for item in members %} + {%- if item in functions + classes + exceptions + attributes %} + {% set _ = filtered_members.append(item) %} + {%- endif %} +{%- endfor %} + +.. automodule:: {{ fullname }} + :members: + + {% block modules %} + {% if modules %} + .. rubric:: Submodules + + .. autosummary:: + :toctree: + :template: custom-module-template.rst + :recursive: + {% for item in modules %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block members %} + {% if filtered_members %} + .. rubric:: Members + + .. autosummary:: + :nosignatures: + {% for item in filtered_members %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docs/conf.py b/docs/conf.py index 5f555b79e..7eb29fc79 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,8 +1,9 @@ -# 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 +"""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 sys from pathlib import Path @@ -34,6 +35,8 @@ extensions = [ # Use this for generating API docs "sphinx.ext.autodoc", + # and making summary tables at the top of API docs + "sphinx.ext.autosummary", # This can parse google style docstrings "sphinx.ext.napoleon", # For linking to external sphinx documentation @@ -86,6 +89,12 @@ # Don't inherit docstrings from baseclasses autodoc_inherit_docstrings = False +# Document only what is in __all__ +autosummary_ignore_module_all = False + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + # Output graphviz directive produced images in a scalable format graphviz_output_format = "svg" @@ -156,12 +165,12 @@ # 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, +# 2. Existing project with latest copier template, switcher exists and works +# 3. Existing project with old copier template 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. +# Point 3 makes checking switcher difficult, because the updated copier template +# 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 = { "logo": { "text": project, @@ -187,7 +196,7 @@ # A dictionary of values to pass into the template engine’s context for all pages html_context = { "github_user": github_user, - "github_repo": project, + "github_repo": github_repo, "github_version": version, "doc_path": "docs", } diff --git a/docs/how-to/contribute.md b/docs/how-to/contribute.md index f9c4ca1d7..6e4197970 100644 --- a/docs/how-to/contribute.md +++ b/docs/how-to/contribute.md @@ -1,2 +1,2 @@ ```{include} ../../.github/CONTRIBUTING.md -``` \ No newline at end of file +``` diff --git a/docs/reference.md b/docs/reference.md index ac4016691..3a0e8a67c 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -6,7 +6,7 @@ Technical reference material including APIs and release notes. :maxdepth: 1 :glob: -reference/* +API <_api/pandablocks> genindex Release Notes ``` diff --git a/pyproject.toml b/pyproject.toml index 69bc0d963..7069b29e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=64", "setuptools_scm[toml]>=6.2"] +requires = ["setuptools>=64", "setuptools_scm[toml]>=8"] build-backend = "setuptools.build_meta" [project] @@ -10,6 +10,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] description = "A Python client to control and data ports of the PandABlocks TCP server" dependencies = ["typing-extensions;python_version<'3.8'", "numpy", "click"] @@ -29,6 +30,7 @@ dev = [ "atomicwrites", "typed-ast", "copier", + "mypy", "myst-parser", "pipdeptree", "pre-commit", @@ -56,7 +58,7 @@ name = "Tom Cobb" [tool.setuptools_scm] -write_to = "src/pandablocks/_version.py" +version_file = "src/pandablocks/_version.py" [tool.mypy] ignore_missing_imports = true # Ignore missing stubs in imported modules @@ -95,8 +97,6 @@ allowlist_externals = sphinx-build sphinx-autobuild commands = - pytest: pytest --cov=src/pandablocks --cov-report term --cov-report xml:cov.xml {posargs} - mypy: mypy src tests {posargs} pre-commit: pre-commit run --all-files --show-diff-on-failure {posargs} type-checking: mypy src tests {posargs} tests: pytest --cov=pandablocks --cov-report term --cov-report xml:cov.xml {posargs} @@ -107,11 +107,18 @@ commands = src = ["src", "tests"] line-length = 88 lint.select = [ - "B", # flake8-bugbear - https://docs.astral.sh/ruff/rules/#flake8-bugbear-b - "C4", # flake8-comprehensions - https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4 - "E", # pycodestyle errors - https://docs.astral.sh/ruff/rules/#error-e - "F", # pyflakes rules - https://docs.astral.sh/ruff/rules/#pyflakes-f - "W", # pycodestyle warnings - https://docs.astral.sh/ruff/rules/#warning-w - "I", # isort - https://docs.astral.sh/ruff/rules/#isort-i - "UP", # pyupgrade - https://docs.astral.sh/ruff/rules/#pyupgrade-up + "B", # flake8-bugbear - https://docs.astral.sh/ruff/rules/#flake8-bugbear-b + "C4", # flake8-comprehensions - https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4 + "E", # pycodestyle errors - https://docs.astral.sh/ruff/rules/#error-e + "F", # pyflakes rules - https://docs.astral.sh/ruff/rules/#pyflakes-f + "W", # pycodestyle warnings - https://docs.astral.sh/ruff/rules/#warning-w + "I", # isort - https://docs.astral.sh/ruff/rules/#isort-i + "UP", # pyupgrade - https://docs.astral.sh/ruff/rules/#pyupgrade-up + "SLF", # self - https://docs.astral.sh/ruff/settings/#lintflake8-self ] + +[tool.ruff.lint.per-file-ignores] +# By default, private member access is allowed in tests +# See https://github.com/DiamondLightSource/python-copier-template/issues/154 +# Remove this line to forbid private member access in tests +"tests/**/*" = ["SLF001"] diff --git a/src/pandablocks/__init__.py b/src/pandablocks/__init__.py index 26d23badb..a2ffbf369 100644 --- a/src/pandablocks/__init__.py +++ b/src/pandablocks/__init__.py @@ -1,3 +1,11 @@ +"""Top level API. + +.. data:: __version__ + :type: str + + Version number as calculated by https://github.com/pypa/setuptools_scm +""" + from ._version import __version__ __all__ = ["__version__"]