diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 60fc23f9..51e5ee2c 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: v4.5.0 + rev: v5.0.0 hooks: - id: check-added-large-files - id: check-yaml diff --git a/Dockerfile b/Dockerfile index 95a5fb1f..62346f3a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,7 @@ ARG PYTHON_VERSION=3.12 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 \ - graphviz \ +RUN apt-get update && apt-get upgrade \ && rm -rf /var/lib/apt/lists/* RUN pip install poetry>=2.0.0 diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..802c57a9 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,231 @@ +"""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 os +import sys +from pathlib import Path +from subprocess import check_output + +import requests + +import phoebus_guibuilder + +# -- General configuration ------------------------------------------------ +sys.path.insert(0, os.path.abspath("../../src")) +# General information about the project. +project = "phoebus-guibuilder" +copyright = "2025, Diamond Light Source" + +# The full version, including alpha/beta/rc tags. +release = phoebus_guibuilder.__version__ + +# The short X.Y version. +if "+" in release: + # 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: + version = release + +extensions = [ + # for diagrams + "sphinxcontrib.mermaid", + # Used for BaseModel autodoc + "sphinxcontrib.autodoc_pydantic", + # Use this for generating API docs + "sphinx.ext.autodoc", + # Not sure if this is still used? + "sphinx.ext.doctest", + # 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 + "sphinx.ext.intersphinx", + # Add links to source code in API docs + "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", + "sphinx.ext.mathjax", + "sphinx.ext.githubpages", +] + +napoleon_google_docstring = False + +# 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 = [ + # builtins + ("py:class", "NoneType"), + ("py:class", "'str'"), + ("py:class", "'float'"), + ("py:class", "'int'"), + ("py:class", "'bool'"), + ("py:class", "'object'"), + ("py:class", "'id'"), + # typing + ("py:class", "typing_extensions.Literal"), +] + +# 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 + +# Add some more modules to the top level autosummary +phoebus_guibuilder.__all__ += [] + +# 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" + +# 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" + + +# Example configuration for intersphinx: refer to the Python standard library. +# This means you can link things like `str` and `asyncio` to the relevant +# docs in the python documentation. +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), +} + +# A dictionary of graphviz graph attributes for inheritance diagrams. +inheritance_graph_attrs = {"rankdir": "TB"} + +# Common links that should be available on every page +rst_epilog = """ +.. _NSLS: https://www.bnl.gov/nsls2 +.. _black: https://github.com/psf/black +.. _ruff: https://beta.ruff.rs/docs/ +.. _mypy: http://mypy-lang.org/ +.. _pre-commit: https://pre-commit.com/ +""" + +# 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 = "pydata_sphinx_theme" +github_repo = "phoebus-guibuilder" +github_user = "DiamondLightSource" +switcher_json = "https://diamondlightsource.github.io/phoebus-guibuilder/switcher.json" +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 " + "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 +# 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 = { + "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": { + "json_url": switcher_json, + "version_match": version, + }, + "check_switcher": False, + "navbar_end": ["theme-switcher", "icon-links", "version-switcher"], + "navigation_with_keys": False, +} + +# 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_version": version, + "doc_path": "docs", +} + +# 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 + +# Logo +# html_logo = "images/phoebus-guibuilder-logo.svg" +# html_favicon = "images/phoebus-guibuilder-favicon.svg" + +# If False and a module has the __all__ attribute set, autosummary documents +# every member listed in __all__ and no others. Default is True +autosummary_ignore_module_all = False + +# Turn on sphinx.ext.autosummary +autosummary_generate = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# Look for signatures in the first line of the docstring (used for C functions) +autodoc_docstring_signature = True + +# Don't show config summary as it's not relevant +autodoc_pydantic_model_show_config_summary = False + +# Show the fields in source order +autodoc_pydantic_model_summary_list_order = "bysource" diff --git a/guibuilder.py b/guibuilder.py deleted file mode 100644 index 75404249..00000000 --- a/guibuilder.py +++ /dev/null @@ -1,83 +0,0 @@ -import pprint -import re -from dataclasses import dataclass -from typing import Dict -from warnings import warn - -import yaml - -pp = pprint.PrettyPrinter() - - -@dataclass -class Beamline: - dom: str - desc: str - - -@dataclass -class Component: - name: str - desc: str - prefix: str - filename: str | None = None - - def __post_init__(self): - self._extract_p_and_r() - - def __repr__(self) -> str: - return f"Component(name={self.name}, desc={self.desc}, prefix={self.P}, suffix={self.R}, filename={self.filename})" - - def _extract_p_and_r(self): - pattern = re.compile( - r""" - ^ # start of string - (?= # lookahead to ensure the following pattern matches - [A-Za-z0-9-]{14,16} # match 14 to 16 alphanumeric characters or hyphens - [:A-Za-z0-9]* # match zero or more colons or alphanumeric characters - [.A-Za-z0-9] # match a dot or alphanumeric character - ) - (?!.*--) # negative lookahead to ensure no double hyphens - (?!.*:\..) # negative lookahead to ensure no colon followed by a dot - ( # start of capture group 1 - (?:[A-Za-z0-9]{2,5}-){3} # match 2 to 5 alphanumeric characters followed by a hyphen, repeated 3 times - [\d]* # match zero or more digits - [^:]? # match zero or one non-colon character - ) - (?::([a-zA-Z0-9:]*))? # match zero or one colon followed by zero or more alphanumeric characters or colons (capture group 2) - (?:\.([a-zA-Z0-9]+))? # match zero or one dot followed by one or more alphanumeric characters (capture group 3) - $ # end of string - """, - re.VERBOSE, - ) - - match = re.match(pattern, self.prefix) - if match: - self.P: str = match.group(1) - self.R: str = match.group(2) - # TODO: Is this needed? - self.attribute: str | None = match.group(3) - else: - warn(f"No valid PV prefix found for {self.name}.") - exit() - - -components: list[Component] = [] - -with open("create_gui.yaml", "r") as f: - conf = yaml.safe_load(f) - - bl: dict[str, str] = conf["beamline"] - comps: dict[str, dict[str, str]] = conf["components"] - - beamline = Beamline(**bl) - - for key, comp in comps.items(): - components.append(Component(key, **comp)) - -print("BEAMLINE:") -pp.pprint(beamline) - -print("") -print("COMPONENTS") -pp.pprint(components) diff --git a/poetry.lock b/poetry.lock index cf56dfbd..ff20ad02 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,25 @@ # This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +[[package]] +name = "accessible-pygments" +version = "0.0.5" +description = "A collection of accessible pygments styles" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"dev\"" +files = [ + {file = "accessible_pygments-0.0.5-py3-none-any.whl", hash = "sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7"}, + {file = "accessible_pygments-0.0.5.tar.gz", hash = "sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872"}, +] + +[package.dependencies] +pygments = ">=1.5" + +[package.extras] +dev = ["pillow", "pkginfo (>=1.10)", "playwright", "pre-commit", "setuptools", "twine (>=5.0)"] +tests = ["hypothesis", "pytest"] + [[package]] name = "alabaster" version = "0.7.16" @@ -82,6 +102,43 @@ files = [ [package.extras] dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"] +[[package]] +name = "beautifulsoup4" +version = "4.13.3" +description = "Screen-scraping library" +optional = true +python-versions = ">=3.7.0" +groups = ["main"] +markers = "extra == \"dev\"" +files = [ + {file = "beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16"}, + {file = "beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b"}, +] + +[package.dependencies] +soupsieve = ">1.2" +typing-extensions = ">=4.0.0" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "cachetools" +version = "5.5.1" +description = "Extensible memoizing collections and decorators" +optional = true +python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"dev\"" +files = [ + {file = "cachetools-5.5.1-py3-none-any.whl", hash = "sha256:b76651fdc3b24ead3c648bbdeeb940c1b04d365b38b4af66788f9ec4a81d42bb"}, + {file = "cachetools-5.5.1.tar.gz", hash = "sha256:70f238fbba50383ef62e55c6aff6d9673175fe59f7c6782c7a0b9e38f4a9df95"}, +] + [[package]] name = "certifi" version = "2025.1.31" @@ -108,6 +165,19 @@ files = [ {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, ] +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = true +python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"dev\"" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + [[package]] name = "charset-normalizer" version = "3.4.1" @@ -548,22 +618,6 @@ files = [ {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] -[[package]] -name = "pathlib2" -version = "2.3.7.post1" -description = "Object-oriented filesystem paths" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"dev\"" -files = [ - {file = "pathlib2-2.3.7.post1-py2.py3-none-any.whl", hash = "sha256:5266a0fd000452f1b3467d782f079a4343c63aaa119221fbdc4e39577489ca5b"}, - {file = "pathlib2-2.3.7.post1.tar.gz", hash = "sha256:9fe0edad898b83c0c3e199c842b27ed216645d2e177757b2dd67384d4113c641"}, -] - -[package.dependencies] -six = "*" - [[package]] name = "platformdirs" version = "4.3.6" @@ -768,6 +822,35 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +[[package]] +name = "pydata-sphinx-theme" +version = "0.16.1" +description = "Bootstrap-based Sphinx theme from the PyData community" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"dev\"" +files = [ + {file = "pydata_sphinx_theme-0.16.1-py3-none-any.whl", hash = "sha256:225331e8ac4b32682c18fcac5a57a6f717c4e632cea5dd0e247b55155faeccde"}, + {file = "pydata_sphinx_theme-0.16.1.tar.gz", hash = "sha256:a08b7f0b7f70387219dc659bff0893a7554d5eb39b59d3b8ef37b8401b7642d7"}, +] + +[package.dependencies] +accessible-pygments = "*" +Babel = "*" +beautifulsoup4 = "*" +docutils = "!=0.17.0" +pygments = ">=2.7" +sphinx = ">=6.1" +typing-extensions = "*" + +[package.extras] +a11y = ["pytest-playwright"] +dev = ["pandoc", "pre-commit", "pydata-sphinx-theme[doc,test]", "pyyaml", "sphinx-theme-builder[cli]", "tox"] +doc = ["ablog (>=0.11.8)", "colorama", "graphviz", "ipykernel", "ipyleaflet", "ipywidgets", "jupyter_sphinx", "jupyterlite-sphinx", "linkify-it-py", "matplotlib", "myst-parser", "nbsphinx", "numpy", "numpydoc", "pandas", "plotly", "rich", "sphinx-autoapi (>=3.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-favicon (>=1.0.1)", "sphinx-sitemap", "sphinx-togglebutton", "sphinxcontrib-youtube (>=1.4.1)", "sphinxext-rediraffe", "xarray"] +i18n = ["Babel", "jinja2"] +test = ["pytest", "pytest-cov", "pytest-regressions", "sphinx[test]"] + [[package]] name = "pygments" version = "2.19.1" @@ -784,6 +867,26 @@ files = [ [package.extras] windows-terminal = ["colorama (>=0.4.6)"] +[[package]] +name = "pyproject-api" +version = "1.9.0" +description = "API to interact with the python pyproject.toml based projects" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"dev\"" +files = [ + {file = "pyproject_api-1.9.0-py3-none-any.whl", hash = "sha256:326df9d68dea22d9d98b5243c46e3ca3161b07a1b9b18e213d1e24fd0e605766"}, + {file = "pyproject_api-1.9.0.tar.gz", hash = "sha256:7e8a9854b2dfb49454fae421cb86af43efbb2b2454e5646ffb7623540321ae6e"}, +] + +[package.dependencies] +packaging = ">=24.2" + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=3)"] +testing = ["covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "setuptools (>=75.8)"] + [[package]] name = "pyright" version = "1.1.393" @@ -1049,19 +1152,6 @@ files = [ {file = "ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7"}, ] -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = true -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -markers = "extra == \"dev\"" -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, -] - [[package]] name = "sniffio" version = "1.3.1" @@ -1088,6 +1178,19 @@ files = [ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] +[[package]] +name = "soupsieve" +version = "2.6" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"dev\"" +files = [ + {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, + {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, +] + [[package]] name = "sphinx" version = "7.3.7" @@ -1342,51 +1445,30 @@ full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart [[package]] name = "tox" -version = "3.28.0" +version = "4.24.1" description = "tox is a generic virtualenv management and test command line tool" optional = true -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -groups = ["main"] -markers = "extra == \"dev\"" -files = [ - {file = "tox-3.28.0-py2.py3-none-any.whl", hash = "sha256:57b5ab7e8bb3074edc3c0c0b4b192a4f3799d3723b2c5b76f1fa9f2d40316eea"}, - {file = "tox-3.28.0.tar.gz", hash = "sha256:d0d28f3fe6d6d7195c27f8b054c3e99d5451952b54abdae673b71609a581f640"}, -] - -[package.dependencies] -colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""} -filelock = ">=3.0.0" -packaging = ">=14" -pluggy = ">=0.12.0" -py = ">=1.4.17" -six = ">=1.14.0" -virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7" - -[package.extras] -docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] -testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psutil (>=5.6.1)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] - -[[package]] -name = "tox-direct" -version = "0.4" -description = "plugin for tox - run everything directly (tox creates no virtual env)" -optional = true -python-versions = "*" +python-versions = ">=3.8" groups = ["main"] markers = "extra == \"dev\"" files = [ - {file = "tox-direct-0.4.tar.gz", hash = "sha256:33bb6627db50c1c1760f889410bf77107e4858cf15a0f4532442fd690b6284c8"}, - {file = "tox_direct-0.4-py2.py3-none-any.whl", hash = "sha256:d80968dfbaf99198d7fa77fb2c20786f6bcf584000be96217a4ffd74dd4b3699"}, + {file = "tox-4.24.1-py3-none-any.whl", hash = "sha256:57ba7df7d199002c6df8c2db9e6484f3de6ca8f42013c083ea2d4d1e5c6bdc75"}, + {file = "tox-4.24.1.tar.gz", hash = "sha256:083a720adbc6166fff0b7d1df9d154f9d00bfccb9403b8abf6bc0ee435d6a62e"}, ] [package.dependencies] -pathlib2 = "*" -py = "*" -tox = ">=3.12,<4" +cachetools = ">=5.5" +chardet = ">=5.2" +colorama = ">=0.4.6" +filelock = ">=3.16.1" +packaging = ">=24.2" +platformdirs = ">=4.3.6" +pluggy = ">=1.5" +pyproject-api = ">=1.8" +virtualenv = ">=20.27.1" [package.extras] -publish = ["twine"] -test = ["pytest"] +test = ["devpi-process (>=1.0.2)", "pytest (>=8.3.3)", "pytest-mock (>=3.14)"] [[package]] name = "types-mock" @@ -1654,9 +1736,9 @@ files = [ ] [extras] -dev = ["autodoc-pydantic", "pre-commit", "pyright", "pytest", "pytest-asyncio", "pytest-cov", "pytest-faulthandler", "pytest-forked", "pytest-rerunfailures", "pytest-timeout", "ruff", "sphinx", "sphinx-autobuild", "sphinx-copybutton", "sphinx-design", "sphinxcontrib-mermaid", "tox-direct", "types-mock", "types-pyyaml"] +dev = ["autodoc-pydantic", "pre-commit", "pydata-sphinx-theme", "pyright", "pytest", "pytest-asyncio", "pytest-cov", "pytest-faulthandler", "pytest-forked", "pytest-rerunfailures", "pytest-timeout", "ruff", "sphinx", "sphinx-autobuild", "sphinx-copybutton", "sphinx-design", "sphinxcontrib-mermaid", "tox", "types-mock", "types-pyyaml"] [metadata] lock-version = "2.1" python-versions = ">=3.12" -content-hash = "8e91bdcebd947df92f6fd0152dff571092b45a81b866645fceb6c27c9dd183bf" +content-hash = "a57e70cf904fb4be42a7239643293468333808127aa743eee2a40464cd6fc535" diff --git a/pyproject.toml b/pyproject.toml index 35b19c47..4024b398 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "phoebus-guibuilder" -version = "0.1.0" +dynamic = ["version"] description = "A package for building GUIs" classifiers = [ "Development Status :: 3 - Alpha", @@ -18,6 +18,7 @@ requires-python = ">=3.12" dependencies = ["pyyaml (>=6.0.2)"] optional-dependencies = { dev = [ "pre-commit", + "pydata-sphinx-theme>=0.12", "pyright", "pytest", "pytest-asyncio", @@ -33,16 +34,42 @@ optional-dependencies = { dev = [ "sphinxcontrib-mermaid", "sphinx-copybutton", "sphinx-design", - "tox-direct", + "tox>=4.22", "types-mock", "types-pyyaml", ] } [build-system] -requires = ["poetry-core>=2.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"] +requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"] build-backend = "poetry_dynamic_versioning.backend" +[tool.poetry] +include = ["src/phoebus_guibuilder/_version.py"] +version = "0.1.0" + +[tool.poetry.requires-plugins] +poetry-dynamic-versioning = { version = ">=1.0.0,<2.0.0", extras = ["plugin"] } + +[tool.poetry-dynamic-versioning] +enable = true +vcs = "git" +latest-tag = true +bump = true +metadata = false +# allows for tags with the format 0.1.0a1 +pattern = "((?P\\d+(\\.\\d+)*)(?P[a-zA-Z]+)?(?P\\d+)?)" + +[tool.poetry-dynamic-versioning.files."src/phoebus_guibuilder/_version.py"] +persistent-substitution = true +initial-content = """ + # These version placeholders will be replaced later during substitution. + __version__ = "0.1.0" + __version_tuple__ = (0, 1, 0) +""" + +[tool.poetry-dynamic-versioning.substitution] +folders = [{ path = "src" }] # [tool.setuptools_scm] # version_file = "src/phoebus_guibuilder/_version.py" # overwrites base version @@ -79,29 +106,59 @@ data_file = "/tmp/phoebus_guibuilder.coverage" # 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,type-checking,tests,docs}] -# Don't create a virtualenv for the command, requires tox-direct plugin -direct = True -passenv = * -allowlist_externals = - pytest - pre-commit - pyright - sphinx-build - sphinx-autobuild -commands = - pre-commit: pre-commit run --all-files --show-diff-on-failure {posargs} - type-checking: pyright src {posargs} - tests: pytest --cov=phoebus_guibuilder --cov-report term --cov-report xml:cov.xml {posargs} - docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html -""" +skipsdist = true + +[tool.tox.env.pre-commit] +description = "Run pre-commit" +direct = true +allowlist_externals = ["pre-commit"] +commands = [ + [ + "pre-commit", + "run", + "--all-files", + "--show-diff-on-failure", + "{posargs}", + ], +] + +[tool.tox.env.type-checking] +description = "Run type-checking" +direct = true +allowlist_externals = ["pyright"] +commands = [["pyright", "src", "{posargs}"]] + +[tool.tox.env.tests] +description = "Run tests" +direct = true +allowlist_externals = ["pytest"] +commands = [ + [ + "pytest", + "--cov=phoebus_guibuilder", + "--cov-report", + "term", + "--cov-report", + "xml:cov.xml", + "{posargs}", + ], +] + +[tool.tox.env.docs] +description = "Run docs" +direct = true +allowlist_externals = ["sphinx-build", "sphinx-autobuild"] +commands = [ + [ + "sphinx-{posargs:build}", + "-EW", + "--keep-going", + "-T", + "docs", + "build/html", + ], +] [tool.ruff] src = ["src", "tests", "system_tests"] diff --git a/src/phoebus_guibuilder/__init__.py b/src/phoebus_guibuilder/__init__.py index a2ffbf36..8df6208a 100644 --- a/src/phoebus_guibuilder/__init__.py +++ b/src/phoebus_guibuilder/__init__.py @@ -3,7 +3,7 @@ .. data:: __version__ :type: str - Version number as calculated by https://github.com/pypa/setuptools_scm + Version number as calculated by poetry-dynamic-versioning """ from ._version import __version__ diff --git a/src/phoebus_guibuilder/guibuilder.py b/src/phoebus_guibuilder/guibuilder.py index 4e3b12cb..ad61613c 100644 --- a/src/phoebus_guibuilder/guibuilder.py +++ b/src/phoebus_guibuilder/guibuilder.py @@ -67,7 +67,7 @@ def _extract_p_and_r(self): components: list[Component] = [] -with open("create_gui.yaml") as f: +with open("example/create_gui.yaml") as f: conf = yaml.safe_load(f) bl: dict[str, str] = conf["beamline"]