Skip to content

Make spyne ready for Python 3.14#723

Open
carloscbl wants to merge 2 commits into
arskom:masterfrom
carloscbl:sm/python-3.14
Open

Make spyne ready for Python 3.14#723
carloscbl wants to merge 2 commits into
arskom:masterfrom
carloscbl:sm/python-3.14

Conversation

@carloscbl

Copy link
Copy Markdown

Summary

Brings spyne up to date with the current CPython release line. After this PR, import spyne and the model/protocol/interface test suites pass cleanly on Python 3.11, 3.12, 3.13 and 3.14 — no SyntaxWarning, no SyntaxError, no removed-stdlib import failures.

Tested on python:3.14-slim: 526/526 tests pass in spyne/test/{model,protocol,interface} and python -m compileall spyne is silent under -W error::SyntaxWarning.

What's in the box

1. Invalid string-escape SyntaxWarning (will be SyntaxError in a future Python)

  • spyne/protocol/http.py:438b'(?P<\\1>[^\.]*)' → raw bytestring rb'(?P<\1>[^\.]*)'. The original sub already used a raw-string version on the line above; this is the same pattern but for the bytes path.
  • spyne/protocol/json.py — module docstring contains \s and \d-like sequences. Marked the docstring as raw (r"""…""").
  • spyne/util/invregexp.py — same fix on the invregexp docstring (contains \d inside an example regex).

2. PEP 765 (Python 3.14): break/continue/return in finally

spyne/protocol/cloth/to_cloth.py:770 had a break inside a finally: block, which Python 3.14 flags as a SyntaxWarning. The break was unconditional after the inner try/except StopIteration, so it can be hoisted out of the finally without changing the happy-path semantics. Added a one-line comment pointing to PEP 765.

3. cgi module removed in Python 3.13

spyne/server/twisted/http.py uses cgi.FieldStorage for multipart parsing in the Twisted HTTP server. PR #713 already addressed cgi.parse_header, but FieldStorage was untouched.

This PR keeps the existing code path working without forcing a heavy dependency on everyone:

  • import cgi is wrapped in a try/except ImportError, falling back to the legacy-cgi PyPI package (a maintained fork of the stdlib cgi module) if it is installed.
  • If neither is available and the multipart code path is actually executed, it raises a RuntimeError with a clear message telling the user to pip install legacy-cgi. Users who don't use multipart over Twisted pay nothing.

A full rewrite of multipart parsing is out of scope here — this is the minimum viable change to keep 3.13/3.14 users running.

4. Deprecated unittest aliases removed in Python 3.12

The test suite still used assertEquals, assertNotEquals, assertRegexpMatches, assertRaisesRegexp and failUnlessEqual, all of which were removed in 3.12. Replaced mechanically with their non-deprecated names in:

  • spyne/test/interop/test_django.py
  • spyne/test/multipython/model/test_complex.py
  • spyne/test/protocol/_test_dictdoc.py

(That last file is why test_json.py, test_msgpack.py and test_yaml.py had 6 collective failures on 3.12+ — same shared base.)

5. Classifiers

Added Python :: 3.11, 3.12, 3.13, 3.14 to setup.py. Did not drop the older entries — happy to do that in a follow-up if you'd rather couple it to a release.

6. Version bump

Bumped __version__ from 2.15.0-alpha to 2.15.0 and added a CHANGELOG.rst entry. If you'd prefer to keep the alpha tag and roll your own release, just drop those two hunks — the rest stands on its own.

Out of scope (intentionally)

  • Twisted multipart rewrite to drop cgi entirely.
  • The FutureWarning from lxml about truth-testing elements in protocol/soap/soap12.py. It's pre-existing and unrelated to 3.14.
  • The wsgiref "iterator garbage collected without being closed" warning from a couple of tests — also pre-existing.
  • spyne/util/six.py — left alone; it's still used internally and Python 2 deprecation is a separate conversation.

Test plan

  • python -m compileall -q spyne clean under -W error::SyntaxWarning on 3.14
  • import spyne; from spyne import Application, ServiceBase, rpc; from spyne.protocol.soap import Soap11, Soap12; from spyne.server.wsgi import WsgiApplication succeeds on 3.14
  • pytest spyne/test/{model,protocol,interface} -q → 526 passed, 0 failed on 3.14
  • CI run on 3.11/3.12/3.13/3.14 (would appreciate maintainers triggering once classifiers are in)

carloscbl added 2 commits May 6, 2026 17:03
- protocol/http.py:438: use rb-string to fix '\.' escape SyntaxWarning
- protocol/json.py: mark module docstring raw to silence '\s' SyntaxWarning
- protocol/cloth/to_cloth.py: hoist 'break' out of finally (PEP 765, Py 3.14)
- util/invregexp.py: mark docstring raw ('\d' escape)
- server/twisted/http.py: cgi removed in 3.13 — try legacy_cgi fallback,
  raise descriptive error if multipart code path is hit without it
- test/*: replace deprecated unittest aliases (assertEquals -> assertEqual etc.)
- setup.py: add 3.11/3.12/3.13/3.14 classifiers

Tested: 526/526 model+protocol+interface tests pass on python:3.14-slim.
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.

1 participant