From 5b77c53ebe619c03d91d00defcaa4a8d6e2224d6 Mon Sep 17 00:00:00 2001 From: Robert Niederreiter Date: Tue, 21 Oct 2025 13:32:59 +0200 Subject: [PATCH 01/12] Refactor package layout to modern Python packaging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Convert setup.py/setup.cfg to pyproject.toml - Implement PEP 420 implicit namespaces (remove namespace declarations) - Delete namespace-only __init__.py files - Add /build to .gitignore 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .gitignore | 1 + pyproject.toml | 53 ++++++++++++++++++++++++++++++++++++++++ setup.cfg | 2 -- setup.py | 58 -------------------------------------------- src/node/__init__.py | 1 - 5 files changed, 54 insertions(+), 61 deletions(-) create mode 100644 pyproject.toml delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 src/node/__init__.py diff --git a/.gitignore b/.gitignore index 85de168..155c3a3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /dist/ /htmlcov/ /requirements-mxdev.txt +/build diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..30b53be --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,53 @@ +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "node" +version = "1.2.3.dev0" +description = "Building data structures as node trees" +readme = "README.rst" +license = {text = "Simplified BSD"} +authors = [{name = "Node Contributors", email = "dev@conestack.org"}] +keywords = ["node", "tree", "fullmapping", "dict"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: BSD License", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Topic :: Software Development", + "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", +] +dependencies = [ + "odict>=1.9.0", + "plumber>=1.5", + "zope.component", + "zope.deferredimport", + "zope.deprecation", + "zope.lifecycleevent", +] + +[project.optional-dependencies] +test = [ + "pytest", +] + +[project.urls] +Homepage = "http://github.com/conestack/node" + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.setuptools] +zip-safe = true + +[tool.setuptools.package-dir] +"" = "src" + +[tool.zest-releaser] +create-wheel = true diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 81049c3..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[zest.releaser] -create-wheel = yes diff --git a/setup.py b/setup.py deleted file mode 100644 index 608c5ff..0000000 --- a/setup.py +++ /dev/null @@ -1,58 +0,0 @@ -from setuptools import find_packages -from setuptools import setup -import os - - -def read_file(name): - with open(os.path.join(os.path.dirname(__file__), name)) as f: - return f.read() - - -version = '1.2.3.dev0' -shortdesc = "Building data structures as node trees" -longdesc = '\n\n'.join([read_file(name) for name in [ - 'README.rst', - 'CHANGES.rst', - 'LICENSE.rst' -]]) - - -setup( - name='node', - version=version, - description=shortdesc, - long_description=longdesc, - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'License :: OSI Approved :: BSD License', - 'Intended Audience :: Developers', - 'Operating System :: OS Independent', - 'Topic :: Software Development', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10' - ], - keywords='node tree fullmapping dict', - author='Node Contributors', - author_email='dev@conestack.org', - url='http://github.com/conestack/node', - license='Simplified BSD', - packages=find_packages('src'), - package_dir={'': 'src'}, - namespace_packages=['node'], - include_package_data=True, - zip_safe=True, - install_requires=[ - 'odict>=1.9.0', - 'plumber>=1.5', - 'setuptools', - 'zope.component', - 'zope.deferredimport', - 'zope.deprecation', - 'zope.lifecycleevent' - ], - extras_require=dict(test=['pytest']), -) diff --git a/src/node/__init__.py b/src/node/__init__.py deleted file mode 100644 index 656dc0f..0000000 --- a/src/node/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover From d02a3dd6a63c4400609449a31157a34df278d410 Mon Sep 17 00:00:00 2001 From: Robert Niederreiter Date: Tue, 21 Oct 2025 15:12:00 +0200 Subject: [PATCH 02/12] Use hatchling instead of setuptools --- pyproject.toml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 30b53be..47ea9dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -requires = ["setuptools>=61.0"] -build-backend = "setuptools.build_meta" +requires = ["hatchling"] +build-backend = "hatchling.build" [project] name = "node" @@ -40,14 +40,5 @@ test = [ [project.urls] Homepage = "http://github.com/conestack/node" -[tool.setuptools.packages.find] -where = ["src"] - -[tool.setuptools] -zip-safe = true - -[tool.setuptools.package-dir] -"" = "src" - [tool.zest-releaser] create-wheel = true From 46d269ada3acae67126536ae2ee4b0e93736c431 Mon Sep 17 00:00:00 2001 From: Robert Niederreiter Date: Tue, 21 Oct 2025 15:49:43 +0200 Subject: [PATCH 03/12] add tool.hatch.build.targets.wheel sections --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 47ea9dd..ba4851f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,5 +40,8 @@ test = [ [project.urls] Homepage = "http://github.com/conestack/node" + +[tool.hatch.build.targets.wheel] +packages = ["src/node"] [tool.zest-releaser] create-wheel = true From 06157d862ba3bca398d50251267f9ab00f6c5f8d Mon Sep 17 00:00:00 2001 From: Robert Niederreiter Date: Wed, 22 Oct 2025 14:53:49 +0200 Subject: [PATCH 04/12] Remove MANIFEST.in and update to Python 3.10-3.14 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove obsolete MANIFEST.in file (now using hatchling) - Update Python classifiers to 3.10-3.14 - Update GitHub Actions workflows to test Python 3.10-3.14 - Remove PyPy from workflows 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/test.yml | 4 +--- MANIFEST.in | 4 ---- pyproject.toml | 10 +++++----- 3 files changed, 6 insertions(+), 12 deletions(-) delete mode 100644 MANIFEST.in diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 48ddf95..9ac4aa9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,13 +16,11 @@ jobs: - macos-latest python: - - "3.8" - - "3.9" - "3.10" - "3.11" - "3.12" - "3.13" - - "pypy3.9" + - "3.14" steps: - uses: actions/checkout@v4 diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 1fb1c79..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -graft src/node -include *.rst -global-exclude *.pyc -prune scripts diff --git a/pyproject.toml b/pyproject.toml index ba4851f..8eaec20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,10 +17,11 @@ classifiers = [ "Operating System :: OS Independent", "Topic :: Software Development", "Programming Language :: Python", - "Programming Language :: Python :: 2.7", - "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", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3.10", ] dependencies = [ @@ -40,7 +41,6 @@ test = [ [project.urls] Homepage = "http://github.com/conestack/node" - [tool.hatch.build.targets.wheel] packages = ["src/node"] [tool.zest-releaser] From 79032028ebb14c24ff24a207fe81116b9942d33f Mon Sep 17 00:00:00 2001 From: Robert Niederreiter Date: Wed, 22 Oct 2025 16:17:15 +0200 Subject: [PATCH 05/12] Add required tytest ini options to consider namespace packages --- pyproject.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8eaec20..0f7570f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,6 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", - "Programming Language :: Python :: 3.10", ] dependencies = [ "odict>=1.9.0", @@ -43,5 +42,11 @@ Homepage = "http://github.com/conestack/node" [tool.hatch.build.targets.wheel] packages = ["src/node"] + +[tool.pytest.ini_options] +consider_namespace_packages = true +addopts = ["--import-mode=importlib"] +pythonpath = "src" + [tool.zest-releaser] create-wheel = true From 24c7c2d1dfd4ccd2a28838fb9c968dcba7debee2 Mon Sep 17 00:00:00 2001 From: Robert Niederreiter Date: Fri, 24 Oct 2025 11:21:17 +0200 Subject: [PATCH 06/12] Update version --- CHANGES.rst | 5 ++++- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index d0bb9e1..b8c240a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,9 +2,12 @@ Changes ======= -1.2.3 (unreleased) +1.3.0 (unreleased) ------------------ +- Refactor package layout to use ``pyproject.toml`` and implecit namespace packages. + [rnix] + - Fix ``Node.treerepr`` if mapping raises an exception on ``__getitem__``. [rnix] diff --git a/pyproject.toml b/pyproject.toml index 0f7570f..d9b592e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "node" -version = "1.2.3.dev0" +version = "1.3.0.dev0" description = "Building data structures as node trees" readme = "README.rst" license = {text = "Simplified BSD"} From dd5987bcced371f9a527bb4e26b9e581e132aca5 Mon Sep 17 00:00:00 2001 From: Robert Niederreiter Date: Mon, 3 Nov 2025 11:34:44 +0100 Subject: [PATCH 07/12] Update package versions. --- CHANGES.rst | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index b8c240a..bae345d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,7 +2,7 @@ Changes ======= -1.3.0 (unreleased) +2.0.0 (unreleased) ------------------ - Refactor package layout to use ``pyproject.toml`` and implecit namespace packages. diff --git a/pyproject.toml b/pyproject.toml index d9b592e..8d0a67d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "node" -version = "1.3.0.dev0" +version = "2.0.0.dev0" description = "Building data structures as node trees" readme = "README.rst" license = {text = "Simplified BSD"} From b33fc55f9476a51cf25ec46bab81a845e62bc2e8 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Tue, 11 Nov 2025 10:51:20 +0100 Subject: [PATCH 08/12] add hatch-fancy-pypi-readme --- pyproject.toml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8d0a67d..8e0cad5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,13 @@ [build-system] -requires = ["hatchling"] +requires = ["hatchling", "hatch-fancy-pypi-readme"] build-backend = "hatchling.build" [project] name = "node" version = "2.0.0.dev0" description = "Building data structures as node trees" -readme = "README.rst" +dynamic = ["readme"] +requires-python = ">=3.10" license = {text = "Simplified BSD"} authors = [{name = "Node Contributors", email = "dev@conestack.org"}] keywords = ["node", "tree", "fullmapping", "dict"] @@ -40,6 +41,24 @@ test = [ [project.urls] Homepage = "http://github.com/conestack/node" +[tool.hatch.version] +source = "vcs" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.metadata.hooks.fancy-pypi-readme] +content-type = "text/x-rst" + +[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] +path = "README.rst" + +[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] +path = "CHANGES.rst" + +[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] +path = "LICENSE.rst" + [tool.hatch.build.targets.wheel] packages = ["src/node"] From 9e237c1228f9be10e808691bcc2860752a3c29c9 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Thu, 13 Nov 2025 10:09:24 +0100 Subject: [PATCH 09/12] checkout packages in mx.ini. remove obsolete lines in pyproject.toml --- .gitignore | 4 +- Makefile | 191 +++++++++++++++++++++++++++++++++++++++++-------- mx.ini | 56 +++++++++++++++ pyproject.toml | 6 -- 4 files changed, 222 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 155c3a3..786961b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,9 @@ /.mxmake /.ruff_cache /.venv +/build /dist/ /htmlcov/ /requirements-mxdev.txt -/build +/constraints-mxdev.txt +/sources/ diff --git a/Makefile b/Makefile index ea3a6cc..e5e08e9 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,12 @@ # THIS FILE IS GENERATED BY MXMAKE # # DOMAINS: +#: applications.zest-releaser #: core.base #: core.mxenv #: core.mxfiles #: core.packages +#: core.sources #: qa.coverage #: qa.test # @@ -37,30 +39,41 @@ INCLUDE_MAKEFILE?=include.mk # No default value. EXTRA_PATH?= +# Path to Python project relative to Makefile (repository root). +# Leave empty if Python project is in the same directory as Makefile. +# For monorepo setups, set to subdirectory name (e.g., `backend`). +# Future-proofed for multi-language monorepos (e.g., PROJECT_PATH_NODEJS). +# No default value. +PROJECT_PATH_PYTHON?= + ## core.mxenv # Primary Python interpreter to use. It is used to create the # virtual environment if `VENV_ENABLED` and `VENV_CREATE` are set to `true`. +# If global `uv` is used, this value is passed as `--python VALUE` to the venv creation. +# uv then downloads the Python interpreter if it is not available. +# for more on this feature read the [uv python documentation](https://docs.astral.sh/uv/concepts/python-versions/) # Default: python3 PRIMARY_PYTHON?=python3 # Minimum required Python version. -# Default: 3.9 -PYTHON_MIN_VERSION?=3.9 +# Default: 3.10 +PYTHON_MIN_VERSION?=3.10 # Install packages using the given package installer method. -# Supported are `pip` and `uv`. If uv is used, its global availability is -# checked. Otherwise, it is installed, either in the virtual environment or -# using the `PRIMARY_PYTHON`, dependent on the `VENV_ENABLED` setting. If -# `VENV_ENABLED` and uv is selected, uv is used to create the virtual -# environment. +# Supported are `pip` and `uv`. When `uv` is selected, a global installation +# is auto-detected and used if available. Otherwise, uv is installed in the +# virtual environment or using `PRIMARY_PYTHON`, depending on the +# `VENV_ENABLED` setting. # Default: pip PYTHON_PACKAGE_INSTALLER?=uv -# Flag whether to use a global installed 'uv' or install -# it in the virtual environment. -# Default: false -MXENV_UV_GLOBAL?=false +# Python version for UV to install/use when creating virtual +# environments with global UV. Passed to `uv venv -p VALUE`. Supports version +# specs like `3.11`, `3.14`, `cpython@3.14`. Defaults to PRIMARY_PYTHON value +# for backward compatibility. +# Default: $(PRIMARY_PYTHON) +UV_PYTHON?=$(PRIMARY_PYTHON) # Flag whether to use virtual environment. If `false`, the # interpreter according to `PRIMARY_PYTHON` found in `PATH` is used. @@ -107,7 +120,7 @@ PACKAGES_ALLOW_PRERELEASES?=false # The command which gets executed. Defaults to the location the # :ref:`run-tests` template gets rendered to if configured. # Default: .mxmake/files/run-tests.sh -TEST_COMMAND?=$(VENV_FOLDER)/bin/pytest src/node/tests +TEST_COMMAND?=.mxmake/files/run-tests.sh # Additional Python requirements for running tests to be # installed (via pip). @@ -123,12 +136,25 @@ TEST_DEPENDENCY_TARGETS?= # The command which gets executed. Defaults to the location the # :ref:`run-coverage` template gets rendered to if configured. # Default: .mxmake/files/run-coverage.sh -COVERAGE_COMMAND?=\ - $(VENV_FOLDER)/bin/coverage run \ - --source=src/node \ - --omit=src/node/testing/profiling.py \ - -m pytest src/node/tests \ - && $(VENV_FOLDER)/bin/coverage report --fail-under=100 +COVERAGE_COMMAND?=.mxmake/files/run-coverage.sh + +## applications.zest-releaser + +# Options to pass to zest.releaser prerelease command. +# No default value. +ZEST_RELEASER_PRERELEASE_OPTIONS?= + +# Options to pass to zest.releaser release command. +# No default value. +ZEST_RELEASER_RELEASE_OPTIONS?= + +# Options to pass to zest.releaser postrelease command. +# No default value. +ZEST_RELEASER_POSTRELEASE_OPTIONS?= + +# Options to pass to zest.releaser fullrelease command. +# No default value. +ZEST_RELEASER_FULLRELEASE_OPTIONS?= ############################################################################## # END SETTINGS - DO NOT EDIT BELOW THIS LINE @@ -144,6 +170,9 @@ FORMAT_TARGETS?= export PATH:=$(if $(EXTRA_PATH),$(EXTRA_PATH):,)$(PATH) +# Helper variable: adds trailing slash to PROJECT_PATH_PYTHON only if non-empty +PYTHON_PROJECT_PREFIX=$(if $(PROJECT_PATH_PYTHON),$(PROJECT_PATH_PYTHON)/,) + # Defensive settings for make: https://tech.davis-hansson.com/p/make/ SHELL:=bash .ONESHELL: @@ -168,7 +197,7 @@ $(SENTINEL): $(firstword $(MAKEFILE_LIST)) # mxenv ############################################################################## -export OS:=$(OS) +OS?= # Determine the executable path ifeq ("$(VENV_ENABLED)", "true") @@ -184,26 +213,61 @@ else MXENV_PYTHON=$(PRIMARY_PYTHON) endif -# Determine the package installer +# Determine the package installer with non-interactive flags ifeq ("$(PYTHON_PACKAGE_INSTALLER)","uv") -PYTHON_PACKAGE_COMMAND=uv pip +PYTHON_PACKAGE_COMMAND=uv pip --no-progress else PYTHON_PACKAGE_COMMAND=$(MXENV_PYTHON) -m pip endif +# Auto-detect global uv availability (simple existence check) +ifeq ("$(PYTHON_PACKAGE_INSTALLER)","uv") +UV_AVAILABLE:=$(shell command -v uv >/dev/null 2>&1 && echo "true" || echo "false") +else +UV_AVAILABLE:=false +endif + +# Determine installation strategy +# depending on the PYTHON_PACKAGE_INSTALLER and UV_AVAILABLE +# - both vars can be false or +# - one of them can be true, +# - but never boths. +USE_GLOBAL_UV:=$(shell [[ "$(PYTHON_PACKAGE_INSTALLER)" == "uv" && "$(UV_AVAILABLE)" == "true" ]] && echo "true" || echo "false") +USE_LOCAL_UV:=$(shell [[ "$(PYTHON_PACKAGE_INSTALLER)" == "uv" && "$(UV_AVAILABLE)" == "false" ]] && echo "true" || echo "false") + +# Check if global UV is outdated (non-blocking warning) +ifeq ("$(USE_GLOBAL_UV)","true") +UV_OUTDATED:=$(shell uv self update --dry-run 2>&1 | grep -q "Would update" && echo "true" || echo "false") +else +UV_OUTDATED:=false +endif + MXENV_TARGET:=$(SENTINEL_FOLDER)/mxenv.sentinel $(MXENV_TARGET): $(SENTINEL) + # Validation: Check Python version if not using global uv +ifneq ("$(USE_GLOBAL_UV)","true") @$(PRIMARY_PYTHON) -c "import sys; vi = sys.version_info; sys.exit(1 if (int(vi[0]), int(vi[1])) >= tuple(map(int, '$(PYTHON_MIN_VERSION)'.split('.'))) else 0)" \ && echo "Need Python >= $(PYTHON_MIN_VERSION)" && exit 1 || : +else + @echo "Using global uv for Python $(UV_PYTHON)" +endif + # Validation: Check VENV_FOLDER is set if venv enabled @[[ "$(VENV_ENABLED)" == "true" && "$(VENV_FOLDER)" == "" ]] \ && echo "VENV_FOLDER must be configured if VENV_ENABLED is true" && exit 1 || : - @[[ "$(VENV_ENABLED)$(PYTHON_PACKAGE_INSTALLER)" == "falseuv" ]] \ + # Validation: Check uv not used with system Python + @[[ "$(VENV_ENABLED)" == "false" && "$(PYTHON_PACKAGE_INSTALLER)" == "uv" ]] \ && echo "Package installer uv does not work with a global Python interpreter." && exit 1 || : + # Warning: Notify if global UV is outdated +ifeq ("$(UV_OUTDATED)","true") + @echo "WARNING: A newer version of uv is available. Run 'uv self update' to upgrade." +endif + + # Create virtual environment ifeq ("$(VENV_ENABLED)", "true") ifeq ("$(VENV_CREATE)", "true") -ifeq ("$(PYTHON_PACKAGE_INSTALLER)$(MXENV_UV_GLOBAL)","uvtrue") - @echo "Setup Python Virtual Environment using package 'uv' at '$(VENV_FOLDER)'" - @uv venv -p $(PRIMARY_PYTHON) --seed $(VENV_FOLDER) +ifeq ("$(USE_GLOBAL_UV)","true") + @echo "Setup Python Virtual Environment using global uv at '$(VENV_FOLDER)'" + @uv venv --allow-existing --no-progress -p $(UV_PYTHON) --seed $(VENV_FOLDER) else @echo "Setup Python Virtual Environment using module 'venv' at '$(VENV_FOLDER)'" @$(PRIMARY_PYTHON) -m venv $(VENV_FOLDER) @@ -213,10 +277,14 @@ endif else @echo "Using system Python interpreter" endif -ifeq ("$(PYTHON_PACKAGE_INSTALLER)$(MXENV_UV_GLOBAL)","uvfalse") - @echo "Install uv" + + # Install uv locally if needed +ifeq ("$(USE_LOCAL_UV)","true") + @echo "Install uv in virtual environment" @$(MXENV_PYTHON) -m pip install uv endif + + # Install/upgrade core packages @$(PYTHON_PACKAGE_COMMAND) install -U pip setuptools wheel @echo "Install/Update MXStack Python packages" @$(PYTHON_PACKAGE_COMMAND) install -U $(MXDEV) $(MXMAKE) @@ -244,6 +312,31 @@ INSTALL_TARGETS+=mxenv DIRTY_TARGETS+=mxenv-dirty CLEAN_TARGETS+=mxenv-clean +############################################################################## +# sources +############################################################################## + +SOURCES_TARGET:=$(SENTINEL_FOLDER)/sources.sentinel +$(SOURCES_TARGET): $(PROJECT_CONFIG) $(MXENV_TARGET) + @echo "Checkout project sources" + @mxdev -f -c $(PROJECT_CONFIG) + @touch $(SOURCES_TARGET) + +.PHONY: sources +sources: $(SOURCES_TARGET) + +.PHONY: sources-dirty +sources-dirty: + @rm -f $(SOURCES_TARGET) + +.PHONY: sources-purge +sources-purge: sources-dirty + @rm -rf sources + +INSTALL_TARGETS+=sources +DIRTY_TARGETS+=sources-dirty +PURGE_TARGETS+=sources-purge + ############################################################################## # mxfiles ############################################################################## @@ -271,7 +364,7 @@ else @echo "[settings]" > $(PROJECT_CONFIG) endif -LOCAL_PACKAGE_FILES:=$(wildcard pyproject.toml setup.cfg setup.py requirements.txt constraints.txt) +LOCAL_PACKAGE_FILES:=$(wildcard $(PYTHON_PROJECT_PREFIX)pyproject.toml $(PYTHON_PROJECT_PREFIX)setup.cfg $(PYTHON_PROJECT_PREFIX)setup.py $(PYTHON_PROJECT_PREFIX)requirements.txt $(PYTHON_PROJECT_PREFIX)constraints.txt) FILES_TARGET:=requirements-mxdev.txt $(FILES_TARGET): $(PROJECT_CONFIG) $(MXENV_TARGET) $(SOURCES_TARGET) $(LOCAL_PACKAGE_FILES) @@ -402,6 +495,48 @@ INSTALL_TARGETS+=$(COVERAGE_TARGET) DIRTY_TARGETS+=coverage-dirty CLEAN_TARGETS+=coverage-clean +############################################################################## +# zest-releaser +############################################################################## + +ZEST_RELEASER_TARGET:=$(SENTINEL_FOLDER)/zest-releaser.sentinel +$(ZEST_RELEASER_TARGET): $(MXENV_TARGET) + @echo "Install zest.releaser" + @$(PYTHON_PACKAGE_COMMAND) install zest.releaser + @touch $(ZEST_RELEASER_TARGET) + +.PHONY: zest-releaser-prerelease +zest-releaser-prerelease: $(ZEST_RELEASER_TARGET) + @echo "Run prerelease" + @prerelease $(ZEST_RELEASER_PRERELEASE_OPTIONS) + +.PHONY: zest-releaser-release +zest-releaser-release: $(ZEST_RELEASER_TARGET) + @echo "Run release" + @release $(ZEST_RELEASER_RELEASE_OPTIONS) + +.PHONY: zest-releaser-postrelease +zest-releaser-postrelease: $(ZEST_RELEASER_TARGET) + @echo "Run postrelease" + @postrelease $(ZEST_RELEASER_POSTRELEASE_OPTIONS) + +.PHONY: zest-releaser-fullrelease +zest-releaser-fullrelease: $(ZEST_RELEASER_TARGET) + @echo "Run fullrelease" + @fullrelease $(ZEST_RELEASER_FULLRELEASE_OPTIONS) + +.PHONY: zest-releaser-dirty +zest-releaser-dirty: + @rm -f $(ZEST_RELEASER_TARGET) + +.PHONY: zest-releaser-clean +zest-releaser-clean: zest-releaser-dirty + @test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y zest.releaser || : + +INSTALL_TARGETS+=$(ZEST_RELEASER_TARGET) +DIRTY_TARGETS+=zest-releaser-dirty +CLEAN_TARGETS+=zest-releaser-clean + ############################################################################## # Custom includes ############################################################################## diff --git a/mx.ini b/mx.ini index 098ead2..5a9d32e 100644 --- a/mx.ini +++ b/mx.ini @@ -1,2 +1,58 @@ [settings] +threads = 5 + +# conestack git URLs +cs = https://github.com/conestack +cs_push = git@github.com:conestack + +# checkout source packages +checkout_packages = true + +# feature branch to checkout +feature_branch = refactor-package-layout + +# main package main-package = -e .[test] + +mxmake-test-runner = pytest +# fixed dependency package versions +version-overrides = + pyramid==2.0.2 + +# templates and environment +mxmake-templates = + run-tests + run-coverage + +mxmake-test-path = src +mxmake-source-path = src/node + +[mxmake-env] +TESTRUN_MARKER = 1 + +[mxmake-run-tests] +environment = env + +[mxmake-run-coverage] +environment = env + +############################################################################### +# base packages +############################################################################### + +[odict] +use = ${settings:checkout_packages} +url = ${settings:cs}/odict.git +pushurl = ${settings:cs_push}/odict.git +branch = ${settings:feature_branch} +mxmake-test-path = tests +mxmake-source-path = src/odict + +[plumber] +use = ${settings:checkout_packages} +url = ${settings:cs}/plumber.git +pushurl = ${settings:cs_push}/plumber.git +branch = ${settings:feature_branch} +extras = test +mxmake-test-path = tests +mxmake-source-path = src/plumber diff --git a/pyproject.toml b/pyproject.toml index 8e0cad5..72a3c47 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,12 +41,6 @@ test = [ [project.urls] Homepage = "http://github.com/conestack/node" -[tool.hatch.version] -source = "vcs" - -[tool.hatch.metadata] -allow-direct-references = true - [tool.hatch.metadata.hooks.fancy-pypi-readme] content-type = "text/x-rst" From f1da78517796fa25b94b724a25f0d4f3b7d19b90 Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Thu, 13 Nov 2025 10:10:17 +0100 Subject: [PATCH 10/12] update github workflow --- .github/workflows/test.yml | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9ac4aa9..4da73a5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,21 +1,14 @@ -name: Tests +name: Test node on: [push] jobs: test: - name: Test ${{ matrix.python }} - ${{ matrix.os }} - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest strategy: - fail-fast: false matrix: - os: - - ubuntu-latest - - windows-latest - - macos-latest - - python: + python-version: - "3.10" - "3.11" - "3.12" @@ -23,24 +16,15 @@ jobs: - "3.14" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - name: Set up Python + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python }} - - - name: Install - run: | - pip install coverage - pip install -e .[test] + python-version: ${{ matrix.python-version }} - - name: Run tests - run: | - python --version - pytest src/node/tests + - name: Show Python version + run: python -c "import sys; print(sys.version)" - - name: Run coverage - run: | - coverage run --source=src/node --omit=src/node/testing/profiling.py -m pytest src/node/tests - coverage report --fail-under=100 + - name: Run tests an collect code coverage + run: make coverage From 83130e89801f7366df09d8ff7e165b225469de8a Mon Sep 17 00:00:00 2001 From: Lena Daxenbichler Date: Tue, 25 Nov 2025 12:36:35 +0100 Subject: [PATCH 11/12] change venv directory to 'venv'. remove unnecessary files from build --- .gitignore | 4 ++-- Makefile | 2 +- pyproject.toml | 7 +++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 786961b..c239efb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,10 @@ /.coverage /.mxmake /.ruff_cache -/.venv /build +/constraints-mxdev.txt /dist/ /htmlcov/ /requirements-mxdev.txt -/constraints-mxdev.txt /sources/ +/venv/ diff --git a/Makefile b/Makefile index e5e08e9..29dc534 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,7 @@ VENV_CREATE?=true # `VENV_CREATE` is false it is expected to point to an existing virtual # environment. If `VENV_ENABLED` is `false` it is ignored. # Default: .venv -VENV_FOLDER?=.venv +VENV_FOLDER?=venv # mxdev to install in virtual environment. # Default: mxdev diff --git a/pyproject.toml b/pyproject.toml index 72a3c47..e37e6e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,13 @@ path = "CHANGES.rst" [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] path = "LICENSE.rst" +[tool.hatch.build.targets.sdist] +exclude = [ + "/.github/", + "/Makefile", + "/mx.ini", +] + [tool.hatch.build.targets.wheel] packages = ["src/node"] From 2ba0e5ae546c6a093511fec1295a6dd1ddf1ac25 Mon Sep 17 00:00:00 2001 From: Robert Niederreiter Date: Tue, 25 Nov 2025 14:54:17 +0100 Subject: [PATCH 12/12] define fancy-pypi-readme fragments as regular array --- pyproject.toml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e37e6e1..da24e6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,15 +43,13 @@ Homepage = "http://github.com/conestack/node" [tool.hatch.metadata.hooks.fancy-pypi-readme] content-type = "text/x-rst" - -[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] -path = "README.rst" - -[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] -path = "CHANGES.rst" - -[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] -path = "LICENSE.rst" +fragments = [ + {path = "README.rst"}, + {text = "\n\n"}, + {path = "CHANGES.rst"}, + {text = "\n\n"}, + {path = "LICENSE.rst"}, +] [tool.hatch.build.targets.sdist] exclude = [