A tool to convert modern Python code to less modern Python versions
Project description
retrofy
A tool which takes modern Python typing code, and makes it compatible with older Python versions.
The idea is to be able to maintain the modern typing in your repository, and then as part of the build stage, convert the code to the older form. You should continue to test your project against older versions (e.g. in CI) for full confidence in the compatibility.
Build-time transformation
retrofy includes the ability to customise the build to
transform Python files into the compatibility form when creating a wheel
using any PEP-517 build backend. This includes support for editable installs
(PEP-660), which transforms the code at import-time using standard import hook
machinery.
To setup a build-time conversion, add the multistage_build backend within
pyproject.toml, for example:
[build-system]
requires = ["multistage-build", "setuptools", "wheel", "setuptools_scm==7.*", "retrofy"]
build-backend = "multistage_build:backend"
[tool.multistage-build]
build-backend = "setuptools.build_meta"
Python compatibility
retrofy can be used with Python 3.9+, and can produce code (and wheels) which are
compatible with Python 3.7.
It is imperative that you test the produced wheels with the target versions, as there
may be syntax which is not yet handled in retrofy, resulting in a SyntaxError on your
desired Python version.
Available transformations
For all transformations, necessary imports (typing, collections.abc, etc.) will be injected where necessary
and appropriate.
-
A | B->typing.Union[A, B] -
PEP-572 - walrus operator
-
PEP-636 - match statements (structural pattern matching):
- Literal patterns:
case 42:->if value == 42: - Variable binding:
case x:->x = value - Sequence patterns:
case [x, y]:->if isinstance(value, collections.abc.Sequence) and not isinstance(value, str) and len(value) == 2: x, y = value - Mapping patterns:
case {"key": value}:->if isinstance(value, dict) and "key" in value: value = value["key"] - Class patterns:
case Point(x=0, y=y):->if isinstance(value, Point) and value.x == 0: y = value.y - Guard clauses:
case x if x > 0:->if x > 0: x = value - OR patterns:
case 1 | 2:->if value in (1, 2): - Wildcard patterns:
case _:->else: - Star patterns:
case [x, *rest]:->if len(value) >= 1: x = value[0]; rest = value[1:] - As patterns:
case [x, y] as point:->if len(value) == 2: point = value; x, y = value - Complex nested patterns with full recursive support
- Literal patterns:
-
PEP-695 - type statements, generic classes, and generic functions:
- Type statements:
type Point = tuple[float, float]->Point = tuple[float, float]type GenericPoint[T] = tuple[T, T]->T = typing.TypeVar("T"); GenericPoint: typing.TypeAlias = tuple[T, T]type BoundedPoint[T: int] = tuple[T, T]->T = typing.TypeVar("T", bound=int); BoundedPoint: typing.TypeAlias = tuple[T, T]
- Generic classes:
class ClassA[T]: ...->from typing import Generic, TypeVar; T = TypeVar("T"); class ClassA(Generic[T]): ...class ClassA[T: str]: ...->T = TypeVar("T", bound=str); class ClassA(Generic[T]): ...
- Generic functions:
def func[T](a: T) -> T: ...->T = typing.TypeVar("T"); def func(a: T) -> T: ...def func[T: str](a: T) -> T: ...->T = typing.TypeVar("T", bound=str); def func(a: T) -> T: ...
- Type statements:
-
dataclasses - the match_args attribute is added to the class (necessary for match statement support)
Transformations not yet implemented
A | None->typing.Optional[A]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file retrofy-0.2.1.tar.gz.
File metadata
- Download URL: retrofy-0.2.1.tar.gz
- Upload date:
- Size: 49.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e54a3191cc226a1dc68acf25743fadeacb9277663280970639ae23ab884921ee
|
|
| MD5 |
5d3511dc374121c37e0fa0f1a2d70bab
|
|
| BLAKE2b-256 |
0f59f3ff635eb8930db9a7c290ca9cb359d5dacaf414db20d69801214ab28b27
|
Provenance
The following attestation bundles were made for retrofy-0.2.1.tar.gz:
Publisher:
python-publish.yml on pelson/retrofy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
retrofy-0.2.1.tar.gz -
Subject digest:
e54a3191cc226a1dc68acf25743fadeacb9277663280970639ae23ab884921ee - Sigstore transparency entry: 397145556
- Sigstore integration time:
-
Permalink:
pelson/retrofy@ca9ccea33fd1d301fd39a5df30a0d6d8cbbc566c -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/pelson
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@ca9ccea33fd1d301fd39a5df30a0d6d8cbbc566c -
Trigger Event:
release
-
Statement type:
File details
Details for the file retrofy-0.2.1-py3-none-any.whl.
File metadata
- Download URL: retrofy-0.2.1-py3-none-any.whl
- Upload date:
- Size: 45.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d10ebbcebae557179e201df4f1d7b15c9e8c05ae132f2634308f65e877fd4786
|
|
| MD5 |
9511810620f936f1d2fcbbce7ddbdcbe
|
|
| BLAKE2b-256 |
0a92d04b0a87993f078d224dfcc2710a52bfa87c8e9b317b720a49dc5051e6cd
|
Provenance
The following attestation bundles were made for retrofy-0.2.1-py3-none-any.whl:
Publisher:
python-publish.yml on pelson/retrofy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
retrofy-0.2.1-py3-none-any.whl -
Subject digest:
d10ebbcebae557179e201df4f1d7b15c9e8c05ae132f2634308f65e877fd4786 - Sigstore transparency entry: 397145575
- Sigstore integration time:
-
Permalink:
pelson/retrofy@ca9ccea33fd1d301fd39a5df30a0d6d8cbbc566c -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/pelson
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@ca9ccea33fd1d301fd39a5df30a0d6d8cbbc566c -
Trigger Event:
release
-
Statement type: