Skip to content

Commit 703edd6

Browse files
Technologicatclaude
andcommitted
Phase 2: bump floor to Python 3.10, version to 2.0.0
Drop Python 3.8/3.9 support. Remove all dead version guards (18 sites): ast.Index wrappers (3.9), posonlyargs hasattr checks (3.8), CodeType positional construction (3.8), types.UnionType guard (3.10). Include posonlyargs directly in arguments() constructors. Remove walrus-inside-subscript parens (now 3.10+). Update TODO comments: parenthesis syntax for macro arguments is now deprecated; kept for backward compatibility. Update metadata: requires-python >=3.10,<3.15, mcpyrate dev dep, classifiers (drop 3.8/3.9, add 3.13/3.14, Production/Stable). CI matrix: 3.10–3.14 + pypy-3.11. Coverage on 3.12. Update CLAUDE.md, README.md, CONTRIBUTING.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent dd1b926 commit 703edd6

22 files changed

Lines changed: 52 additions & 145 deletions

.github/workflows/coverage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
runs-on: ubuntu-latest
1616
strategy:
1717
matrix:
18-
python-version: ["3.10"]
18+
python-version: ["3.12"]
1919

2020
steps:
2121
- uses: actions/checkout@v6

.github/workflows/python-package.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
runs-on: ubuntu-latest
1818
strategy:
1919
matrix:
20-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", pypy-3.8, pypy-3.9, pypy-3.10]
20+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "pypy-3.11"]
2121

2222
steps:
2323
- uses: actions/checkout@v6

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ A Python library providing language extensions and utilities inspired by Lisp, H
1212

1313
## API stability
1414

15-
Released as 1.0.0 in February 2026, signalling API stability. The public API (everything in `__all__`) should remain backward-compatible. If backward-incompatible changes become necessary (e.g. due to Python 3.13/3.14 compat), they warrant a 2.0.0 release. Prefer non-breaking solutions when possible.
15+
Released as 2.0.0 in March 2026 (floor bump + mcpyrate 4.0.0 dependency). The public API (everything in `__all__`) should remain backward-compatible. Prefer non-breaking solutions when possible.
1616

1717
## Build and development
1818

19-
Uses PDM with `pdm-backend`. Python 3.8–3.12, also PyPy 3.8–3.10. Version 3.13/3.14 compatibility update pending (will be released as 1.1.0).
19+
Uses PDM with `pdm-backend`. Python 3.10–3.14, also PyPy 3.11.
2020

