extensions: address ast deprecations introduced in Python 3.12
Tests would fail with:
.../mercurial/extensions.py:910: DeprecationWarning: ast.Str is deprecated and will be removed in Python 3.14; use ast.Constant instead
if isinstance(a, ast.Str):
.../mercurial/extensions.py:912: DeprecationWarning: ast.Bytes is deprecated and will be removed in Python 3.14; use ast.Constant instead
elif isinstance(a, ast.Bytes):
.../mercurial/extensions.py:913: DeprecationWarning: Attribute s is deprecated and will be removed in Python 3.14; use value instead
name = a.s
--- a/mercurial/extensions.py Tue Jun 27 08:39:12 2023 +0200
+++ b/mercurial/extensions.py Tue Jun 27 22:31:44 2023 +0200
@@ -885,16 +885,31 @@
with open(path, b'rb') as src:
root = ast.parse(src.read(), path)
cmdtable = {}
+
+ # Python 3.12 started removing Bytes and Str and deprecate harder
+ use_constant = 'Bytes' not in vars(ast)
+
for node in _walkcommand(root):
if not node.args:
continue
a = node.args[0]
- if isinstance(a, ast.Str):
- name = pycompat.sysbytes(a.s)
- elif isinstance(a, ast.Bytes):
- name = a.s
- else:
- continue
+ if use_constant: # Valid since Python 3.8
+ if isinstance(a, ast.Constant):
+ if isinstance(a.value, str):
+ name = pycompat.sysbytes(a.value)
+ elif isinstance(a.value, bytes):
+ name = a.value
+ else:
+ continue
+ else:
+ continue
+ else: # Valid until 3.11
+ if isinstance(a, ast.Str):
+ name = pycompat.sysbytes(a.s)
+ elif isinstance(a, ast.Bytes):
+ name = a.s
+ else:
+ continue
cmdtable[name] = (None, [], b'')
return cmdtable