Fix DeprecationWarning while spying on generator functions.

Review Request #14574 — Created Aug. 28, 2025 and updated

Information

kgb
master

Reviewers

kgb

Python 3.13 added a new DeprecationWarning which is triggered when
calling setattr() to replace the code object of a function in the case
that the code object's flags have a mismatch on the CO_GENERATOR,
CO_COROUTINE, or CO_ASYNC_GENERATOR bits. This was done in response
to a bug (https://github.com/python/cpython/issues/81137) where
replacing a lambda's code object with the gi_code attribute from a
generator expression would then cause cpython to crash. This was purely
a problem with the way that gi_code works for generator expressions
(and comprehensions), and does not affect generator functions in the
same way. This means that rather than posing a real issue for kgb, we
just see ugly warnings.

In order to prevent these warnings, we now copy true values for those
three flags from the old code object into the new one.

  • Commented out the fix and saw the new unit test fail.
  • Ran unit tests and saw no more warnings.
  • Tested with an experimental test (not included here) that replaces an
    async generator and saw that that worked too.
  • Ran tests on Python 3.8-3.13
Summary ID
Fix DeprecationWarning while spying on generator functions.
Python 3.13 added a new `DeprecationWarning` which is triggered when calling `setattr()` to replace the code object of a function in the case that the code object's flags have a mismatch on the `CO_GENERATOR`, `CO_COROUTINE`, or `CO_ASYNC_GENERATOR` bits. This was done in response to a bug (https://github.com/python/cpython/issues/81137) where replacing a lambda's code object with the `gi_code` attribute from a generator expression would then cause cpython to crash. This was purely a problem with the way that `gi_code` works for generator expressions (and comprehensions), and does not affect generator functions in the same way. This means that rather than posing a real issue for kgb, we just see ugly warnings. In order to prevent these warnings, we now copy true values for those three flags from the old code object into the new one. Testing Done: - Commented out the fix and saw the new unit test fail. - Ran unit tests and saw no more warnings. - Tested with an experimental test (not included here) that replaces an async generator and saw that that worked too. - Ran tests on Python 3.8-3.13
nlputqsrwlmlwnrnzwsrzqzxqqxwoqpm
Description From Last Updated

Can you verify (and include in Testing Done) whether all Python versions pass via tox?

chipx86chipx86

Can you add a blank line before that URL? This looks unbalanced.

chipx86chipx86

"CPython"

chipx86chipx86

Can we do one per line?

chipx86chipx86
maubin
  1. Ship It!
  2. 
      
chipx86
  1. 
      
  2. Show all issues

    Can you verify (and include in Testing Done) whether all Python versions pass via tox?

    1. For some reason running through tox isn't working, but I manually verified 3.8-3.13.

      Did discover that this fix breaks < 3.11 as a result though, so thanks for the push.

  3. kgb/spies.py (Diff revision 1)
     
     
     
     
     
    Show all issues

    Can you add a blank line before that URL? This looks unbalanced.

  4. kgb/spies.py (Diff revision 1)
     
     
    Show all issues

    "CPython"

  5. kgb/spies.py (Diff revision 1)
     
     
     
    Show all issues

    Can we do one per line?

  6. 
      
david
Review request changed
Testing Done:
   
  • Commented out the fix and saw the new unit test fail.
   
  • Ran unit tests and saw no more warnings.
   
  • Tested with an experimental test (not included here) that replaces an
    async generator and saw that that worked too.
  +
  • Ran tests on Python 3.8-3.13
Commits:
Summary ID
Fix DeprecationWarning while spying on generator functions.
Python 3.13 added a new `DeprecationWarning` which is triggered when calling `setattr()` to replace the code object of a function in the case that the code object's flags have a mismatch on the `CO_GENERATOR`, `CO_COROUTINE`, or `CO_ASYNC_GENERATOR` bits. This was done in response to a bug (https://github.com/python/cpython/issues/81137) where replacing a lambda's code object with the `gi_code` attribute from a generator expression would then cause cpython to crash. This was purely a problem with the way that `gi_code` works for generator expressions (and comprehensions), and does not affect generator functions in the same way. This means that rather than posing a real issue for kgb, we just see ugly warnings. In order to prevent these warnings, we now copy true values for those three flags from the old code object into the new one. Testing Done: - Commented out the fix and saw the new unit test fail. - Ran unit tests and saw no more warnings. - Tested with an experimental test (not included here) that replaces an async generator and saw that that worked too.
zqxoklumwxzuwspwlvnwwrqmomxznppt
Fix DeprecationWarning while spying on generator functions.
Python 3.13 added a new `DeprecationWarning` which is triggered when calling `setattr()` to replace the code object of a function in the case that the code object's flags have a mismatch on the `CO_GENERATOR`, `CO_COROUTINE`, or `CO_ASYNC_GENERATOR` bits. This was done in response to a bug (https://github.com/python/cpython/issues/81137) where replacing a lambda's code object with the `gi_code` attribute from a generator expression would then cause cpython to crash. This was purely a problem with the way that `gi_code` works for generator expressions (and comprehensions), and does not affect generator functions in the same way. This means that rather than posing a real issue for kgb, we just see ugly warnings. In order to prevent these warnings, we now copy true values for those three flags from the old code object into the new one. Testing Done: - Commented out the fix and saw the new unit test fail. - Ran unit tests and saw no more warnings. - Tested with an experimental test (not included here) that replaces an async generator and saw that that worked too. - Ran tests on Python 3.8-3.13
nlputqsrwlmlwnrnzwsrzqzxqqxwoqpm

Checks run (2 succeeded)

flake8 passed.
JSHint passed.