From 2cb0d53e2141519b6e10d4511475b9a8bf9a606c Mon Sep 17 00:00:00 2001 From: Chris Rink Date: Tue, 28 Oct 2025 21:33:19 -0400 Subject: [PATCH 1/4] Add support for 3.14; drop support for 3.9 --- .github/workflows/run-tests.yml | 14 ++++++----- CHANGELOG.md | 5 ++++ README.md | 2 +- pyproject.toml | 5 ++-- src/basilisp/lang/runtime.py | 2 +- tests/basilisp/runtime_test.py | 42 ++++++++++++++++----------------- tox.ini | 14 +++++------ 7 files changed, 45 insertions(+), 39 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 51746939..112350de 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - version: ['3.9', '3.10', '3.11', '3.12', '3.13.0'] + version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14'] include: - version: '3.9' tox-env: py39,py39-mypy,py39-lint,bandit @@ -25,14 +25,16 @@ jobs: - version: '3.11' tox-env: py311,py311-mypy,py311-lint,bandit - version: '3.12' - tox-env: py312,py312-mypy,py312-lint,format,bandit - - version: '3.13.0' + tox-env: py312,py312-mypy,py312-lint,bandit + - version: '3.13' tox-env: py313,py313-mypy,py313-lint,bandit + - version: '3.14' + tox-env: py314,py314-mypy,py314-lint,bandit,format - os: windows-latest - version: '3.13' - tox-env: py313,bandit + version: '3.14' + tox-env: py314,bandit - os: macos-latest - version: '3.13' + version: '3.14' tox-env: py313,bandit steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 092d9c10..2af0eeee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + * Added support for Python 3.14 (#1282) + +### Removed + * Removed support for Python 3.9 (#1283) ## [v0.4.0] ### Added diff --git a/README.md b/README.md index dd852c6a..c4dfd162 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🐍 basilisp 🐍 -A Clojure-compatible(-ish) Lisp dialect targeting Python 3.9+. +A Clojure-compatible(-ish) Lisp dialect targeting Python 3.10+. [![PyPI](https://img.shields.io/pypi/v/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![python](https://img.shields.io/pypi/pyversions/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![pyimpl](https://img.shields.io/pypi/implementation/basilisp.svg?style=flat-square)](https://pypi.org/project/basilisp/) [![readthedocs](https://img.shields.io/readthedocs/basilisp.svg?style=flat-square)](https://basilisp.readthedocs.io/) [![Run tests](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml/badge.svg?branch=main)](https://github.com/basilisp-lang/basilisp/actions/workflows/run-tests.yml) [![Coveralls github](https://img.shields.io/coveralls/github/basilisp-lang/basilisp.svg?style=flat-square)](https://coveralls.io/github/basilisp-lang/basilisp) [![license](https://img.shields.io/github/license/basilisp-lang/basilisp.svg?style=flat-square)](https://github.com/basilisp-lang/basilisp/blob/master/LICENSE) diff --git a/pyproject.toml b/pyproject.toml index 983e902b..97ccfa2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,11 +18,11 @@ classifiers = [ "License :: OSI Approved :: Eclipse Public License 1.0 (EPL-1.0)", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Compilers", @@ -30,7 +30,7 @@ classifiers = [ include = ["README.md", "LICENSE"] [tool.poetry.dependencies] -python = "^3.9" +python = "^3.10" attrs = ">=22.2.0" immutables = ">=0.20,<1.0.0" prompt-toolkit = ">=3.0.0,<4.0.0" @@ -236,7 +236,6 @@ warn_unused_ignores = true [[tool.mypy.overrides]] module = [ - "astor.*", "prompt_toolkit.*", "pygments.*", "pytest.*", diff --git a/src/basilisp/lang/runtime.py b/src/basilisp/lang/runtime.py index ea629fc3..773e33ac 100644 --- a/src/basilisp/lang/runtime.py +++ b/src/basilisp/lang/runtime.py @@ -68,7 +68,7 @@ IMPORT_MODULE_VAR_SYM = sym.symbol(IMPORT_MODULE_VAR_NAME, ns=CORE_NS) NS_VAR_NS = CORE_NS REPL_DEFAULT_NS = "basilisp.user" -SUPPORTED_PYTHON_VERSIONS = frozenset({(3, 9), (3, 10), (3, 11), (3, 12), (3, 13)}) +SUPPORTED_PYTHON_VERSIONS = frozenset({(3, 10), (3, 11), (3, 12), (3, 13), (3, 14)}) BASILISP_VERSION_STRING = importlib.metadata.version("basilisp") BASILISP_VERSION = vec.vector( (int(s) if s.isdigit() else s) for s in BASILISP_VERSION_STRING.split(".") diff --git a/tests/basilisp/runtime_test.py b/tests/basilisp/runtime_test.py index 2c3d766e..2ae855fe 100644 --- a/tests/basilisp/runtime_test.py +++ b/tests/basilisp/runtime_test.py @@ -30,23 +30,6 @@ def test_is_supported_python_version(): @pytest.mark.parametrize( "feature", { - (3, 9): frozenset( - map( - kw.keyword, - [ - "lpy39", - "default", - "lpy", - "lpy39-", - "lpy39+", - "lpy310-", - "lpy311-", - "lpy312-", - "lpy313-", - platform.system().lower(), - ], - ) - ), (3, 10): frozenset( map( kw.keyword, @@ -59,7 +42,7 @@ def test_is_supported_python_version(): "lpy311-", "lpy310+", "lpy310-", - "lpy39+", + "lpy314-", platform.system().lower(), ], ) @@ -76,7 +59,7 @@ def test_is_supported_python_version(): "lpy312-", "lpy311-", "lpy310+", - "lpy39+", + "lpy314-", platform.system().lower(), ], ) @@ -92,7 +75,7 @@ def test_is_supported_python_version(): "lpy312+", "lpy313-", "lpy312-", - "lpy39+", + "lpy314-", platform.system().lower(), ], ) @@ -109,7 +92,24 @@ def test_is_supported_python_version(): "lpy313+", "lpy313-", "lpy310+", - "lpy39+", + "lpy314-", + platform.system().lower(), + ], + ) + ), + (3, 14): frozenset( + map( + kw.keyword, + [ + "lpy314", + "default", + "lpy", + "lpy310+", + "lpy311+", + "lpy312+", + "lpy313+", + "lpy314-", + "lpy314+", platform.system().lower(), ], ) diff --git a/tox.ini b/tox.ini index 9e6e2014..6277d89d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] -envlist = py39,py310,py311,py312,py313,pypy3,coverage,py{39,310,311,312,313}-mypy,py{39,310,311,312,313}-lint,format,bandit +envlist = py310,py311,py312,py313,pypy3,coverage,py{310,311,312,313,314}-mypy,py{310,311,312,313,314}-lint,format,bandit labels = - test = py39,py310,py311,py312,py313 + test = py310,py311,py312,py313,py314 [testenv] allowlist_externals = poetry @@ -25,7 +25,7 @@ commands = {posargs} [testenv:coverage] -depends = py39, py310, py311, py312, py313 +depends = py310, py311, py312, py313, py314 deps = coverage[toml] commands = coverage combine @@ -40,7 +40,7 @@ commands = isort --check . black --check . -[testenv:py{39,310,311,312,313}-mypy] +[testenv:py{310,311,312,313,314}-mypy] labels = mypy deps = mypy @@ -49,11 +49,11 @@ deps = commands = mypy --config-file={toxinidir}/pyproject.toml -p basilisp -[testenv:py{39,310,311,312,313}-lint] +[testenv:py{310,311,312,313,314}-lint] labels = lint deps = - pylint >=3.0.0,<4.0.0 - pytest >=7.0.0,<8.0.0 + pylint >=4.0.0,<5.0.0 + pytest >=7.0.0,<9.0.0 ruff >=0.1.0,<1.0.0 sphinx commands = From ed2e9013ebefc5db7008bd349cc7850893fe2b85 Mon Sep 17 00:00:00 2001 From: Chris Rink Date: Tue, 28 Oct 2025 21:34:57 -0400 Subject: [PATCH 2/4] Min deps test --- .github/workflows/run-tests.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 112350de..726ccf9c 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -16,10 +16,8 @@ jobs: strategy: matrix: os: [ubuntu-latest] - version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14'] + version: ['3.10', '3.11', '3.12', '3.13', '3.14'] include: - - version: '3.9' - tox-env: py39,py39-mypy,py39-lint,bandit - version: '3.10' tox-env: py310,py310-mypy,py310-lint,bandit - version: '3.11' @@ -150,8 +148,8 @@ jobs: strategy: matrix: os: [ubuntu-latest] - version: ['3.9'] - tox-env: ['py39'] + version: ['3.10'] + tox-env: ['py310'] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 From bf85223e72b56ff2f85add035e01a9fc90f0c41f Mon Sep 17 00:00:00 2001 From: Chris Rink Date: Tue, 28 Oct 2025 21:44:39 -0400 Subject: [PATCH 3/4] Fixes --- .github/workflows/run-tests.yml | 8 +++++--- src/basilisp/lang/reader.py | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 726ccf9c..46e5ef81 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -26,14 +26,16 @@ jobs: tox-env: py312,py312-mypy,py312-lint,bandit - version: '3.13' tox-env: py313,py313-mypy,py313-lint,bandit + # TODO: bandit doesn't currently work with 3.14 + # https://github.com/PyCQA/bandit/issues/1314 - version: '3.14' - tox-env: py314,py314-mypy,py314-lint,bandit,format + tox-env: py314,py314-mypy,py314-lint,format - os: windows-latest version: '3.14' - tox-env: py314,bandit + tox-env: py314,py314-lint - os: macos-latest version: '3.14' - tox-env: py313,bandit + tox-env: py313,py314-lint steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/src/basilisp/lang/reader.py b/src/basilisp/lang/reader.py index 0a815f20..ee5587ad 100644 --- a/src/basilisp/lang/reader.py +++ b/src/basilisp/lang/reader.py @@ -5,6 +5,7 @@ import decimal import functools import io +import math import os import re import uuid @@ -1498,9 +1499,9 @@ def _read_regex(ctx: ReaderContext) -> Pattern: _NUMERIC_CONSTANTS = { - "NaN": float("nan"), - "Inf": float("inf"), - "-Inf": -float("inf"), + "NaN": math.nan, + "Inf": math.inf, + "-Inf": -math.inf, } From 6bc7b004c1c7ce88066c95e0ef5eb69ca0ea8808 Mon Sep 17 00:00:00 2001 From: Chris Rink Date: Tue, 28 Oct 2025 21:50:43 -0400 Subject: [PATCH 4/4] Documentation updates --- docs/compiler.rst | 2 +- docs/differencesfromclojure.rst | 2 +- docs/index.rst | 2 +- docs/reader.rst | 2 +- pyproject.toml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/compiler.rst b/docs/compiler.rst index 00821cc0..a4727dc5 100644 --- a/docs/compiler.rst +++ b/docs/compiler.rst @@ -193,7 +193,7 @@ Debugging The compiler generates Python code by generating Python AST nodes, rather than emitting the raw Python code as text. This is convenient for the compiler, but inspecting Python AST nodes manually for bugs can be a bit of a challenge even with a debugger. -For this reason, the Basilisp compiler can also use the :external:py:func:`ast.unparse` (`astor `_ in versions of Python prior to 3.9) library to generate raw Python code for visual inspection. +For this reason, the Basilisp compiler can also use the :external:py:func:`ast.unparse` library to generate raw Python code for visual inspection. Currently, the compiler is configured to automatically generate Python code for all namespaces. This code generation isn't slow, but it does add an appreciable amount of time to the compilation of each individual namespace. diff --git a/docs/differencesfromclojure.rst b/docs/differencesfromclojure.rst index c55d5b67..9e344571 100644 --- a/docs/differencesfromclojure.rst +++ b/docs/differencesfromclojure.rst @@ -16,7 +16,7 @@ Hosted on Python ---------------- Unlike Clojure, Basilisp is hosted on the Python VM. -Basilisp supports versions of Python 3.9+. +Basilisp supports versions of Python 3.10+. Basilisp projects and libraries may both import Python code and be imported by Python code (once the Basilisp runtime has been :ref:`initialized ` and the import hooks have been installed). .. _type_differences: diff --git a/docs/index.rst b/docs/index.rst index e6a02736..ae5ea66d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,7 +6,7 @@ Welcome to Basilisp's documentation! ==================================== -Basilisp is a :ref:`Clojure-compatible(-ish) ` Lisp dialect targeting Python 3.9+. +Basilisp is a :ref:`Clojure-compatible(-ish) ` Lisp dialect targeting Python 3.10+. Basilisp compiles down to raw Python 3 code and executes on the Python 3 virtual machine, allowing natural interoperability between existing Python libraries and new Lisp code. diff --git a/docs/reader.rst b/docs/reader.rst index 9295fc96..c9323a2c 100644 --- a/docs/reader.rst +++ b/docs/reader.rst @@ -603,7 +603,7 @@ Splicing reader conditionals may only appear within other collection literal for Python Version Reader Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Basilisp includes a specialized set of reader features based on the major version of Python (e.g. 3.8, 3.9, etc.). +Basilisp includes a specialized set of reader features based on the major version of Python (e.g. 3.10, 3.11, etc.). Because the API of Python's standard library changes significantly between versions, it can be challenging to support multiple versions at once. In classical Python, users are forced to use conditional gates either at the top level of a module to define different function versions, or perhaps gate the logic within a function or class. Both options incur some level of runtime cost. diff --git a/pyproject.toml b/pyproject.toml index 97ccfa2d..38b5f691 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ pytest-pycharm = "*" # to maintain consistent output during both development and publishing on # Read The Docs. sphinx = "^7.1.0" -sphinx-autobuild = { version = "^2024.04.16", python = ">=3.9" } +sphinx-autobuild = "^2024.04.16" sphinx-copybutton = "^0.5.2" sphinxext-opengraph = "^v0.9.1" furo = "^2023.08.19"