Skip to content

Commit

Permalink
Drop support for Python 3.8.
Browse files Browse the repository at this point in the history
This also adds the recently released Python 3.13 to CI.
  • Loading branch information
whitequark committed Oct 9, 2024
1 parent 41762f1 commit b6bf515
Show file tree
Hide file tree
Showing 10 changed files with 19 additions and 40 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,17 @@ jobs:
strategy:
matrix:
python-version:
- '3.8'
- '3.9'
- '3.10'
- '3.11'
- '3.12'
- 'pypy-3.8'
- '3.13'
- 'pypy-3.9'
- 'pypy-3.10'
allow-failure:
- false
include:
- python-version: '3.13-dev'
- python-version: '3.14-dev'
allow-failure: true
continue-on-error: ${{ matrix.allow-failure }}
name: 'test (${{ matrix.python-version }})'
Expand Down
21 changes: 6 additions & 15 deletions amaranth/_toolchain/yosys.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,8 @@
import subprocess
import warnings
import pathlib
from importlib import metadata as importlib_metadata
try:
from importlib import resources as importlib_resources
try:
importlib_resources.files # py3.9+ stdlib
except AttributeError:
import importlib_resources # py3.8- shim
except ImportError:
importlib_resources = None
import importlib.metadata
import importlib.resources

from . import has_tool, require_tool

Expand Down Expand Up @@ -109,23 +102,21 @@ class _BuiltinYosys(YosysBinary):

@classmethod
def available(cls):
if importlib_metadata is None or importlib_resources is None:
return False
try:
importlib_metadata.version(cls.YOSYS_PACKAGE)
importlib.metadata.version(cls.YOSYS_PACKAGE)
return True
except importlib_metadata.PackageNotFoundError:
except importlib.metadata.PackageNotFoundError:
return False

@classmethod
def version(cls):
version = importlib_metadata.version(cls.YOSYS_PACKAGE)
version = importlib.metadata.version(cls.YOSYS_PACKAGE)
match = re.match(r"^(\d+)\.(\d+)\.(?:\d+)(?:\.(\d+))?(?:\.post(\d+))?", version)
return (int(match[1]), int(match[2]), int(match[3] or 0), int(match[4] or 0))

@classmethod
def data_dir(cls):
return importlib_resources.files(cls.YOSYS_PACKAGE) / "share"
return importlib.resources.files(cls.YOSYS_PACKAGE) / "share"

@classmethod
def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
Expand Down
2 changes: 1 addition & 1 deletion amaranth/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Iterable
from collections.abc import Iterable
from contextlib import contextmanager
import io

Expand Down
6 changes: 2 additions & 4 deletions amaranth/build/res.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,7 @@ def add_clock_constraint(self, clock, period=None, frequency=None):
clocks[clock] = frequency

def iter_signal_clock_constraints(self):
for signal, frequency in self._clocks.items():
yield signal, frequency
yield from self._clocks.items()

