From fc63663a5c320c0f8c95ee88e40e0b29e1149224 Mon Sep 17 00:00:00 2001 From: Jay Pantone Date: Thu, 15 Jan 2026 11:03:55 -0600 Subject: [PATCH 1/6] Modernize packaging with pyproject.toml and hatchling - Replace setup.py and MANIFEST.in with comprehensive pyproject.toml using hatchling backend - Update minimum Python version to 3.10 (drop 3.8, 3.9 support) - Update GitHub Actions to v4/v5 and use python -m build - Update tox.ini: remove setup.py from flake8, use black>=22.10.0 - Update Black target version to py310 - Fix .zenodo.json syntax error (missing comma) - Add CITATION.cff for GitHub citation support - Update README.rst badges (GitHub Actions, Black, mypy) and installation instructions - Bump version to 4.1.0 --- .github/workflows/build-and-deploy.yml | 8 +-- .github/workflows/test.yml | 16 +++--- .zenodo.json | 4 +- CHANGELOG.md | 13 ++++- CITATION.cff | 32 +++++++++++ MANIFEST.in | 1 - README.rst | 21 ++++--- pyproject.toml | 79 ++++++++++++++++++++++++-- setup.py | 58 ------------------- tilings/__init__.py | 2 +- tox.ini | 6 +- 11 files changed, 145 insertions(+), 95 deletions(-) create mode 100644 CITATION.cff delete mode 100644 MANIFEST.in delete mode 100755 setup.py diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index d198ea2f..d5060808 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -9,16 +9,16 @@ jobs: build-and-deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: "3.13" - name: install dependencies run: | python -m pip install --upgrade pip - pip install setuptools wheel twine + pip install build twine - name: build - run: python setup.py sdist + run: python -m build - name: deploy env: TWINE_USERNAME: __token__ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3dc4036e..6cb17579 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,8 +51,8 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install dependencies from develop branch @@ -61,22 +61,20 @@ jobs: echo "Installing dependencies from develop branches instead of PyPI" python -m pip install git+https://github.com/PermutaTriangle/comb_spec_searcher.git@develop python -m pip install git+https://github.com/PermutaTriangle/Permuta.git@develop - - # Optional: Install the project in development mode to work with the new dependencies + + # Install the project in development mode to work with the new dependencies python -m pip install -e . - + # Verify installed versions echo "Checking installed comb_spec_searcher version:" python -c "import comb_spec_searcher; print(comb_spec_searcher.__version__)" echo "Checking installed permuta version:" python -c "import permuta; print(permuta.__version__)" - name: install dependencies - run: | - python -m pip install --upgrade pip tox - pip install setuptools wheel twine + run: python -m pip install --upgrade pip tox - name: run env: TOXENV: ${{ matrix.toxenv }} run: tox - name: setup - run: python setup.py install + run: pip install -e . diff --git a/.zenodo.json b/.zenodo.json index f10f421e..33b6585d 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -20,10 +20,10 @@ { "affiliation": "Marquette University", "name": "Jay Pantone" - } + }, { "affiliation": "Reykjavik University", "name": "Henning Ulfarsson" - }, + } ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 4edbb946..12e5de99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## Unreleased +## Unreleased + +## [4.1.0] - 2026-01-15 ### Changed - new GriddedPerm.contains_patt function checks positions first, then pattern and as a result can lead to huge 2x - 4x speed improvement in specification finding +- Migrated to modern pyproject.toml packaging with hatchling backend +- Minimum Python version is now 3.10 (dropped 3.8, 3.9 support) +- Updated GitHub Actions to use latest action versions (checkout@v4, setup-python@v5) +- Updated Black target version to Python 3.10 + +### Removed +- Removed legacy setup.py and MANIFEST.in files -## [4.0.0 - 2025-03-13] +## [4.0.0] - 2025-03-13 ### Added - python3.9 are deprecated, python3.10 - python3.13 are supported - added `TileScopePack.requirement_and_row_and_col_placements` diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..2f2415fd --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,32 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it as below." +type: software +title: "tilings: A Python library for gridded permutations and tilings" +url: "https://github.com/PermutaTriangle/Tilings" +repository-code: "https://github.com/PermutaTriangle/Tilings" +license: BSD-3-Clause +authors: + - given-names: "Christian" + family-names: "Bean" + affiliation: "Reykjavik University" + - given-names: "Jon Steinn" + family-names: "Eliasson" + affiliation: "Reykjavik University" + - given-names: "Tomas Ken" + family-names: "Magnusson" + - given-names: "Émile" + family-names: "Nadeau" + affiliation: "Reykjavik University" + - given-names: "Jay" + family-names: "Pantone" + affiliation: "Marquette University" + - given-names: "Henning" + family-names: "Ulfarsson" + affiliation: "Reykjavik University" +identifiers: + - type: doi + value: "10.5281/zenodo.4948344" + description: "DOI for all versions" + - type: url + value: "https://zenodo.org/badge/latestdoi/121506164" + description: "Latest Zenodo DOI" diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 27c4da87..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ - include tilings/py.typed diff --git a/README.rst b/README.rst index fa152180..874ac7bb 100644 --- a/README.rst +++ b/README.rst @@ -1,12 +1,18 @@ Tilings ======= -.. image:: https://travis-ci.org/PermutaTriangle/Tilings.svg?branch=master - :alt: Travis - :target: https://travis-ci.org/PermutaTriangle/Tilings -.. image:: https://coveralls.io/repos/github/PermutaTriangle/Tilings/badge.svg?branch=master +.. image:: https://github.com/PermutaTriangle/Tilings/actions/workflows/test.yml/badge.svg + :alt: Tests + :target: https://github.com/PermutaTriangle/Tilings/actions/workflows/test.yml +.. image:: https://img.shields.io/badge/code%20style-black-000000.svg + :alt: Code style: black + :target: https://github.com/psf/black +.. image:: https://img.shields.io/badge/mypy-checked-blue + :alt: mypy: checked + :target: https://mypy-lang.org/ +.. image:: https://img.shields.io/coveralls/github/PermutaTriangle/Tilings.svg :alt: Coveralls - :target: https://coveralls.io/github/PermutaTriangle/Tilings?branch=master + :target: https://coveralls.io/github/PermutaTriangle/Tilings .. image:: https://img.shields.io/pypi/v/Tilings.svg :alt: PyPI :target: https://pypi.python.org/pypi/Tilings @@ -14,9 +20,6 @@ Tilings :target: https://pypi.python.org/pypi/Tilings .. image:: https://img.shields.io/pypi/pyversions/Tilings.svg :target: https://pypi.python.org/pypi/Tilings -.. image:: https://requires.io/github/PermutaTriangle/Tilings/requirements.svg?branch=master - :target: https://requires.io/github/PermutaTriangle/Tilings/requirements/?branch=master - :alt: Requirements Status .. image:: https://zenodo.org/badge/121506164.svg :target: https://zenodo.org/badge/latestdoi/121506164 @@ -54,7 +57,7 @@ development mode by cloning the repository, running .. code:: bash - ./setup.py develop + pip install -e . To verify that your installation is correct, you can try to get a specification for `Av(12)` by running in your terminal: diff --git a/pyproject.toml b/pyproject.toml index 01c77571..cc3aa80c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,80 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "tilings" +dynamic = ["version"] +authors = [ + {name = "Permuta Triangle", email = "permutatriangle@gmail.com"}, +] +description = "A Python library for gridded permutations and tilings." +readme = "README.rst" +license = {text = "BSD-3-Clause"} +keywords = [ + "permutation", + "perm", + "gridded", + "pattern", + "tiling", + "avoid", + "contain", + "occurrences", + "grid", + "class", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Education", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Education", + "Topic :: Scientific/Engineering :: Mathematics", +] +requires-python = ">=3.10" +dependencies = [ + "comb-spec-searcher>=4.2.1", + "permuta>=2.3.0", +] + +[project.urls] +Source = "https://github.com/PermutaTriangle/Tilings" +Tracker = "https://github.com/PermutaTriangle/Tilings/issues" + +[project.scripts] +tilescope = "tilings.cli:main" + +[tool.hatch.version] +path = "tilings/__init__.py" + +[tool.hatchling.build.targets.wheel] +packages = ["tilings"] + +[tool.hatchling.build.targets.sdist] +include = [ + "tilings", + "tests", + "README.rst", + "LICENSE", + "CHANGELOG.md", + "CITATION.cff", +] + [tool.black] -target-version = ['py37'] +target-version = ['py310'] include = '\.pyi?$' exclude = ''' - ( /( - \.eggs # exclude a few common directories in the - | \.git # root of the project + \.eggs + | \.git | \.hg | \.mypy_cache | \.tox @@ -16,7 +84,6 @@ exclude = ''' | build | dist )/ - | foo.py # also separately exclude a file named foo.py in - # the root of the project + | foo.py ) ''' diff --git a/setup.py b/setup.py deleted file mode 100755 index 9c945de1..00000000 --- a/setup.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -import os - -from setuptools import find_packages, setup - - -def read(fname): - return open(os.path.join(os.path.dirname(__file__), fname), encoding="utf-8").read() - - -def get_version(rel_path): - for line in read(rel_path).splitlines(): - if line.startswith("__version__"): - delim = '"' if '"' in line else "'" - return line.split(delim)[1] - raise RuntimeError("Unable to find version string.") - - -setup( - name="tilings", - version=get_version("tilings/__init__.py"), - author="Permuta Triangle", - author_email="permutatriangle@gmail.com", - description="A Python library for gridded permutations and tilings.", - license="BSD-3", - keywords=( - "permutation perm gridded pattern tiling avoid contain" "occurrences grid class" - ), - url="https://github.com/PermutaTriangle/Tilings", - project_urls={ - "Source": "https://github.com/PermutaTriangle/Tilings", - "Tracker": "https://github.com/PermutaTriangle/Tilings/issues", - }, - packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), - long_description=read("README.rst"), - install_requires=[ - "comb-spec-searcher>=4.2.1", - "permuta>=2.3.0", - ], - python_requires=">=3.8", - include_package_data=True, - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Education", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: BSD License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Topic :: Education", - "Topic :: Scientific/Engineering :: Mathematics", - ], - entry_points={"console_scripts": ["tilescope=tilings.cli:main"]}, -) diff --git a/tilings/__init__.py b/tilings/__init__.py index f31c82f4..cdd506a0 100644 --- a/tilings/__init__.py +++ b/tilings/__init__.py @@ -2,6 +2,6 @@ from tilings.griddedperm import GriddedPerm from tilings.tiling import Tiling -__version__ = "4.0.0" +__version__ = "4.1.0" __all__ = ["GriddedPerm", "Tiling", "TrackingAssumption"] diff --git a/tox.ini b/tox.ini index a9127f83..4767d49b 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ basepython = deps = pytest pytest-timeout -commands = +commands = pip install --force-reinstall git+https://github.com/PermutaTriangle/comb_spec_searcher.git@develop pip freeze pytest @@ -43,7 +43,7 @@ deps = flake8 flake8-isort commands = - flake8 --isort-show-traceback tilings tests setup.py + flake8 --isort-show-traceback tilings tests [testenv:pylint] description = run pylint (static code analysis) @@ -65,5 +65,5 @@ commands = mypy description = check that comply with autoformating basepython = {[default]basepython} deps = - black==22.10.0 + black>=22.10.0 commands = black --check --diff . From 0f7d75838a39b8c87a575b0171e58871c3ab1c00 Mon Sep 17 00:00:00 2001 From: Jay Pantone Date: Thu, 15 Jan 2026 11:07:42 -0600 Subject: [PATCH 2/6] Fix Christian Bean affiliation to Keele University, fix changelog format --- .zenodo.json | 2 +- CHANGELOG.md | 2 +- CITATION.cff | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 33b6585d..29a65e4a 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -3,7 +3,7 @@ "title": "tilings", "creators": [ { - "affiliation": "Reykjavik University", + "affiliation": "Keele University", "name": "Christian Bean" }, { diff --git a/CHANGELOG.md b/CHANGELOG.md index 12e5de99..3c317fe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## Unreleased +## [Unreleased] ## [4.1.0] - 2026-01-15 ### Changed diff --git a/CITATION.cff b/CITATION.cff index 2f2415fd..2e33fe6d 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -8,7 +8,7 @@ license: BSD-3-Clause authors: - given-names: "Christian" family-names: "Bean" - affiliation: "Reykjavik University" + affiliation: "Keele University" - given-names: "Jon Steinn" family-names: "Eliasson" affiliation: "Reykjavik University" From fdae744a3b1e676d390e3301f252789b0ad0437b Mon Sep 17 00:00:00 2001 From: Jay Pantone Date: Thu, 15 Jan 2026 11:12:30 -0600 Subject: [PATCH 3/6] Apply black formatting for Python 3.10 target --- tests/strategies/test_encoding.py | 7 ++++++- tests/strategies/test_fusion_strat.py | 1 - tests/strategies/test_sanity_check.py | 4 +++- tests/test_assumptions.py | 1 - tests/test_griddedperm.py | 5 ++++- tilings/algorithms/fusion.py | 2 +- tilings/algorithms/minimal_gridded_perms.py | 2 +- tilings/algorithms/subclass_verification.py | 1 - tilings/gui_launcher.py | 1 - tilings/strategies/factor.py | 1 - tilings/strategies/fusion/fusion.py | 1 - tilings/strategies/pointing.py | 1 - tilings/strategies/requirement_placement.py | 1 - tilings/tilescope.py | 2 +- 14 files changed, 16 insertions(+), 14 deletions(-) diff --git a/tests/strategies/test_encoding.py b/tests/strategies/test_encoding.py index ad7923ce..5999a0ef 100644 --- a/tests/strategies/test_encoding.py +++ b/tests/strategies/test_encoding.py @@ -170,7 +170,12 @@ def maxreqlen_extrabasis_ignoreparent_one_cell_only(strategy): ignore_parent=ignore_parent, one_cell_only=one_cell_only, ) - for (maxreqlen, extra_basis, ignore_parent, one_cell_only,) in product( + for ( + maxreqlen, + extra_basis, + ignore_parent, + one_cell_only, + ) in product( (1, 2, 3), (None, [Perm((0, 1))], [Perm((0, 2, 1)), Perm((0, 1, 2))]), (True, False), diff --git a/tests/strategies/test_fusion_strat.py b/tests/strategies/test_fusion_strat.py index bbd9f4a3..3427b045 100644 --- a/tests/strategies/test_fusion_strat.py +++ b/tests/strategies/test_fusion_strat.py @@ -340,7 +340,6 @@ def easy_fusable( def test_fusion_gfs(): - x = var("x") k_0 = var("k_0") k_1 = var("k_1") diff --git a/tests/strategies/test_sanity_check.py b/tests/strategies/test_sanity_check.py index 4b331de1..648c2340 100644 --- a/tests/strategies/test_sanity_check.py +++ b/tests/strategies/test_sanity_check.py @@ -525,7 +525,9 @@ assumptions=(TrackingAssumption((GriddedPerm((0,), ((0, 0),)),)),), ) ), - RequirementInsertionStrategy(gps=(GriddedPerm((0,), ((1, 0),)),),)( + RequirementInsertionStrategy( + gps=(GriddedPerm((0,), ((1, 0),)),), + )( Tiling( obstructions=( GriddedPerm((0, 1), ((0, 0), (0, 0))), diff --git a/tests/test_assumptions.py b/tests/test_assumptions.py index 0b00ca38..7dd37eea 100644 --- a/tests/test_assumptions.py +++ b/tests/test_assumptions.py @@ -77,7 +77,6 @@ def all_tilings( def test_bytes(tplaced, tplaced_tracked, all_tilings): - assert len(tplaced.assumptions) == 0 remade = Tiling.from_bytes(tplaced.to_bytes()) assert tplaced != tplaced_tracked diff --git a/tests/test_griddedperm.py b/tests/test_griddedperm.py index 0d8666db..658ed508 100644 --- a/tests/test_griddedperm.py +++ b/tests/test_griddedperm.py @@ -491,7 +491,10 @@ def test_permute_rows(): Perm((1, 3, 2, 0, 4)), ((0, 1), (0, 2), (0, 1), (1, 0), (2, 2)) ) - assert GriddedPerm((0,), ((0, 0),),).permute_rows((1, 2, 0)) == GriddedPerm( + assert GriddedPerm( + (0,), + ((0, 0),), + ).permute_rows((1, 2, 0)) == GriddedPerm( (0,), ((0, 2),), ) diff --git a/tilings/algorithms/fusion.py b/tilings/algorithms/fusion.py index f5092357..8788f5f9 100644 --- a/tilings/algorithms/fusion.py +++ b/tilings/algorithms/fusion.py @@ -169,7 +169,7 @@ def positive_left_right_requirements( one point, and the right contains at least one point. """ left, right = [], [] - for (x, y) in self._tiling.active_cells: + for x, y in self._tiling.active_cells: if self._fuse_row and y == self._row_idx: left.append(GriddedPerm.single_cell((0,), (x, y))) right.append(GriddedPerm.single_cell((0,), (x, y + 1))) diff --git a/tilings/algorithms/minimal_gridded_perms.py b/tilings/algorithms/minimal_gridded_perms.py index 0d3e87ac..d6df29af 100644 --- a/tilings/algorithms/minimal_gridded_perms.py +++ b/tilings/algorithms/minimal_gridded_perms.py @@ -454,7 +454,7 @@ def _process_work_packet( qpacket: QueuePacket, queue: List[QueuePacket] ) -> Iterator[GriddedPerm]: # now we try inserting a new point into the cell - for (cell, localised) in self._get_cells_to_try(qpacket): + for cell, localised in self._get_cells_to_try(qpacket): # The `localised` bool tells us if we inserted into # a cell as it didn't contain the patterns in the # cell. If not, then we update the last cell, to diff --git a/tilings/algorithms/subclass_verification.py b/tilings/algorithms/subclass_verification.py index c687d178..4d3503e8 100644 --- a/tilings/algorithms/subclass_verification.py +++ b/tilings/algorithms/subclass_verification.py @@ -69,7 +69,6 @@ def subclasses(self) -> Tuple[Perm, ...]: return cast(Tuple[Perm, ...], self._subclasses) def compute_subclasses(self) -> None: - self._subclasses = tuple() perms_to_check = self.quick_pare() diff --git a/tilings/gui_launcher.py b/tilings/gui_launcher.py index 0eb30a7f..8d1df1de 100644 --- a/tilings/gui_launcher.py +++ b/tilings/gui_launcher.py @@ -14,7 +14,6 @@ except ImportError: def _fake_version(_str: str) -> str: - print("=== If you are using older version of python than 3.8 ===") print(f"To use for {sys.executable} you need importlib-metadata.") print(f"{sys.executable} -m pip install importlib-metadata", flush=True) diff --git a/tilings/strategies/factor.py b/tilings/strategies/factor.py index 11c3f4a4..7bb4dc47 100644 --- a/tilings/strategies/factor.py +++ b/tilings/strategies/factor.py @@ -552,7 +552,6 @@ class FactorWithMonotoneInterleavingStrategy(FactorWithInterleavingStrategy): class FactorFactory(StrategyFactory[Tiling]): - FACTOR_ALGO_AND_CLASS = { None: (Factor, FactorStrategy), "monotone": ( diff --git a/tilings/strategies/fusion/fusion.py b/tilings/strategies/fusion/fusion.py index 18644cfd..29ceafe7 100644 --- a/tilings/strategies/fusion/fusion.py +++ b/tilings/strategies/fusion/fusion.py @@ -35,7 +35,6 @@ def is_equivalence( return False def _ensure_level_objects(self, n: int) -> None: - if self.subobjects is None: raise RuntimeError("set_subrecs must be set first") while n >= len(self.objects_cache): diff --git a/tilings/strategies/pointing.py b/tilings/strategies/pointing.py index c9f60a29..4ffa5d0a 100644 --- a/tilings/strategies/pointing.py +++ b/tilings/strategies/pointing.py @@ -387,7 +387,6 @@ def to_jsonable(self) -> dict: @classmethod def from_dict(cls, d: dict) -> "AssumptionPointingFactory": - return cls(**d) diff --git a/tilings/strategies/requirement_placement.py b/tilings/strategies/requirement_placement.py index 27a2aff7..5791c136 100644 --- a/tilings/strategies/requirement_placement.py +++ b/tilings/strategies/requirement_placement.py @@ -680,7 +680,6 @@ def __str__(self) -> str: class AllPlacementsFactory(AbstractRequirementPlacementFactory): - PLACEMENT_STRATS: Tuple[AbstractRequirementPlacementFactory, ...] = ( PatternPlacementFactory(point_only=False), # subreqs=True covers everything but it blows up massively! diff --git a/tilings/tilescope.py b/tilings/tilescope.py index d6b2e174..29b604b8 100644 --- a/tilings/tilescope.py +++ b/tilings/tilescope.py @@ -58,7 +58,6 @@ def __init__( expand_verified: bool = False, debug: bool = False, ) -> None: - """Initialise TileScope.""" if isinstance(start_class, Tiling): start_tiling = start_class @@ -127,6 +126,7 @@ def _rules_from_strategy( # type: ignore Yield all the rules given by a strategy/strategy factory whose children all satisfy the max_assumptions constraint. """ + # pylint: disable=arguments-differ def num_child_assumptions(child: Tiling) -> int: return sum( From 6609d1717055b420fe0764ba7cc7a9c5e10ed4dc Mon Sep 17 00:00:00 2001 From: Jay Pantone Date: Thu, 15 Jan 2026 11:22:11 -0600 Subject: [PATCH 4/6] Pin black==25.1.0 and apply formatting --- tests/algorithms/test_enumeration.py | 17 +++--------- tests/strategies/test_verification.py | 14 ++-------- tilings/algorithms/fusion.py | 1 + tilings/algorithms/requirement_placement.py | 8 +++--- tilings/algorithms/row_col_separation.py | 1 + tilings/algorithms/sliding.py | 28 +++++++++++--------- tilings/bijections.py | 2 +- tilings/misc.py | 1 + tilings/strategies/assumption_insertion.py | 8 +++--- tilings/strategies/assumption_splitting.py | 2 +- tilings/strategies/cell_reduction.py | 1 + tilings/strategies/deflation.py | 1 + tilings/strategies/detect_components.py | 6 ++--- tilings/strategies/factor.py | 2 +- tilings/strategies/fusion/constructor.py | 17 +++++++----- tilings/strategies/pointing.py | 15 ++++++----- tilings/strategies/row_and_col_separation.py | 1 + tilings/strategies/verification.py | 6 ++--- tilings/strategy_pack.py | 4 +-- tox.ini | 2 +- 20 files changed, 69 insertions(+), 68 deletions(-) diff --git a/tests/algorithms/test_enumeration.py b/tests/algorithms/test_enumeration.py index c148e120..18ae7b18 100644 --- a/tests/algorithms/test_enumeration.py +++ b/tests/algorithms/test_enumeration.py @@ -251,10 +251,7 @@ def test_not_verified(self, enum_with_list_req, onebyone_enum, enum_with_crossin def test_get_genf(self, enum_verified): x = sympy.Symbol("x") expected_gf = -( - sympy.sqrt( - -(4 * x**3 - 14 * x**2 + 8 * x - 1) / (2 * x**2 - 4 * x + 1) - ) - - 1 + sympy.sqrt(-(4 * x**3 - 14 * x**2 + 8 * x - 1) / (2 * x**2 - 4 * x + 1)) - 1 ) / (2 * x * (x**2 - 3 * x + 1)) assert sympy.simplify(enum_verified.get_genf() - expected_gf) == 0 t = Tiling( @@ -324,8 +321,7 @@ def test_interleave_fixed_length(self, enum_verified): == 20 * x**11 * dummy_var**3 * cell_var**3 ) assert ( - enum_verified._interleave_fixed_length(F, (1, 0), 0) - == x**8 * dummy_var**3 + enum_verified._interleave_fixed_length(F, (1, 0), 0) == x**8 * dummy_var**3 ) def test_interleave_fixed_lengths(self, enum_verified): @@ -392,14 +388,7 @@ def test_genf_with_big_finite_cell(self): genf = enum.get_genf().expand() x = sympy.var("x") assert ( - genf - == 1 - + 2 * x - + 4 * x**2 - + 8 * x**3 - + 14 * x**4 - + 20 * x**5 - + 20 * x**6 + genf == 1 + 2 * x + 4 * x**2 + 8 * x**3 + 14 * x**4 + 20 * x**5 + 20 * x**6 ) def test_with_two_reqs(self): diff --git a/tests/strategies/test_verification.py b/tests/strategies/test_verification.py index 623d4520..4e207da7 100644 --- a/tests/strategies/test_verification.py +++ b/tests/strategies/test_verification.py @@ -677,10 +677,7 @@ def test_get_specification(self, strategy, enum_verified): def test_get_genf(self, strategy, enum_verified): x = sympy.Symbol("x") expected_gf = -( - sympy.sqrt( - -(4 * x**3 - 14 * x**2 + 8 * x - 1) / (2 * x**2 - 4 * x + 1) - ) - - 1 + sympy.sqrt(-(4 * x**3 - 14 * x**2 + 8 * x - 1) / (2 * x**2 - 4 * x + 1)) - 1 ) / (2 * x * (x**2 - 3 * x + 1)) assert sympy.simplify(strategy.get_genf(enum_verified[0]) - expected_gf) == 0 @@ -758,14 +755,7 @@ def test_genf_with_big_finite_cell(self, strategy): genf = strategy.get_genf(t).expand() x = sympy.var("x") assert ( - genf - == 1 - + 2 * x - + 4 * x**2 - + 8 * x**3 - + 14 * x**4 - + 20 * x**5 - + 20 * x**6 + genf == 1 + 2 * x + 4 * x**2 + 8 * x**3 + 14 * x**4 + 20 * x**5 + 20 * x**6 ) def test_with_two_reqs(self, strategy): diff --git a/tilings/algorithms/fusion.py b/tilings/algorithms/fusion.py index 8788f5f9..038f3304 100644 --- a/tilings/algorithms/fusion.py +++ b/tilings/algorithms/fusion.py @@ -1,6 +1,7 @@ """ The implementation of the fusion algorithm """ + import collections from itertools import chain from typing import ( diff --git a/tilings/algorithms/requirement_placement.py b/tilings/algorithms/requirement_placement.py index a3997518..e5fb85d0 100644 --- a/tilings/algorithms/requirement_placement.py +++ b/tilings/algorithms/requirement_placement.py @@ -153,9 +153,11 @@ def _gridded_perm_translation_with_point( # TODO: to prepare for intervals consider all ways of drawing a # rectangle around point in cell. new_pos = [ - self._point_translation(gp, i, (point_index, gp.patt[point_index])) - if i != point_index - else self._placed_cell(gp.pos[point_index]) + ( + self._point_translation(gp, i, (point_index, gp.patt[point_index])) + if i != point_index + else self._placed_cell(gp.pos[point_index]) + ) for i in range(len(gp)) ] return gp.__class__(gp.patt, new_pos) diff --git a/tilings/algorithms/row_col_separation.py b/tilings/algorithms/row_col_separation.py index bcf2ec43..4c4dc7fe 100644 --- a/tilings/algorithms/row_col_separation.py +++ b/tilings/algorithms/row_col_separation.py @@ -7,6 +7,7 @@ The role of the class `RowColSeparation` is to make sure that row columns separation is idempotent by applying the core algorithm until it stabilises. """ + import heapq from itertools import combinations, product from typing import TYPE_CHECKING, Dict, List, Tuple diff --git a/tilings/algorithms/sliding.py b/tilings/algorithms/sliding.py index 2780e652..d5864f20 100644 --- a/tilings/algorithms/sliding.py +++ b/tilings/algorithms/sliding.py @@ -82,9 +82,11 @@ def slide_assumption( gp.patt, ( ( - c2 - if gp.pos[0][0] == c1 - else (c1 if gp.pos[0][0] == c2 else gp.pos[0][0]), + ( + c2 + if gp.pos[0][0] == c1 + else (c1 if gp.pos[0][0] == c2 else gp.pos[0][0]) + ), 0, ), ), @@ -99,9 +101,11 @@ def slide_assumption( gp.patt, ( ( - c2 - if gp.pos[0][0] == c1 - else (c1 if gp.pos[0][0] == c2 else gp.pos[0][0]), + ( + c2 + if gp.pos[0][0] == c1 + else (c1 if gp.pos[0][0] == c2 else gp.pos[0][0]) + ), 0, ), ), @@ -405,9 +409,11 @@ def _slide_obstructions( # The 12...n obstrudtion that connects av12 and av123 yield GriddedPerm( range(n), - ((av_12, 0),) * (n - 1) + ((av_123, 0),) - if av_12 < av_123 - else ((av_123, 0),) + ((av_12, 0),) * (n - 1), + ( + ((av_12, 0),) * (n - 1) + ((av_123, 0),) + if av_12 < av_123 + else ((av_123, 0),) + ((av_12, 0),) * (n - 1) + ), ) elif gp in self.col_info[av_123][2]: # The one with two points in av_123 are altered so that the two @@ -435,9 +441,7 @@ def _slide_obstructions( yield gp @staticmethod - def _gp_slide_split( - gp: GriddedPerm, c1: int, c2: int - ) -> Tuple[ + def _gp_slide_split(gp: GriddedPerm, c1: int, c2: int) -> Tuple[ Tuple[Deque[int], Deque[int], Deque[int], Deque[int], Deque[int], Deque[int]], Tuple[List[int], List[int], List[int]], ]: diff --git a/tilings/bijections.py b/tilings/bijections.py index 81f08574..21ba7c69 100644 --- a/tilings/bijections.py +++ b/tilings/bijections.py @@ -91,7 +91,7 @@ def _init_assumptions(self) -> Tuple[AssumptionLabels, AssumptionLabels]: @staticmethod def _get_next( - path: Deque[Tuple[AbstractRule, int]] + path: Deque[Tuple[AbstractRule, int]], ) -> Tuple[Rule[Tiling, GriddedPerm], int]: """Get next rule and the index of its child we traverse through.""" r, idx = path.popleft() diff --git a/tilings/misc.py b/tilings/misc.py index 50850a85..5b747a99 100644 --- a/tilings/misc.py +++ b/tilings/misc.py @@ -2,6 +2,7 @@ Collection of function that are not directly related to the code but still useful. """ + from functools import reduce from typing import ( Collection, diff --git a/tilings/strategies/assumption_insertion.py b/tilings/strategies/assumption_insertion.py index 524f69f0..0a4ecd86 100644 --- a/tilings/strategies/assumption_insertion.py +++ b/tilings/strategies/assumption_insertion.py @@ -77,9 +77,11 @@ def _build_child_param_map(self, parent: Tiling, child: Tiling) -> ParametersMap } child_param_to_parent_param = {v: k for k, v in self.extra_parameters.items()} child_pos_to_parent_pos: Tuple[Tuple[int, ...], ...] = tuple( - tuple() - if param in self.new_parameters - else (parent_param_to_pos[child_param_to_parent_param[param]],) + ( + tuple() + if param in self.new_parameters + else (parent_param_to_pos[child_param_to_parent_param[param]],) + ) for param in child.extra_parameters ) return self.build_param_map( diff --git a/tilings/strategies/assumption_splitting.py b/tilings/strategies/assumption_splitting.py index a410f832..52ec4009 100644 --- a/tilings/strategies/assumption_splitting.py +++ b/tilings/strategies/assumption_splitting.py @@ -77,7 +77,7 @@ def compositions_dict(value: int, parameters: Tuple[str, ...]): yield dict(zip(parameters, comp)) def union_params( - sub_params: Tuple[Dict[str, int], ...] + sub_params: Tuple[Dict[str, int], ...], ) -> Optional[Dict[str, int]]: new_params: Dict[str, int] = {} for params in sub_params: diff --git a/tilings/strategies/cell_reduction.py b/tilings/strategies/cell_reduction.py index 9ff68ea9..07fce85e 100644 --- a/tilings/strategies/cell_reduction.py +++ b/tilings/strategies/cell_reduction.py @@ -1,4 +1,5 @@ """The cell reduction strategy.""" + from typing import Callable, Dict, Iterator, List, Optional, Set, Tuple, cast import sympy diff --git a/tilings/strategies/deflation.py b/tilings/strategies/deflation.py index 4a8a2f6a..74473799 100644 --- a/tilings/strategies/deflation.py +++ b/tilings/strategies/deflation.py @@ -1,4 +1,5 @@ """The deflation strategy.""" + from typing import Callable, Dict, Iterator, List, Optional, Tuple, cast import sympy diff --git a/tilings/strategies/detect_components.py b/tilings/strategies/detect_components.py index 4b06d77d..af20a98c 100644 --- a/tilings/strategies/detect_components.py +++ b/tilings/strategies/detect_components.py @@ -163,9 +163,9 @@ def extra_parameters( for assumption in comb_class.assumptions: mapped_assumption = assumption.remove_components(comb_class) if mapped_assumption.gps: - extra_parameters[ - comb_class.get_assumption_parameter(assumption) - ] = child.get_assumption_parameter(mapped_assumption) + extra_parameters[comb_class.get_assumption_parameter(assumption)] = ( + child.get_assumption_parameter(mapped_assumption) + ) return (extra_parameters,) def formal_step(self) -> str: diff --git a/tilings/strategies/factor.py b/tilings/strategies/factor.py index 7bb4dc47..3564905a 100644 --- a/tilings/strategies/factor.py +++ b/tilings/strategies/factor.py @@ -297,7 +297,7 @@ def assumptions_to_add(self, comb_class: Tiling) -> Tuple[TrackingAssumption, .. @staticmethod def interleaving_rows_and_cols( - partition: Tuple[Tuple[Cell, ...], ...] + partition: Tuple[Tuple[Cell, ...], ...], ) -> Tuple[Set[int], Set[int]]: """ Return the set of cols and the set of rows that are being interleaved when diff --git a/tilings/strategies/fusion/constructor.py b/tilings/strategies/fusion/constructor.py index 5cf811de..0f279237 100644 --- a/tilings/strategies/fusion/constructor.py +++ b/tilings/strategies/fusion/constructor.py @@ -13,6 +13,7 @@ We will assume we are always fusing two adjacent columns, and discuss the left and right hand sides accordingly. """ + import enum from collections import Counter, defaultdict from functools import reduce @@ -100,9 +101,11 @@ def __init__( ( "left" if parent_fusion_parameter in self.left_sided_parameters - else "right" - if parent_fusion_parameter in self.right_sided_parameters - else "both" + else ( + "right" + if parent_fusion_parameter in self.right_sided_parameters + else "both" + ) ) for parent_fusion_parameter in self.parent_fusion_parameters ] @@ -506,9 +509,11 @@ def update_subparams( updated_value = ( value + number_of_left_points if parameter in self.right_sided_parameters - else value + number_of_right_points - if parameter in self.left_sided_parameters - else value + else ( + value + number_of_right_points + if parameter in self.left_sided_parameters + else value + ) ) child_parameter = self.extra_parameters[parameter] if child_parameter not in res: diff --git a/tilings/strategies/pointing.py b/tilings/strategies/pointing.py index 4ffa5d0a..641d8e68 100644 --- a/tilings/strategies/pointing.py +++ b/tilings/strategies/pointing.py @@ -2,6 +2,7 @@ The directionless point placement strategy that is counted by the 'pointing' constructor. """ + from collections import Counter from itertools import product from typing import ( @@ -158,9 +159,9 @@ def extra_parameters( ] for ass, mapped_ass in zip(comb_class.assumptions, mapped_assumptions): if mapped_ass.gps: - params[ - comb_class.get_assumption_parameter(ass) - ] = child.get_assumption_parameter(mapped_ass) + params[comb_class.get_assumption_parameter(ass)] = ( + child.get_assumption_parameter(mapped_ass) + ) res.append(params) return tuple(res) @@ -206,9 +207,11 @@ def get_terms( terms = DisjointUnion.get_terms(self, parent_terms, subterms, n) return Counter( { - key: value // (key[self.division_index] + self.shift) - if (key[self.division_index] + self.shift) != 0 - else value + key: ( + value // (key[self.division_index] + self.shift) + if (key[self.division_index] + self.shift) != 0 + else value + ) for key, value in terms.items() } ) diff --git a/tilings/strategies/row_and_col_separation.py b/tilings/strategies/row_and_col_separation.py index 7ac3ce9c..e842f5c4 100644 --- a/tilings/strategies/row_and_col_separation.py +++ b/tilings/strategies/row_and_col_separation.py @@ -2,6 +2,7 @@ The row and column separation strategy. The details of the algorithm can be found in the algorithms folder. """ + from typing import Dict, Iterator, Optional, Tuple from comb_spec_searcher import DisjointUnionStrategy diff --git a/tilings/strategies/verification.py b/tilings/strategies/verification.py index 9488d7f3..87d433b4 100644 --- a/tilings/strategies/verification.py +++ b/tilings/strategies/verification.py @@ -118,9 +118,9 @@ def get_genf( gp = next(comb_class.minimal_gridded_perms()) expected = {"x": len(gp)} for assumption in comb_class.assumptions: - expected[ - comb_class.get_assumption_parameter(assumption) - ] = assumption.get_value(gp) + expected[comb_class.get_assumption_parameter(assumption)] = ( + assumption.get_value(gp) + ) return reduce(mul, [var(k) ** n for k, n in expected.items()], 1) def __repr__(self) -> str: diff --git a/tilings/strategy_pack.py b/tilings/strategy_pack.py index de7f9e91..7208a0f9 100644 --- a/tilings/strategy_pack.py +++ b/tilings/strategy_pack.py @@ -33,7 +33,7 @@ def add_basis(self, basis: Iterable[Perm]) -> "TileScopePack": symmetry = bool(self.symmetries) def replace_list( - strats: Tuple[Union[AbstractStrategy, StrategyFactory], ...] + strats: Tuple[Union[AbstractStrategy, StrategyFactory], ...], ) -> List[Union[AbstractStrategy, StrategyFactory]]: """Return a new list with the replaced 1x1 strat.""" res: List[Union[AbstractStrategy, StrategyFactory]] = [] @@ -74,7 +74,7 @@ def setup_subclass_verification(self, start_tiling: "Tiling") -> "TileScopePack" """ def replace_list( - strats: Tuple[Union[AbstractStrategy, StrategyFactory], ...] + strats: Tuple[Union[AbstractStrategy, StrategyFactory], ...], ) -> List[Union[AbstractStrategy, StrategyFactory]]: """ Find subclass verification and alter its perms_to_check variable. diff --git a/tox.ini b/tox.ini index 4767d49b..fef35663 100644 --- a/tox.ini +++ b/tox.ini @@ -65,5 +65,5 @@ commands = mypy description = check that comply with autoformating basepython = {[default]basepython} deps = - black>=22.10.0 + black==25.12.0 commands = black --check --diff . From 83820936d034b5ea4caaf924209c687ec83d2560 Mon Sep 17 00:00:00 2001 From: Jay Pantone Date: Thu, 15 Jan 2026 11:40:52 -0600 Subject: [PATCH 5/6] Add Python 3.14 testing as main version --- .github/workflows/test.yml | 19 +++++++++++-------- tox.ini | 5 +++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6cb17579..4963c6d0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,16 +9,16 @@ jobs: fail-fast: false matrix: include: - - python: "3.13" + - python: "3.14" toxenv: flake8 os: ubuntu-latest - - python: "3.13" + - python: "3.14" toxenv: mypy os: ubuntu-latest - - python: "3.13" + - python: "3.14" toxenv: pylint os: ubuntu-latest - - python: "3.13" + - python: "3.14" toxenv: black os: ubuntu-latest @@ -34,6 +34,9 @@ jobs: - python: "3.13" toxenv: py313 os: ubuntu-latest + - python: "3.14" + toxenv: py314 + os: ubuntu-latest - python: "pypy-3.10" toxenv: pypy310 @@ -42,11 +45,11 @@ jobs: toxenv: pypy311 os: ubuntu-latest - - python: "3.13" - toxenv: py313 + - python: "3.14" + toxenv: py314 os: macos-latest - - python: "3.13" - toxenv: py313 + - python: "3.14" + toxenv: py314 os: windows-latest runs-on: ${{ matrix.os }} diff --git a/tox.ini b/tox.ini index fef35663..0aba2056 100644 --- a/tox.ini +++ b/tox.ini @@ -6,11 +6,11 @@ [tox] envlist = flake8, mypy, pylint, black - py{310,311,312,313}, + py{310,311,312,313,314}, pypy{310,311} [default] -basepython=python3.13 +basepython=python3.14 [testenv] description = run test @@ -19,6 +19,7 @@ basepython = py311: python3.11 py312: python3.12 py313: python3.13 + py314: python3.14 pypy310: pypy3.10 pypy311: pypy3.11 deps = From 3ad62b97df3f1e2468ac4f35cd03870d9fefe475 Mon Sep 17 00:00:00 2001 From: Jay Pantone Date: Thu, 15 Jan 2026 12:27:01 -0600 Subject: [PATCH 6/6] update deploy to py314 --- .github/workflows/build-and-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index d5060808..faccd5cc 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: "3.13" + python-version: "3.14" - name: install dependencies run: | python -m pip install --upgrade pip