Skip to content

Python 3.13/3.14 compatibility: fix escape sequence and cgi removal#553

Open
marcelo-srs wants to merge 1 commit intorawpython:masterfrom
marcelo-srs:master
Open

Python 3.13/3.14 compatibility: fix escape sequence and cgi removal#553
marcelo-srs wants to merge 1 commit intorawpython:masterfrom
marcelo-srs:master

Conversation

@marcelo-srs
Copy link

Summary

This PR fixes three Python 3.13/3.14 compatibility issues found when using remi with PyInstaller and modern Python versions.

1. Fix invalid escape sequence \E in server.py (SyntaxWarning → SyntaxError)

remi/server.py contained \ERROR in a debug format string. \E is not a valid Python escape sequence:

  • Python 3.12: emits SyntaxWarning
  • Python 3.13: emits SyntaxWarning (promoted to error by PyInstaller in frozen builds)
  • Python 3.14: hard SyntaxError — the module fails to import entirely

Fix: changed \ERROR\\ERROR.

2. Replace removed cgi module

cgi.FieldStorage was deprecated in Python 3.11 and removed in Python 3.13. It was used in do_POST to parse multipart/form-data file uploads.

Fix: wrapped the import in a try/except:

  • Python ≤ 3.12: imports cgi.FieldStorage as before — no behaviour change
  • Python 3.13+: uses a minimal _FieldStorage drop-in built on email.parser that exposes the same .keys() / .__getitem__() / .filename / .file interface

3. Ensure remi.__version__ is always defined (PyInstaller / frozen builds)

__init__.py looked up the version via importlib.metadata, then pkg_resources, and silently passed if neither could find the package. In PyInstaller frozen builds the package metadata is typically absent, leaving __version__ undefined and causing AttributeError on access.

Fix: set __version__ = _FALLBACK_VERSION (hardcoded "2026.03.24") before the lookup chain. The metadata lookup still overrides it when available; the fallback guarantees __version__ is always a valid string.

Version bumped to 2026.03.24 in both __init__.py and setup.py.


New tests — test/test_version.py

Test What it covers
TestNoSyntaxWarnings.test_server_py_no_syntax_warnings Compiles server.py with -W error::SyntaxWarning — asserts no warnings/errors
TestVersionAlwaysDefined.test_version_is_string remi.__version__ is always a str
TestVersionAlwaysDefined.test_version_non_empty remi.__version__ is never empty
TestVersionImportlibMetadataPath.test_importlib_metadata_used When importlib.metadata.version() succeeds, its value is used
TestVersionPkgResourcesFallback.test_pkg_resources_fallback When importlib.metadata is absent, pkg_resources provides the version
TestVersionHardcodedFallback.test_hardcoded_fallback_used When metadata lookup raises PackageNotFoundError, hardcoded fallback is used
TestVersionHardcodedFallback.test_fallback_version_matches_setup _FALLBACK_VERSION in __init__.py stays in sync with setup.py

Test results across Python versions

All 7 new tests pass on every tested version. The 4 pre-existing failures (missing optional matplotlib/PIL deps, and two assertEquals calls deprecated since 3.12) are unchanged and unrelated to this PR.

Python 3.12.8

Ran 95 tests in 2.146s
FAILED (errors=4 [pre-existing], skipped=8)
New version tests: 7/7 ✅
SyntaxWarning check: ✅

Python 3.13.1

Ran 95 tests in 2.130s
FAILED (errors=4 [pre-existing], skipped=8)
New version tests: 7/7 ✅
SyntaxWarning check: ✅

Python 3.14.3

Ran 95 tests in 2.143s
FAILED (errors=4 [pre-existing], skipped=8)
New version tests: 7/7 ✅
SyntaxWarning check: ✅

Note for PyInstaller users: the pkg_resources injection workaround previously needed in launcher scripts is no longer required — importlib.metadata takes priority on Python 3.8+ and the hardcoded fallback covers frozen-build environments.

🤖 Generated with Claude Code

- Fix SyntaxWarning (→ SyntaxError in 3.14) from invalid escape sequence
  `\E` in server.py onerror debug string; replace with `\\E`
- Replace removed `cgi` module (dropped in Python 3.13) with a try/except
  that imports `cgi.FieldStorage` on Python ≤3.12 and falls back to a
  minimal `_FieldStorage` implementation using `email.parser` on 3.13+
- Always define `remi.__version__`: set `_FALLBACK_VERSION = "2026.03.24"`
  before the importlib.metadata / pkg_resources lookup chain so the
  attribute is never undefined in PyInstaller frozen builds or bare
  source checkouts
- Bump hardcoded fallback version to 2026.03.24 in both __init__.py and
  setup.py (kept in sync)
- Add test/test_version.py with 7 test cases validated on Python 3.12,
  3.13 and 3.14

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dddomodossola
Copy link
Collaborator

Thank you very much @marcelo-srs 😉

pull bot pushed a commit to Pandinosaurus/remi that referenced this pull request Mar 24, 2026
Python 3.13/3.14 compatibility: fix escape sequence and cgi removal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants