Repository: twisted/twisted

Issue:
Update for Python 3.13 builtins.TypeError: '<' not supported between instances of 'NoneType' and 'int'

I now see there is 3.13 alpha build available on GitHub https://github.com/actions/python-versions/releases/tag/3.13.0-alpha.2-6966007093

There is this run reports from Karolina for Fedora:

https://download.copr.fedorainfracloud.org/results/@python/python3.13/fedora-rawhide-x86_64/06770350-python-twisted/builder-live.log.gz

```
[FAIL]
Traceback (most recent call last):
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/test/test_assertions.py", line 1599, in test_callDeprecationWithWrongMessage
    exception = self.assertRaises(
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 430, in assertRaises
    return context._handle(lambda: f(*args, **kwargs))
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 320, in _handle
    with self as context:
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 355, in __exit__
    self._testCase.fail(
twisted.trial.unittest.FailTest: builtins.TypeError raised instead of FailTest:
 Traceback (most recent call last):
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/python/util.py", line 958, in runWithWarningsSuppressed
    return f(*args, **kwargs)
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/test/test_assertions.py", line 1599, in test_callDeprecationWithWrongMessage
    exception = self.assertRaises(
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 430, in assertRaises
    return context._handle(lambda: f(*args, **kwargs))
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 320, in _handle
    with self as context:
--- <exception caught here> ---
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 321, in _handle
    self._returnValue = obj()
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 430, in <lambda>
    return context._handle(lambda: f(*args, **kwargs))
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 1297, in callDeprecated
    warningsShown = self.flushWarnings([self.callDeprecated])
  File "/builddir/build/BUILD/twisted-twisted-23.10.0/src/twisted/trial/_synctest.py", line 1196, in flushWarnings
    if not (min(lineNumbers) <= aWarning.lineno <= max(lineNumbers)):
builtins.TypeError: '<' not supported between instances of 'NoneType' and 'int'


twisted.trial.test.test_assertions.CallDeprecatedTests.test_callDeprecationWithWrongMessage
```

Try to run the tests with py3.13 and see if we can fix this error.

We might not merge the py3.13 test run just yet.


Discussion:

Resolving patch:
diff --git a/src/twisted/python/deprecate.py b/src/twisted/python/deprecate.py
--- a/src/twisted/python/deprecate.py
+++ b/src/twisted/python/deprecate.py
@@ -601,12 +601,19 @@ def warnAboutFunction(offender, warningString):
     """
     # inspect.getmodule() is attractive, but somewhat
     # broken in Python < 2.6.  See Python bug 4845.
+    # In Python 3.13 line numbers returned by findlinestarts
+    # can be None for bytecode that does not map to source
+    # lines.
     offenderModule = sys.modules[offender.__module__]
     warn_explicit(
         warningString,
         category=DeprecationWarning,
         filename=inspect.getabsfile(offenderModule),
-        lineno=max(lineNumber for _, lineNumber in findlinestarts(offender.__code__)),
+        lineno=max(
+            lineNumber
+            for _, lineNumber in findlinestarts(offender.__code__)
+            if lineNumber is not None
+        ),
         module=offenderModule.__name__,
         registry=offender.__globals__.setdefault("__warningregistry__", {}),
         module_globals=None,
diff --git a/src/twisted/trial/_synctest.py b/src/twisted/trial/_synctest.py
--- a/src/twisted/trial/_synctest.py
+++ b/src/twisted/trial/_synctest.py
@@ -1189,9 +1189,14 @@ def flushWarnings(self, offendingFunctions=None):
 
                     if filename != os.path.normcase(aWarning.filename):
                         continue
+
+                    # In Python 3.13 line numbers returned by findlinestarts
+                    # can be None for bytecode that does not map to source
+                    # lines.
                     lineNumbers = [
                         lineNumber
                         for _, lineNumber in _findlinestarts(aFunction.__code__)
+                        if lineNumber is not None
                     ]
                     if not (min(lineNumbers) <= aWarning.lineno <= max(lineNumbers)):
                         continue


Test patch:
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -134,6 +134,21 @@ jobs:
           # Just Python 3.11 with default settings.
           - python-version: '3.11'
 
+          # Just Python 3.13 alpha with default settings.
+          # For now, no dependencies as cffi doesn't work on 3.13.
+          # No coverage also.
+          - python-version: '3.13.0-alpha.3'
+            tox-env: 'nodeps-nocov-posix'
+            job-name: 'nodeps-nocov-3.13'
+            skip-coverage: yes
+            # FIXME:https://github.com/twisted/twisted/issues/12060
+            # Also add twisted.python
+            # FIXME:https://github.com/twisted/twisted/issues/12061
+            # Add full twisted.internet
+            # FIXME:https://github.com/twisted/twisted/issues/12062
+            # Add full twisted.test
+            trial-target: 'twisted.conch twisted.cred twisted.logger twisted.mail twisted.names twisted.pair twisted.persisted twisted.protocols twisted.runner twisted.spread twisted.test.test_defer twisted.trial twisted.words'
+
           # Newest macOS and oldest Python (major) supported versions.
           - python-version: '3.8'
             runs-on: 'macos-12'
@@ -194,7 +209,7 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Set up Python
-      uses: actions/setup-python@v4
+      uses: actions/setup-python@v5
       with:
         python-version: ${{ matrix.python-version }}
         allow-prereleases: true