From 59cf0af27f69e2aa8dc9bdd2ce4b79e29cfb2111 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:17:12 +0200 Subject: [PATCH 01/11] Create ComPWA packaging fork of 1.4.0 --- .github/workflows/cd.yml | 25 +++++++++++++++++++++++++ README.rst | 11 +++++++++-- constraint/version.py | 4 ++-- pyproject.toml | 6 ++++++ setup.py | 2 +- 5 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/cd.yml create mode 100644 pyproject.toml diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..46ccc4c --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,25 @@ +name: CD + +on: + release: + types: + - prereleased + - released + +jobs: + package-name: + uses: ComPWA/actions/.github/workflows/get-pypi-name.yml@v4 + pypi: + environment: + name: PyPI + url: https://pypi.org/p/${{ needs.package-name.outputs.name }} + if: startsWith(github.ref, 'refs/tags') + name: Publish to PyPI + needs: + - package-name + permissions: + id-token: write + runs-on: ubuntu-24.04 + steps: + - uses: ComPWA/actions/build-pypi-distribution@v4 + - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/README.rst b/README.rst index 564e46a..05a8eb5 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,14 @@ |Build Status| |Code Health| |Code Coverage| -python-constraint -================= +compwa-python-constraint +======================= + +This is the ComPWA-maintained packaging fork of ``python-constraint`` 1.4.0. +It preserves the public ``constraint`` import package while providing modern +``.tar.gz`` and wheel distribution artifacts. + +The original project is maintained at +https://github.com/python-constraint/python-constraint. Introduction ------------ diff --git a/constraint/version.py b/constraint/version.py index b3dddc1..dc4315e 100644 --- a/constraint/version.py +++ b/constraint/version.py @@ -2,7 +2,7 @@ __copyright__ = "Copyright (c) 2005-2018 - Gustavo Niemeyer " __credits__ = ["Sebastien Celles"] __license__ = "" -__version__ = "1.4.0" +__version__ = "1.4.0.post1" __email__ = "gustavo@niemeyer.net" __status__ = "Development" -__url__ = "https://github.com/python-constraint/python-constraint" +__url__ = "https://github.com/ComPWA/python-constraint" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..bb40d50 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +build-backend = "setuptools.build_meta" +requires = [ + "setuptools>=61", + "wheel", +] diff --git a/setup.py b/setup.py index 77b0253..1136fa5 100755 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from os import path import io -NAME = "python-constraint" +NAME = "compwa-python-constraint" filename = "%s/version.py" % "constraint" with open(filename) as f: exec(f.read()) From 80427d0e9644855cfd6230c207337021b83e6635 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:30:38 +0200 Subject: [PATCH 02/11] Migrate package metadata to pyproject.toml --- README.rst | 2 +- pyproject.toml | 57 ++++++++++++++++++++++++++- setup.cfg | 9 ----- setup.py | 102 ------------------------------------------------- 4 files changed, 56 insertions(+), 114 deletions(-) delete mode 100644 setup.cfg delete mode 100755 setup.py diff --git a/README.rst b/README.rst index 05a8eb5..db7e7e5 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ |Build Status| |Code Health| |Code Coverage| compwa-python-constraint -======================= +======================== This is the ComPWA-maintained packaging fork of ``python-constraint`` 1.4.0. It preserves the public ``constraint`` import package while providing modern diff --git a/pyproject.toml b/pyproject.toml index bb40d50..c7dba34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,59 @@ [build-system] build-backend = "setuptools.build_meta" requires = [ - "setuptools>=61", - "wheel", + "setuptools>=77", ] + +[project] +authors = [ + {name = "Gustavo Niemeyer", email = "gustavo@niemeyer.net"}, +] +classifiers = [ + "Development Status :: 3 - Alpha", + "Environment :: Console", + "Intended Audience :: Science/Research", + "Operating System :: OS Independent", + "Programming Language :: Cython", + "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Topic :: Scientific/Engineering", +] +description = "Support for handling constraint-solving problems over finite domains" +dynamic = ["version"] +keywords = [ + "CSP", + "constraint solving", + "problem solver", +] +license = "BSD-2-Clause" +license-files = ["LICENSE"] +name = "compwa-python-constraint" +readme = "README.rst" + +[project.optional-dependencies] +dev = [ + "check-manifest", + "nose", +] +test = [ + "coverage", + "nose", +] + +[project.urls] +Documentation = "https://python-constraint.github.io/python-constraint/" +Issues = "https://github.com/ComPWA/python-constraint/issues" +Repository = "https://github.com/ComPWA/python-constraint" + +[tool.setuptools.packages.find] +exclude = [ + "contrib", + "docs", + "tests*", +] + +[tool.setuptools.dynamic] +version = {attr = "constraint.version.__version__"} diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 5bf0452..0000000 --- a/setup.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[bdist_wheel] -universal = 1 - -[bdist_rpm] -doc_files = README.rst -use_bzip2 = 1 - -[sdist] -formats = bztar diff --git a/setup.py b/setup.py deleted file mode 100755 index 1136fa5..0000000 --- a/setup.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from setuptools import setup, find_packages # Always prefer setuptools over distutils -from codecs import open # To use a consistent encoding -from os import path -import io - -NAME = "compwa-python-constraint" -filename = "%s/version.py" % "constraint" -with open(filename) as f: - exec(f.read()) - -here = path.abspath(path.dirname(__file__)) - - -def readme(): - filename = path.join(here, "README.rst") - with io.open(filename, "rt", encoding="UTF-8") as f: - return f.read() - - -setup( - name=NAME, - # Versions should comply with PEP440. For a discussion on single-sourcing - # the version across setup.py and the project code, see - # https://packaging.python.org/en/latest/development.html#single-sourcing-the-version - # version='0.0.1', - version=__version__, - description="python-constraint is a module implementing support " - "for handling CSPs (Constraint Solving Problems) over finite domain", - long_description=readme(), - # The project's main homepage. - url=__url__, - # Author details - author=__author__, - author_email=__email__, - # Choose your license - license=__license__, - # See https://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=[ - # How mature is this project? Common values are - # 3 - Alpha - # 4 - Beta - # 5 - Production/Stable - "Development Status :: 3 - Alpha", - # Indicate who your project is intended for - "Environment :: Console", - # 'Topic :: Software Development :: Build Tools', - "Intended Audience :: Science/Research", - "Operating System :: OS Independent", - # Specify the Python versions you support here. In particular, ensure - # that you indicate whether you support Python 2, Python 3 or both. - "Programming Language :: Cython", - "Programming Language :: Python", - # 'Programming Language :: Python :: 2', - # 'Programming Language :: Python :: 2.6', - "Programming Language :: Python :: 2.7", - # 'Programming Language :: Python :: 3', - # 'Programming Language :: Python :: 3.2', - # "Programming Language :: Python :: 3.3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Topic :: Scientific/Engineering", - # Pick your license as you wish (should match "license" above) - "License :: OSI Approved :: BSD License", - ], - # What does your project relate to? - keywords="csp constraint solving problems problem solver", - # You can just specify the packages manually here if your project is - # simple. Or you can use find_packages(). - packages=find_packages(exclude=["contrib", "docs", "tests*"]), - # List run-time dependencies here. These will be installed by pip when your - # project is installed. For an analysis of "install_requires" vs pip's - # requirements files see: - # https://packaging.python.org/en/latest/technical.html#install-requires-vs-requirements-files - install_requires=[], - # List additional groups of dependencies here (e.g. development dependencies). - # You can install these using the following syntax, for example: - # $ pip install -e .[dev,test] - extras_require={"dev": ["check-manifest", "nose"], "test": ["coverage", "nose"]}, - # If there are data files included in your packages that need to be - # installed, specify them here. If using Python 2.6 or less, then these - # have to be included in MANIFEST.in as well. - # package_data={ - # 'sample': ['logging.conf'], - # }, - # Although 'package_data' is the preferred approach, in some case you may - # need to place data files outside of your packages. - # see http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files - # In this case, 'data_file' will be installed into '/my_data' - # data_files=[('my_data', ['data/data_file'])], - # To provide executable scripts, use entry points in preference to the - # "scripts" keyword. Entry points provide cross-platform support and allow - # pip to create the appropriate form of executable for the target platform. - # entry_points={ - # 'console_scripts': [ - # 'sample=sample:main', - # ], - # }, -) From 57c86ea1b6dabb691731368f59234496dae35196 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:51:17 +0200 Subject: [PATCH 03/11] MAINT: update GitHub Actions and pin SHA --- .github/workflows/cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 46ccc4c..4006689 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -8,7 +8,7 @@ on: jobs: package-name: - uses: ComPWA/actions/.github/workflows/get-pypi-name.yml@v4 + uses: ComPWA/actions/.github/workflows/get-pypi-name.yml@99e91bcc486218c7dbbb4f2e0319bfcb028562aa # 4.0.1 pypi: environment: name: PyPI @@ -21,5 +21,5 @@ jobs: id-token: write runs-on: ubuntu-24.04 steps: - - uses: ComPWA/actions/build-pypi-distribution@v4 - - uses: pypa/gh-action-pypi-publish@release/v1 + - uses: ComPWA/actions/build-pypi-distribution@99e91bcc486218c7dbbb4f2e0319bfcb028562aa # 4.0.1 + - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 From 54a68473de02a3b14251a688e12142db95ede3dd Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:51:51 +0200 Subject: [PATCH 04/11] DX: run tests on GitHub --- .github/workflows/ci.yml | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..102129e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,61 @@ +name: CI + +on: + pull_request: + branches: + - 1.4.x + push: + branches: + - 1.4.x + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }} + +jobs: + test: + name: Test Python ${{ matrix.python-version }} + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + python-version: + - "3.10" + - "3.11" + - "3.12" + - "3.13" + - "3.14" + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + python-version: ${{ matrix.python-version }} + - name: Run tests + run: uv run --no-project --with pytest python -m pytest -q + + distribution: + name: Build and inspect distributions + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + python-version: "3.14" + - name: Build wheel and source distribution + run: uv build + - name: Check distribution metadata + run: uvx twine check dist/* + - name: Prepare isolated wheel tests + run: | + mkdir -p "${{ runner.temp }}/wheel-test" + cp -R tests "${{ runner.temp }}/wheel-test/" + - name: Test the installed wheel + working-directory: ${{ runner.temp }}/wheel-test + run: >- + uv run + --isolated + --no-project + --with "${{ github.workspace }}"/dist/*.whl + --with pytest + python -m pytest -q From f91570a173a59144397dff5a8a51fa9f47118ee0 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 14:52:08 +0200 Subject: [PATCH 05/11] DX: add Dependabot --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6caa301 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 + +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: yearly From b2fb57311e07f4437d75206653530ded31149fc5 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:02:27 +0200 Subject: [PATCH 06/11] ENH: show colors in CI * DX: add agents configurations to `.gitignore` --- .github/workflows/ci.yml | 3 +++ .gitignore | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 102129e..e0dd542 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,8 @@ name: CI +env: + FORCE_COLOR: yes + on: pull_request: branches: diff --git a/.gitignore b/.gitignore index b102207..de19ed7 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,10 @@ target/ # PyCharm / Intellij .idea/ + +# Agent configuration +/.agents/ +/.claude/ +/.codex/ +/AGENTS.md +/CLAUDE.md From ba03f135626bc5f92911c5f365250e0af03d6b82 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:10:08 +0200 Subject: [PATCH 07/11] DX: add Tombi configuration --- pyproject.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index c7dba34..d8f3ec4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,3 +57,13 @@ exclude = [ [tool.setuptools.dynamic] version = {attr = "constraint.version.__version__"} + +[tool.tombi.files] +exclude = ["**/uv.lock"] + +[tool.tombi.format.rules] +indent-width = 4 +line-width = 88 + +[tool.tombi.lint.rules] +key-empty = "off" From 7e33b333a74952f07eae5b3dbf0a73bc56d335c5 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:14:31 +0200 Subject: [PATCH 08/11] MAINT: format `pyproject.toml` --- pyproject.toml | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d8f3ec4..4c39584 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,14 @@ -[build-system] -build-backend = "setuptools.build_meta" -requires = [ - "setuptools>=77", -] - [project] -authors = [ - {name = "Gustavo Niemeyer", email = "gustavo@niemeyer.net"}, +name = "compwa-python-constraint" +description = "Support for handling constraint-solving problems over finite domains" +readme = "README.rst" +license = "BSD-2-Clause" +license-files = ["LICENSE"] +authors = [{ name = "Gustavo Niemeyer", email = "gustavo@niemeyer.net" }] +keywords = [ + "CSP", + "constraint solving", + "problem solver", ] classifiers = [ "Development Status :: 3 - Alpha", @@ -21,17 +23,12 @@ classifiers = [ "Programming Language :: Python :: 3.6", "Topic :: Scientific/Engineering", ] -description = "Support for handling constraint-solving problems over finite domains" dynamic = ["version"] -keywords = [ - "CSP", - "constraint solving", - "problem solver", -] -license = "BSD-2-Clause" -license-files = ["LICENSE"] -name = "compwa-python-constraint" -readme = "README.rst" + +[project.urls] +Documentation = "https://python-constraint.github.io/python-constraint" +Issues = "https://github.com/ComPWA/python-constraint/issues" +Repository = "https://github.com/ComPWA/python-constraint" [project.optional-dependencies] dev = [ @@ -43,10 +40,9 @@ test = [ "nose", ] -[project.urls] -Documentation = "https://python-constraint.github.io/python-constraint/" -Issues = "https://github.com/ComPWA/python-constraint/issues" -Repository = "https://github.com/ComPWA/python-constraint" +[build-system] +requires = ["setuptools>=77"] +build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] exclude = [ @@ -56,7 +52,7 @@ exclude = [ ] [tool.setuptools.dynamic] -version = {attr = "constraint.version.__version__"} +version = { attr = "constraint.version.__version__" } [tool.tombi.files] exclude = ["**/uv.lock"] From fc02a60e5dcc1a518c7e696c65b71021fb61a7d7 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:14:48 +0200 Subject: [PATCH 09/11] DX: add virtual environments to `.gitignore` --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index de19ed7..3870980 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,10 @@ target/ # PyCharm / Intellij .idea/ +# Virtual environments +.venv/ +uv.lock + # Agent configuration /.agents/ /.claude/ From 8f467e83d33a9226a853d1aca2a317d934802d67 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:16:16 +0200 Subject: [PATCH 10/11] DOC: improve motivation description for this fork --- README.rst | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index db7e7e5..71a291e 100644 --- a/README.rst +++ b/README.rst @@ -3,12 +3,38 @@ compwa-python-constraint ======================== -This is the ComPWA-maintained packaging fork of ``python-constraint`` 1.4.0. -It preserves the public ``constraint`` import package while providing modern -``.tar.gz`` and wheel distribution artifacts. +This is a packaging fork of `python-constraint 1.4.0 +`_, +maintained by the `ComPWA project `_. It is +published as `compwa-python-constraint +`_, but preserves the +public ``constraint`` import package and the behavior of the upstream 1.4.0 +solver. + +Why this fork exists +-------------------- -The original project is maintained at -https://github.com/python-constraint/python-constraint. +The upstream 1.4.0 release on `PyPI +`_ provides only a +``.tar.bz2`` source distribution. `PEP 625 +`_ standardized source distributions as +gzip-compressed ``.tar.gz`` archives. In version 0.12.0, `uv stopped +accepting legacy source-distribution formats +`_, +including ``.tar.bz2``, and recommends rebuilding affected packages as +``.tar.gz`` archives. + +This fork makes that packaging-only update so projects can continue using the +1.4.0 implementation with current Python packaging tools. Its declarative +``pyproject.toml`` build produces: + +* a pure-Python ``py3-none-any`` wheel, which installers can use without a + local build step; and +* a standards-compliant ``.tar.gz`` source distribution as a fallback. + +The distribution is versioned as ``1.4.0.post1`` to identify it as a +downstream packaging revision. Solver changes continue to belong in the +`upstream project `_. Introduction ------------ From a51a72210a60381253f0ffd56967862b738f4185 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:20:52 +0200 Subject: [PATCH 11/11] MAINT: convert reST to Markdown --- README.md | 145 +++++++++++++++++++++++++++++++++++++ README.rst | 192 ------------------------------------------------- pyproject.toml | 2 +- 3 files changed, 146 insertions(+), 193 deletions(-) create mode 100644 README.md delete mode 100644 README.rst diff --git a/README.md b/README.md new file mode 100644 index 0000000..55c6b28 --- /dev/null +++ b/README.md @@ -0,0 +1,145 @@ +[![CI](https://github.com/ComPWA/python-constraint/actions/workflows/ci.yml/badge.svg)](https://github.com/ComPWA/python-constraint/actions/workflows/ci.yml) + +# compwa-python-constraint + +> [!NOTE] +> This is a packaging fork of [python-constraint 1.4.0](https://github.com/python-constraint/python-constraint/tree/1.4.0), maintained by the [ComPWA project](https://compwa.github.io). It is published as [compwa-python-constraint](https://pypi.org/project/compwa-python-constraint), but preserves the public `constraint` import package and the behavior of the upstream 1.4.0 solver. + +## Why this fork exists + +The upstream 1.4.0 release on +[PyPI](https://pypi.org/project/python-constraint/1.4.0) provides only a +`.tar.bz2` source distribution. +[PEP 625](https://peps.python.org/pep-0625/) standardized source distributions +as gzip-compressed `.tar.gz` archives. In version 0.12.0, +[uv stopped accepting legacy source-distribution formats](https://github.com/astral-sh/uv/releases/tag/0.12.0#breaking-changes), +including `.tar.bz2`, and recommends rebuilding affected packages as `.tar.gz` +archives. + +This fork makes that packaging-only update so projects can continue using the +1.4.0 implementation with current Python packaging tools. Its declarative +`pyproject.toml` build produces: + +- a pure-Python `py3-none-any` wheel, which installers can use without a local + build step; and +- a standards-compliant `.tar.gz` source distribution as a fallback. + +The distribution is versioned as `1.4.0.post1` to identify it as a downstream +packaging revision. Solver changes continue to belong in the +[upstream project](https://github.com/python-constraint/python-constraint). + +## Introduction + +The Python constraint module offers solvers for +[Constraint Satisfaction Problems (CSPs)](https://en.wikipedia.org/wiki/Constraint_satisfaction_problem) +over finite domains in simple and pure Python. A CSP can be represented in +terms of variables, their possible domains, and constraints between them. + +## Examples + +### Basics + +```python +>>> from constraint import * +>>> problem = Problem() +>>> problem.addVariable("a", [1, 2, 3]) +>>> problem.addVariable("b", [4, 5, 6]) +>>> problem.getSolutions() +[{'a': 3, 'b': 6}, {'a': 3, 'b': 5}, {'a': 3, 'b': 4}, + {'a': 2, 'b': 6}, {'a': 2, 'b': 5}, {'a': 2, 'b': 4}, + {'a': 1, 'b': 6}, {'a': 1, 'b': 5}, {'a': 1, 'b': 4}] + +>>> problem.addConstraint(lambda a, b: a * 2 == b, ("a", "b")) +>>> problem.getSolutions() +[{'a': 3, 'b': 6}, {'a': 2, 'b': 4}] + +>>> problem = Problem() +>>> problem.addVariables(["a", "b"], [1, 2, 3]) +>>> problem.addConstraint(AllDifferentConstraint()) +>>> problem.getSolutions() +[{'a': 3, 'b': 2}, {'a': 3, 'b': 1}, {'a': 2, 'b': 3}, + {'a': 2, 'b': 1}, {'a': 1, 'b': 2}, {'a': 1, 'b': 3}] +``` + +### Rooks problem + +```python +>>> problem = Problem() +>>> numpieces = 8 +>>> cols = range(numpieces) +>>> rows = range(numpieces) +>>> problem.addVariables(cols, rows) +>>> for col1 in cols: +... for col2 in cols: +... if col1 < col2: +... problem.addConstraint( +... lambda row1, row2: row1 != row2, +... (col1, col2), +... ) +>>> solutions = problem.getSolutions() +``` + +### Magic squares + +```python +>>> problem = Problem() +>>> problem.addVariables(range(16), range(1, 17)) +>>> problem.addConstraint(AllDifferentConstraint(), range(16)) +>>> problem.addConstraint(ExactSumConstraint(34), [0, 5, 10, 15]) +>>> problem.addConstraint(ExactSumConstraint(34), [3, 6, 9, 12]) +>>> for row in range(4): +... problem.addConstraint( +... ExactSumConstraint(34), +... [row * 4 + i for i in range(4)], +... ) +>>> for col in range(4): +... problem.addConstraint( +... ExactSumConstraint(34), +... [col + 4 * i for i in range(4)], +... ) +>>> solutions = problem.getSolutions() +``` + +## Features + +The following solvers are available: + +- Backtracking solver +- Recursive backtracking solver +- Minimum conflicts solver + +Predefined constraint types include: + +- `FunctionConstraint` +- `AllDifferentConstraint` +- `AllEqualConstraint` +- `ExactSumConstraint` +- `MaxSumConstraint` +- `MinSumConstraint` +- `InSetConstraint` +- `NotInSetConstraint` +- `SomeInSetConstraint` +- `SomeNotInSetConstraint` + +## Installation + +```shell +python -m pip install compwa-python-constraint +``` + +The distribution name is `compwa-python-constraint`, while the import remains +unchanged: + +```python +from constraint import Problem +``` + +## Upstream project + +`python-constraint` was written by Gustavo Niemeyer and is maintained at +[python-constraint/python-constraint](https://github.com/python-constraint/python-constraint). +Please report solver bugs and propose behavioral changes +[upstream](https://github.com/python-constraint/python-constraint/issues). + +For packaging issues specific to this fork, use the +[ComPWA issue tracker](https://github.com/ComPWA/python-constraint/issues). diff --git a/README.rst b/README.rst deleted file mode 100644 index 71a291e..0000000 --- a/README.rst +++ /dev/null @@ -1,192 +0,0 @@ -|Build Status| |Code Health| |Code Coverage| - -compwa-python-constraint -======================== - -This is a packaging fork of `python-constraint 1.4.0 -`_, -maintained by the `ComPWA project `_. It is -published as `compwa-python-constraint -`_, but preserves the -public ``constraint`` import package and the behavior of the upstream 1.4.0 -solver. - -Why this fork exists --------------------- - -The upstream 1.4.0 release on `PyPI -`_ provides only a -``.tar.bz2`` source distribution. `PEP 625 -`_ standardized source distributions as -gzip-compressed ``.tar.gz`` archives. In version 0.12.0, `uv stopped -accepting legacy source-distribution formats -`_, -including ``.tar.bz2``, and recommends rebuilding affected packages as -``.tar.gz`` archives. - -This fork makes that packaging-only update so projects can continue using the -1.4.0 implementation with current Python packaging tools. Its declarative -``pyproject.toml`` build produces: - -* a pure-Python ``py3-none-any`` wheel, which installers can use without a - local build step; and -* a standards-compliant ``.tar.gz`` source distribution as a fallback. - -The distribution is versioned as ``1.4.0.post1`` to identify it as a -downstream packaging revision. Solver changes continue to belong in the -`upstream project `_. - -Introduction ------------- -The Python constraint module offers solvers for `Constraint Satisfaction Problems (CSPs) `_ over finite domains in simple and pure Python. CSP is class of problems which may be represented in terms of variables (a, b, ...), domains (a in [1, 2, 3], ...), and constraints (a < b, ...). - -Examples --------- - -Basics -~~~~~~ - -This interactive Python session demonstrates the module basic operation: - -.. code-block:: python - - >>> from constraint import * - >>> problem = Problem() - >>> problem.addVariable("a", [1,2,3]) - >>> problem.addVariable("b", [4,5,6]) - >>> problem.getSolutions() - [{'a': 3, 'b': 6}, {'a': 3, 'b': 5}, {'a': 3, 'b': 4}, - {'a': 2, 'b': 6}, {'a': 2, 'b': 5}, {'a': 2, 'b': 4}, - {'a': 1, 'b': 6}, {'a': 1, 'b': 5}, {'a': 1, 'b': 4}] - - >>> problem.addConstraint(lambda a, b: a*2 == b, - ("a", "b")) - >>> problem.getSolutions() - [{'a': 3, 'b': 6}, {'a': 2, 'b': 4}] - - >>> problem = Problem() - >>> problem.addVariables(["a", "b"], [1, 2, 3]) - >>> problem.addConstraint(AllDifferentConstraint()) - >>> problem.getSolutions() - [{'a': 3, 'b': 2}, {'a': 3, 'b': 1}, {'a': 2, 'b': 3}, - {'a': 2, 'b': 1}, {'a': 1, 'b': 2}, {'a': 1, 'b': 3}] - -Rooks problem -~~~~~~~~~~~~~ - -The following example solves the classical Eight Rooks problem: - -.. code-block:: python - - >>> problem = Problem() - >>> numpieces = 8 - >>> cols = range(numpieces) - >>> rows = range(numpieces) - >>> problem.addVariables(cols, rows) - >>> for col1 in cols: - ... for col2 in cols: - ... if col1 < col2: - ... problem.addConstraint(lambda row1, row2: row1 != row2, - ... (col1, col2)) - >>> solutions = problem.getSolutions() - >>> solutions - >>> solutions - [{0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 1, 7: 0}, - {0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 0, 7: 1}, - {0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 1, 6: 2, 7: 0}, - {0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 1, 6: 0, 7: 2}, - ... - {0: 7, 1: 5, 2: 3, 3: 6, 4: 2, 5: 1, 6: 4, 7: 0}, - {0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 2, 6: 0, 7: 4}, - {0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 2, 6: 4, 7: 0}, - {0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 4, 6: 2, 7: 0}, - {0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 4, 6: 0, 7: 2}, - ...] - - -Magic squares -~~~~~~~~~~~~~ - -This example solves a 4x4 magic square: - -.. code-block:: python - - >>> problem = Problem() - >>> problem.addVariables(range(0, 16), range(1, 16 + 1)) - >>> problem.addConstraint(AllDifferentConstraint(), range(0, 16)) - >>> problem.addConstraint(ExactSumConstraint(34), [0, 5, 10, 15]) - >>> problem.addConstraint(ExactSumConstraint(34), [3, 6, 9, 12]) - >>> for row in range(4): - ... problem.addConstraint(ExactSumConstraint(34), - [row * 4 + i for i in range(4)]) - >>> for col in range(4): - ... problem.addConstraint(ExactSumConstraint(34), - [col + 4 * i for i in range(4)]) - >>> solutions = problem.getSolutions() - -Features --------- - -The following solvers are available: - -- Backtracking solver -- Recursive backtracking solver -- Minimum conflicts solver - - -.. role:: python(code) - :language: python - -Predefined constraint types currently available: - -- :python:`FunctionConstraint` -- :python:`AllDifferentConstraint` -- :python:`AllEqualConstraint` -- :python:`ExactSumConstraint` -- :python:`MaxSumConstraint` -- :python:`MinSumConstraint` -- :python:`InSetConstraint` -- :python:`NotInSetConstraint` -- :python:`SomeInSetConstraint` -- :python:`SomeNotInSetConstraint` - -API documentation ------------------ -Documentation for the module is available at: http://labix.org/doc/constraint/ - -Download and install --------------------- - -.. code-block:: shell - - $ pip install python-constraint - -Roadmap -------- - -This GitHub organization and repository is a global effort to help to -maintain python-constraint which was written by Gustavo Niemeyer -and originaly located at https://labix.org/python-constraint - -- Create some unit tests - DONE -- Enable continuous integration - DONE -- Port to Python 3 (Python 2 being also supported) - DONE -- Respect Style Guide for Python Code (PEP8) - DONE -- Improve code coverage writting more unit tests - ToDo -- Move doc to Sphinx or MkDocs - https://readthedocs.org/ - ToDo - -Contact -------- -- `Gustavo Niemeyer `_ -- `Sébastien Celles `_ - -But it's probably better to `open an issue `_. - - -.. |Build Status| image:: https://travis-ci.org/python-constraint/python-constraint.svg?branch=master - :target: https://travis-ci.org/python-constraint/python-constraint -.. |Code Health| image:: https://landscape.io/github/python-constraint/python-constraint/master/landscape.svg?style=flat - :target: https://landscape.io/github/python-constraint/python-constraint/master - :alt: Code Health -.. |Code Coverage| image:: https://coveralls.io/repos/github/python-constraint/python-constraint/badge.svg - :target: https://coveralls.io/github/python-constraint/python-constraint diff --git a/pyproject.toml b/pyproject.toml index 4c39584..1713df6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "compwa-python-constraint" description = "Support for handling constraint-solving problems over finite domains" -readme = "README.rst" +readme = "README.md" license = "BSD-2-Clause" license-files = ["LICENSE"] authors = [{ name = "Gustavo Niemeyer", email = "gustavo@niemeyer.net" }]