2121
```bash
2222
# Set up development environment

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ The `lazify` and `continuations` macros are the most complex (and perhaps fearso
118118

119119
`unpythonic.syntax.scopeanalyzer` is a unfortunate artifact that is needed to implement macros that interact with Python's scoping rules, notably `let`. Fortunately, [the language reference explicitly documents](https://docs.python.org/3/reference/executionmodel.html#naming-and-binding) what is needed for a lexical scope analysis for Python. So we have just implemented that (better, as an AST analysis, rather than scanning the surface syntax text).
120120

121-
As of the first half of 2021, the main target platforms are **CPython 3.8** and **PyPy3 3.7** (since as of April 2021, PyPy3 does not have 3.8 yet). The code should run on 3.6 or any later Python. We have [a GitHub workflow](https://github.com/Technologicat/unpythonic/actions?query=workflow%3A%22Python+package%22) that runs the test suite on CPython 3.6 through 3.9, and on PyPy3.
121+
As of v2.0.0, the main target platforms are **CPython 3.10** through **3.14**, and **PyPy3** (language version 3.11). We have [a GitHub workflow](https://github.com/Technologicat/unpythonic/actions?query=workflow%3A%22Python+package%22) that runs the test suite on these platforms.
122122

123123

124124
## Style guide

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ None required.
1717

1818
- [`mcpyrate`](https://github.com/Technologicat/mcpyrate) optional, to enable the syntactic macro layer, an interactive macro REPL, and some example dialects.
1919

20-
As of v0.15.3, `unpythonic` runs on CPython 3.8, 3.9 and 3.10, 3.11, 3.12, and PyPy3 (language versions 3.8, 3.9, 3.10); the [CI](https://en.wikipedia.org/wiki/Continuous_integration) process verifies the tests pass on those platforms. New Python versions are added and old ones are removed following the [Long-term support roadmap](https://github.com/Technologicat/unpythonic/issues/1).
20+
As of v2.0.0, `unpythonic` runs on CPython 3.10, 3.11, 3.12, 3.13, 3.14, and PyPy3 (language version 3.11); the [CI](https://en.wikipedia.org/wiki/Continuous_integration) process verifies the tests pass on those platforms. New Python versions are added and old ones are removed following the [Long-term support roadmap](https://github.com/Technologicat/unpythonic/issues/1).
2121

2222

2323
### Documentation

pyproject.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = "Supercharge your Python with parts of Lisp and Haskell."
44
authors = [
55
{ name = "Juha Jeronen", email = "juha.m.jeronen@gmail.com" },
66
]
7-
requires-python = ">=3.8,<3.13"
7+
requires-python = ">=3.10,<3.15"
88

99
# the `read` function and long_description_content_type from setup.py are no longer needed,
1010
# modern build tools like pdm/hatch already know how to handle markdown if you point them at a .md file
@@ -19,25 +19,25 @@ license = { text = "BSD" }
1919
dynamic = ["version"]
2020

2121
dependencies = [
22-
"mcpyrate>=3.6.4",
22+
"mcpyrate @ file:///home/jje/Documents/koodit/mcpyrate",
2323
"sympy>=1.13"
2424
]
2525
keywords=["functional-programming", "language-extension", "syntactic-macros",
2626
"tail-call-optimization", "tco", "continuations", "currying", "lazy-evaluation",
2727
"dynamic-variable", "macros", "lisp", "scheme", "racket", "haskell"]
2828
classifiers = [
29-
"Development Status :: 4 - Beta",
29+
"Development Status :: 5 - Production/Stable",
3030
"Environment :: Console",
3131
"Intended Audience :: Developers",
3232
"License :: OSI Approved :: BSD License",
3333
"Operating System :: POSIX :: Linux",
3434
"Programming Language :: Python",
3535
"Programming Language :: Python :: 3",
36-
"Programming Language :: Python :: 3.8",
37-
"Programming Language :: Python :: 3.9",
3836
"Programming Language :: Python :: 3.10",
3937
"Programming Language :: Python :: 3.11",
4038
"Programming Language :: Python :: 3.12",
39+
"Programming Language :: Python :: 3.13",
40+
"Programming Language :: Python :: 3.14",
4141
"Programming Language :: Python :: Implementation :: CPython",
4242
"Programming Language :: Python :: Implementation :: PyPy",
4343
"Topic :: Software Development :: Libraries",

unpythonic/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
for a trip down the rabbit hole.
88
"""
99

10-
__version__ = '1.0.1'
10+
__version__ = '2.0.0'
1111

1212
from .amb import * # noqa: F401, F403
1313
from .arity import * # noqa: F401, F403

unpythonic/misc.py

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
from itertools import count
1616
import inspect
1717
from queue import Empty
18-
from sys import version_info
1918
from time import monotonic
20-
from types import CodeType, FunctionType, LambdaType
19+
from types import FunctionType, LambdaType
2120

2221
from .regutil import register_decorator
2322

@@ -98,27 +97,7 @@ def rename(f):
9897
f.__name__ = name
9998
idx = f.__qualname__.rfind('.')
10099
f.__qualname__ = f"{f.__qualname__[:idx]}.{name}" if idx != -1 else name
101-
# __code__.co_name is read-only, but there's a types.CodeType constructor
102-
# that we can use to re-create the code object with the new name.
103-
# (This is no worse than what the stdlib's Lib/modulefinder.py already does.)
104-
co = f.__code__
105-
# https://github.com/ipython/ipython/blob/master/IPython/core/interactiveshell.py
106-
# https://www.python.org/dev/peps/pep-0570/
107-
# https://docs.python.org/3/library/types.html#types.CodeType
108-
# https://docs.python.org/3/library/inspect.html#types-and-members
109-
if version_info >= (3, 8, 0): # Python 3.8+: positional-only parameters
110-
# In Python 3.8+, `CodeType` has the convenient `replace()` method to functionally update it.
111-
# In Python 3.10, we must actually use it to avoid losing the line number info,
112-
# or `inspect.stack()` will crash in the unit tests for `callsite_filename()`.
113-
f.__code__ = f.__code__.replace(co_name=name)
114-
else:
115-
f.__code__ = CodeType(co.co_argcount, co.co_kwonlyargcount,
116-
co.co_nlocals, co.co_stacksize, co.co_flags,
117-
co.co_code, co.co_consts, co.co_names,
118-
co.co_varnames, co.co_filename,
119-
name,
120-
co.co_firstlineno, co.co_lnotab, co.co_freevars,
121-
co.co_cellvars)
100+
f.__code__ = f.__code__.replace(co_name=name)
122101
return f
123102
return rename
124103

unpythonic/syntax/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@
8181

8282
# TODO: 0.16: AST pattern matching for `mcpyrate`? Would make destructuring easier. A writable representation (auto-viewify) is a pain to build, though...
8383

84-
# TODO: Far future: Change decorator macro invocations to use [] instead of () to pass macro arguments. Requires Python 3.9, so the earliest time to do this is when 3.9 becomes the minimum Python version for `unpythonic`.
84+
# Parenthesis syntax for decorator macro arguments is deprecated; bracket syntax is preferred.
85+
# Parenthesis syntax is kept for backward compatibility.
8586

8687
from .autocurry import * # noqa: F401, F403
8788
from .autoref import * # noqa: F401, F403

unpythonic/syntax/lambdatools.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,10 +451,7 @@ def _envify(block_body):
451451
# second pass, inside-out
452452
def getargs(tree): # tree: FunctionDef, AsyncFunctionDef, Lambda
453453
a = tree.args
454-
if hasattr(a, "posonlyargs"): # Python 3.8+: positional-only parameters
455-
allargs = a.posonlyargs + a.args + a.kwonlyargs
456-
else:
457-
allargs = a.args + a.kwonlyargs
454+
allargs = a.posonlyargs + a.args + a.kwonlyargs
458455
argnames = [x.arg for x in allargs]
459456
if a.vararg:
460457
argnames.append(a.vararg.arg)

0 commit comments

Comments
 (0)