def iter_port_clock_constraints(self):
for port, frequency in self._io_clocks.items():
yield port, frequency
yield from self._io_clocks.items()
4 changes: 2 additions & 2 deletions amaranth/hdl/_ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ def __init__(self, netlist: _nir.Netlist, design: Design, *, all_undef_to_ff=Fal
# SignalDict from Signal to dict from (module index, ClockDomain | None) to NetlistDriver
self.drivers = _ast.SignalDict()
self.io_ports: dict[_ast.IOPort, int] = {}
self.rhs_cache: dict[int, Tuple[_nir.Value, bool, _ast.Value]] = {}
self.rhs_cache: dict[int, tuple[_nir.Value, bool, _ast.Value]] = {}
self.matches_cache = {}
self.priority_match_cache = {}
self.fragment_module_idx: dict[Fragment, int] = {}
Expand Down Expand Up @@ -817,7 +817,7 @@ def unify_shapes_bitwise(self,
operand_b = self.extend(operand_b, signed_b, shape.width)
return (operand_a, operand_b, shape.signed)

def emit_rhs(self, module_idx: int, value: _ast.Value) -> Tuple[_nir.Value, bool]:
def emit_rhs(self, module_idx: int, value: _ast.Value) -> tuple[_nir.Value, bool]:
"""Emits a RHS value, returns a tuple of (value, is_signed)"""
try:
result, signed, value = self.rhs_cache[id(value)]
Expand Down
3 changes: 2 additions & 1 deletion amaranth/hdl/_nir.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Iterable, Any
from typing import Any
from collections.abc import Iterable
import enum

from ._ast import SignalDict
Expand Down
5 changes: 0 additions & 5 deletions amaranth/lib/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ class EnumType(ShapeCastable, py_enum.EnumMeta):
can be specified by passing the ``view_class=`` keyword argument when creating the enum class.
"""

# TODO: remove this shim once py3.8 support is dropped
@classmethod
def __prepare__(metacls, name, bases, shape=None, view_class=None, **kwargs):
return super().__prepare__(name, bases, **kwargs)

def __new__(metacls, name, bases, namespace, shape=None, view_class=None, **kwargs):
if shape is not None:
shape = Shape.cast(shape)
Expand Down
2 changes: 1 addition & 1 deletion amaranth/lib/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,6 @@ def _extract_schemas(package, *, base_uri, path="schema/"):
f"Schema $id {schema['$id']} must be {base_uri}/{relative_path}"

schema_filename.parent.mkdir(parents=True, exist_ok=True)
with open(pathlib.Path(path) / relative_path, "wt") as schema_file:
with open(pathlib.Path(path) / relative_path, "w") as schema_file:
json.dump(schema, schema_file, indent=2)
print(f"Extracted {schema['$id']} to {schema_filename}")
4 changes: 2 additions & 2 deletions docs/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ System requirements
.. |yosys-version| replace:: 0.40 (or newer)

Amaranth HDL requires Python 3.8; it works on CPython_ 3.8 (or newer), and works faster on PyPy3.8_ 7.3.7 (or newer). Installation requires pip_ 23.0 (or newer).
Amaranth HDL requires Python 3.9; it works on CPython_ 3.9 (or newer), and works faster on PyPy3.9_ 7.3.7 (or newer). Installation requires pip_ 23.0 (or newer).

For most workflows, Amaranth requires Yosys_ |yosys-version|. A `compatible version of Yosys <amaranth-yosys_>`_ is distributed via PyPI_ for most popular platforms, so it is usually not necessary to install Yosys separately.

Expand All @@ -34,7 +34,7 @@ Synthesizing, placing and routing an Amaranth design for an FPGA requires the FP
.. TODO: Link to FPGA family docs here
.. _CPython: https://www.python.org/
.. _PyPy3.8: https://www.pypy.org/
.. _PyPy3.9: https://www.pypy.org/
.. _pip: https://pip.pypa.io/en/stable/
.. _Yosys: https://yosyshq.net/yosys/
.. _amaranth-yosys: https://pypi.org/project/amaranth-yosys/
Expand Down
7 changes: 1 addition & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ readme = "README.md"
authors = [{name = "Amaranth HDL contributors"}]
license = { text = "BSD-2-clause" }

requires-python = "~=3.8"
requires-python = "~=3.9"
dependencies = [
"importlib_resources; python_version<'3.9'", # for amaranth._toolchain.yosys
"jschon~=0.11.1", # for amaranth.lib.meta
"pyvcd>=0.2.2,<0.5", # for amaranth.sim.pysim
"Jinja2~=3.0", # for amaranth.build
Expand Down Expand Up @@ -47,10 +46,6 @@ amaranth-rpc = "amaranth.rpc:main"
requires = ["pdm-backend~=2.3.0"]
build-backend = "pdm.backend"

[tool.pdm]
# Remove this once we no longer support Python 3.8.
ignore_package_warnings = ["sphinx*", "alabaster"]

[tool.pdm.build]
# If amaranth 0.3 is checked out with git (e.g. as a part of a persistent editable install or
# a git worktree cached by tools like poetry), it can have an empty `nmigen` directory left over,
Expand Down

0 comments on commit b6bf515

Please sign in to comment.