Skip to content

fix: Support Python 3.14 where ast._Unparser was moved#92

Open
MementoRC wants to merge 1 commit intoisidentical:mainfrom
Claire-s-Monster:fix/python-3.14-ast-unparser
Open

fix: Support Python 3.14 where ast._Unparser was moved#92
MementoRC wants to merge 1 commit intoisidentical:mainfrom
Claire-s-Monster:fix/python-3.14-ast-unparser

Conversation

@MementoRC
Copy link
Copy Markdown
Contributor

Problem

Python 3.14 completely breaks refactor on import:

AttributeError: module 'ast' has no attribute '_Unparser'. Did you mean: 'unparse'?

This also breaks downstream tools like teyit.

Root Cause

Python 3.14 moved ast._Unparser to a C extension module _ast_unparse.Unparser. The ast.unparse() function now lazy-imports from there:

# Python 3.14 ast.py
def unparse(ast_obj):
    global _Unparser
    try:
        unparser = _Unparser()
    except NameError:
        from _ast_unparse import Unparser as _Unparser
        unparser = _Unparser()
    return unparser.visit(ast_obj)

Fix

Conditional import in refactor/ast.py:

try:
    _UnparserBase = ast._Unparser
except AttributeError:
    from _ast_unparse import Unparser as _UnparserBase

All internal APIs (visit, traverse, fill, write, _indent, _source) remain identical in the new location.

Compatibility

  • Python 3.10–3.13: uses ast._Unparser (unchanged behavior)
  • Python 3.14+: uses _ast_unparse.Unparser

Fixes #91

Python 3.14 moved ast._Unparser to _ast_unparse.Unparser
(C extension module). Add conditional import to support both
3.10-3.13 (ast._Unparser) and 3.14+ (_ast_unparse.Unparser).

All internal APIs (visit, traverse, fill, write, _indent, _source)
remain identical in the new location.

Fixes isidentical#91
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.

Python 3.14: AttributeError: module 'ast' has no attribute '_Unparser'

1 participant