Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-gast for openSUSE:Factory checked in at 2023-10-11 23:54:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-gast (Old) and /work/SRC/openSUSE:Factory/.python-gast.new.1807 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-gast" Wed Oct 11 23:54:14 2023 rev:8 rq:1116718 version:0.5.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-gast/python-gast.changes 2023-04-22 22:01:41.077655589 +0200 +++ /work/SRC/openSUSE:Factory/.python-gast.new.1807/python-gast.changes 2023-10-12 11:53:19.961401504 +0200 @@ -1,0 +2,17 @@ +Tue Oct 10 13:44:16 UTC 2023 - Matej Cepl <mc...@cepl.eu> + +- Once more on the breach! Update to 0.5.4 (see changes below). + +------------------------------------------------------------------- +Wed May 17 14:37:48 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- go back to 0.5.3 + +------------------------------------------------------------------- +Sun May 14 12:52:11 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 0.5.4: + * Support TryStar from python 3.11 + * Support match statement from python 3.10 + +------------------------------------------------------------------- Old: ---- gast-0.5.3.tar.gz New: ---- gast-0.5.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-gast.spec ++++++ --- /var/tmp/diff_new_pack.Pk8FBj/_old 2023-10-12 11:53:21.005437826 +0200 +++ /var/tmp/diff_new_pack.Pk8FBj/_new 2023-10-12 11:53:21.021438382 +0200 @@ -17,16 +17,16 @@ %define srcname gast -%{?!python_module:%define python_module() python-%{**} python3-%{**}} %{?sle15_python_module_pythons} Name: python-gast -Version: 0.5.3 +Version: 0.5.4 Release: 0 Summary: Python AST that abstracts the underlying Python version License: BSD-3-Clause URL: https://github.com/serge-sans-paille/gast/ Source: https://github.com/serge-sans-paille/gast/archive/%{version}.tar.gz#/%{srcname}-%{version}.tar.gz -BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module pip} +BuildRequires: %{python_module wheel} BuildRequires: python-rpm-macros # SECTION test requirements BuildRequires: %{python_module astunparse} @@ -42,20 +42,21 @@ as produced by ``ast.parse`` from the standard ``ast`` module. %prep -%setup -q -n gast-%{version} +%autosetup -p1 -n gast-%{version} %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %check %pyunittest discover -v tests %files %{python_files} -%{python_sitelib}/* +%{python_sitelib}/gast +%{python_sitelib}/gast-%{version}*-info %doc README.rst %license LICENSE ++++++ gast-0.5.3.tar.gz -> gast-0.5.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gast-0.5.3/.github/workflows/core.yml new/gast-0.5.4/.github/workflows/core.yml --- old/gast-0.5.3/.github/workflows/core.yml 2021-11-13 22:38:20.000000000 +0100 +++ new/gast-0.5.4/.github/workflows/core.yml 2023-04-29 21:35:43.000000000 +0200 @@ -9,14 +9,18 @@ - master jobs: build: - runs-on: ubuntu-18.04 strategy: matrix: - python-version: [3.6, 3.8, 3.9, 3.10-dev] + python-version: ["2.7", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev"] + include: + - python-version: 3.6 + os: ubuntu-20.04 + runs-on: ${{ matrix.os || 'ubuntu-latest' }} + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gast-0.5.3/README.rst new/gast-0.5.4/README.rst --- old/gast-0.5.3/README.rst 2021-11-13 22:38:20.000000000 +0100 +++ new/gast-0.5.4/README.rst 2023-04-29 21:35:43.000000000 +0200 @@ -50,6 +50,7 @@ - 3.8 - 3.9 - 3.10 +- 3.11 AST Changes @@ -118,6 +119,9 @@ ASDL **** +This closely matches the one from https://docs.python.org/3/library/ast.html#abstract-grammar, with a few +trade-offs to cope with legacy ASTs. + .. code:: -- ASDL's six builtin types are identifier, int, string, bytes, object, singleton @@ -163,8 +167,11 @@ | With(withitem* items, stmt* body, string? type_comment) | AsyncWith(withitem* items, stmt* body, string? type_comment) + | Match(expr subject, match_case* cases) + | Raise(expr? exc, expr? cause) | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) + | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) | Assert(expr test, expr? msg) | Import(alias* names) @@ -254,5 +261,21 @@ withitem = (expr context_expr, expr? optional_vars) + match_case = (pattern pattern, expr? guard, stmt* body) + + pattern = MatchValue(expr value) + | MatchSingleton(constant value) + | MatchSequence(pattern* patterns) + | MatchMapping(expr* keys, pattern* patterns, identifier? rest) + | MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns) + + | MatchStar(identifier? name) + -- The optional "rest" MatchMapping parameter handles capturing extra mapping keys + + | MatchAs(pattern? pattern, identifier? name) + | MatchOr(pattern* patterns) + + attributes (int lineno, int col_offset, int end_lineno, int end_col_offset) + type_ignore = TypeIgnore(int lineno, string tag) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gast-0.5.3/gast/gast.py new/gast-0.5.4/gast/gast.py --- old/gast-0.5.3/gast/gast.py 2021-11-13 22:38:20.000000000 +0100 +++ new/gast-0.5.4/gast/gast.py 2023-04-29 21:35:43.000000000 +0200 @@ -10,6 +10,12 @@ class TypeIgnore(AST): pass +try: + from ast import pattern +except ImportError: + class pattern(AST): + pass + def _make_node(Name, Fields, Attributes, Bases): NBFields = len(Fields) @@ -93,12 +99,18 @@ ('AsyncWith', (('items', 'body', 'type_comment'), ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',), (stmt,))), + ('Match', (('subject', 'cases'), + ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',), + (stmt,))), ('Raise', (('exc', 'cause',), ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',), (stmt,))), ('Try', (('body', 'handlers', 'orelse', 'finalbody',), ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',), (stmt,))), + ('TryStar', (('body', 'handlers', 'orelse', 'finalbody',), + ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',), + (stmt,))), ('Assert', (('test', 'msg',), ('lineno', 'col_offset', 'end_lineno', 'end_col_offset',), (stmt,))), @@ -290,6 +302,42 @@ # withitem ('withitem', (('context_expr', 'optional_vars'), (), (AST,))), + # match_case + ('match_case', (('pattern', 'guard', 'body'), (), (AST,))), + + # pattern + ('MatchValue', (('value',), + ('lineno', 'col_offset', 'end_lineno', 'end_col_offset'), + (pattern,))), + ('MatchSingleton', (('value',), + ('lineno', 'col_offset', + 'end_lineno', 'end_col_offset'), + (pattern,))), + ('MatchSequence', (('patterns',), + ('lineno', 'col_offset', + 'end_lineno', 'end_col_offset'), + (pattern,))), + ('MatchMapping', (('keys', 'patterns', 'rest'), + ('lineno', 'col_offset', + 'end_lineno', 'end_col_offset'), + (pattern,))), + ('MatchClass', (('cls', 'patterns', 'kwd_attrs', 'kwd_patterns'), + ('lineno', 'col_offset', + 'end_lineno', 'end_col_offset'), + (pattern,))), + ('MatchStar', (('name',), + ('lineno', 'col_offset', + 'end_lineno', 'end_col_offset'), + (pattern,))), + ('MatchAs', (('pattern', 'name'), + ('lineno', 'col_offset', + 'end_lineno', 'end_col_offset'), + (pattern,))), + ('MatchOr', (('patterns',), + ('lineno', 'col_offset', + 'end_lineno', 'end_col_offset'), + (pattern,))), + # type_ignore ('type_ignore', ((), ('lineno', 'tag'), (TypeIgnore,))), ) @@ -308,7 +356,7 @@ def unparse(gast_obj): - from gast.unparser import unparse + from .unparser import unparse return unparse(gast_obj) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gast-0.5.3/gast/unparser.py new/gast-0.5.4/gast/unparser.py --- old/gast-0.5.3/gast/unparser.py 2021-11-13 22:38:20.000000000 +0100 +++ new/gast-0.5.4/gast/unparser.py 2023-04-29 21:35:43.000000000 +0200 @@ -50,9 +50,9 @@ # Agreement. import sys -from gast import * +from . import * from contextlib import contextmanager -from enum import auto, Enum +from string import printable class nullcontext(object): @@ -96,14 +96,14 @@ _SINGLE_QUOTES = ("'", '"') _MULTI_QUOTES = ('"""', "'''") -_ALL_QUOTES = (*_SINGLE_QUOTES, *_MULTI_QUOTES) +_ALL_QUOTES = _SINGLE_QUOTES + _MULTI_QUOTES class _Unparser(NodeVisitor): """Methods in this class recursively traverse an AST and output source code for the abstract syntax; original formatting is disregarded.""" - def __init__(self, *, _avoid_backslashes=False): + def __init__(self, _avoid_backslashes=False): self._source = [] self._buffer = [] self._precedences = {} @@ -158,7 +158,7 @@ return value @contextmanager - def block(self, *, extra = None): + def block(self, extra = None): """A context manager for preparing the source for blocks. It adds the character':', increases the indentation on enter and decreases the indentation on exit. If *extra* is given, it will be directly @@ -216,14 +216,14 @@ def get_type_comment(self, node): comment = self._type_ignores.get(node.lineno) or node.type_comment if comment is not None: - return f" # type: {comment}" + return " # type: {}".format(comment) def traverse(self, node): if isinstance(node, list): for item in node: self.traverse(item) else: - super().visit(node) + super(_Unparser, self).visit(node) # Note: as visit() resets the output text, do NOT rely on # NodeVisitor.generic_visit to handle any nodes (as it calls back in to @@ -245,7 +245,7 @@ def visit_Module(self, node): self._type_ignores = { - ignore.lineno: f"ignore{ignore.tag}" + ignore.lineno: "ignore{}".format(ignore.tag) for ignore in node.type_ignores } self._write_docstring_and_traverse_body(node) @@ -372,7 +372,7 @@ self.fill("raise") if not node.exc: if node.cause: - raise ValueError(f"Node can't use cause without an exception.") + raise ValueError("Node can't use cause without an exception.") return self.write(" ") self.traverse(node.exc) @@ -510,7 +510,7 @@ self.traverse(node.body) def _str_literal_helper( - self, string, *, quote_types=_ALL_QUOTES, escape_special_whitespace=False + self, string, quote_types=_ALL_QUOTES, escape_special_whitespace=False ): """Helper for writing string literals, minimizing escapes. Returns the tuple (string literal to write, possible quote types). @@ -521,7 +521,7 @@ if not escape_special_whitespace and c in "\n\t": return c # Always escape backslashes and other non-printable characters - if c == "\\" or not c.isprintable(): + if c == "\\" or not all(cc in printable for cc in c): return c.encode("unicode_escape").decode("ascii") return c @@ -547,11 +547,11 @@ escaped_string = escaped_string[:-1] + "\\" + escaped_string[-1] return escaped_string, possible_quotes - def _write_str_avoiding_backslashes(self, string, *, quote_types=_ALL_QUOTES): + def _write_str_avoiding_backslashes(self, string, quote_types=_ALL_QUOTES): """Write string literal value with a best effort attempt to avoid backslashes.""" string, quote_types = self._str_literal_helper(string, quote_types=quote_types) quote_type = quote_types[0] - self.write(f"{quote_type}{string}{quote_type}") + self.write("{0}{1}{0}".format(quote_type, string)) def visit_JoinedStr(self, node): self.write("f") @@ -582,7 +582,7 @@ new_buffer.append(value) value = "".join(new_buffer) quote_type = quote_types[0] - self.write(f"{quote_type}{value}{quote_type}") + self.write("{0}{1}{0}".format(quote_type, value)) def visit_FormattedValue(self, node): self.write("f") @@ -614,7 +614,7 @@ conversion = chr(node.conversion) if conversion not in "sra": raise ValueError("Unknown f-string conversion.") - write(f"!{conversion}") + write("!{}".format(conversion)) if node.format_spec: write(":") meth = getattr(self, "_fstring_" + type(node.format_spec).__name__) @@ -637,7 +637,7 @@ self.write( repr(value) .replace("inf", _INFSTR) - .replace("nan", f"({_INFSTR}-{_INFSTR})") + .replace("nan", "({0}-{0})".format(_INFSTR)) ) elif self._avoid_backslashes and isinstance(value, str): self._write_str_avoiding_backslashes(value) @@ -649,7 +649,7 @@ if isinstance(value, tuple): with self.delimit("(", ")"): self.items_view(self._write_constant, value) - elif value is ...: + elif value is Ellipsis: self.write("...") else: if node.kind == "u": @@ -811,7 +811,7 @@ self.set_precedence(left_precedence, node.left) self.traverse(node.left) - self.write(f" {operator} ") + self.write(" {} ".format(operator)) self.set_precedence(right_precedence, node.right) self.traverse(node.right) @@ -841,16 +841,15 @@ def visit_BoolOp(self, node): operator = self.boolops[node.op.__class__.__name__] - operator_precedence = self.boolop_precedence[operator] + operator_precedence = [self.boolop_precedence[operator]] def increasing_level_traverse(node): - nonlocal operator_precedence - operator_precedence = operator_precedence + 1 - self.set_precedence(operator_precedence, node) + operator_precedence[0] += 1 + self.set_precedence(operator_precedence[0], node) self.traverse(node) - with self.require_parens(operator_precedence, node): - s = f" {operator} " + with self.require_parens(operator_precedence[0], node): + s = " {} ".format(operator) self.interleave(lambda: self.write(s), increasing_level_traverse, node.values) def visit_Attribute(self, node): @@ -1035,7 +1034,7 @@ name = node.name if name is None: name = "_" - self.write(f"*{name}") + self.write("*{}".format(name)) def visit_MatchMapping(self, node): def write_key_pattern_pair(pair): @@ -1055,7 +1054,7 @@ if rest is not None: if keys: self.write(", ") - self.write(f"**{rest}") + self.write("**{}".format(rest)) def visit_MatchClass(self, node): self.set_precedence(_Precedence.ATOM, node.cls) @@ -1069,7 +1068,7 @@ if attrs: def write_attr_pattern(pair): attr, pattern = pair - self.write(f"{attr}=") + self.write("{}=".format(attr)) self.traverse(pattern) if patterns: @@ -1091,7 +1090,7 @@ with self.require_parens(_Precedence.TEST, node): self.set_precedence(_Precedence.BOR, node.pattern) self.traverse(node.pattern) - self.write(f" as {node.name}") + self.write(" as {}".format(node.name)) def visit_MatchOr(self, node): with self.require_parens(_Precedence.BOR, node): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gast-0.5.3/gast/version.py new/gast-0.5.4/gast/version.py --- old/gast-0.5.3/gast/version.py 2021-11-13 22:38:20.000000000 +0100 +++ new/gast-0.5.4/gast/version.py 2023-04-29 21:35:43.000000000 +0200 @@ -1 +1 @@ -__version__ = '0.5.3' +__version__ = '0.5.4' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gast-0.5.3/setup.py new/gast-0.5.4/setup.py --- old/gast-0.5.3/setup.py 2021-11-13 22:38:20.000000000 +0100 +++ new/gast-0.5.4/setup.py 2023-04-29 21:35:43.000000000 +0200 @@ -41,6 +41,7 @@ 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', ], python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', **kw diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gast-0.5.3/tests/test_compat.py new/gast-0.5.4/tests/test_compat.py --- old/gast-0.5.3/tests/test_compat.py 2021-11-13 22:38:20.000000000 +0100 +++ new/gast-0.5.4/tests/test_compat.py 2023-04-29 21:35:43.000000000 +0200 @@ -122,6 +122,127 @@ "[])") self.assertEqual(gast.dump(tree), norm) + if sys.version_info.minor >= 10: + + def test_MatchValue(self): + code = 'match v:\n case "hello":...' + tree = gast.parse(code) + compile(gast.gast_to_ast(tree), '<test>', 'exec') + norm = ("Module(body=[Match(subject=Name(id='v', ctx=Load" + "(), annotation=None, type_comment=None), cases=" + "[match_case(pattern=MatchValue(value=Constant(" + "value='hello', kind=None)), guard=None, body=" + "[Expr(value=Constant(value=Ellipsis, kind=None))]" + ")])], type_ignores=[])" + ) + self.assertEqual(gast.dump(tree), norm) + + def test_MatchSingleton(self): + self.maxDiff = None + code = 'match v:\n case None:...' + tree = gast.parse(code) + compile(gast.gast_to_ast(tree), '<test>', 'exec') + norm = ("Module(body=[Match(subject=Name(id='v', ctx=Load" + "(), annotation=None, type_comment=None), cases=[" + "match_case(pattern=MatchSingleton(value=None), " + "guard=None, body=[Expr(value=Constant(value=" + "Ellipsis, kind=None))])])], type_ignores=[])") + self.assertEqual(gast.dump(tree), norm) + + def test_MatchSequence(self): + code = 'match v:\n case a, b:...' + tree = gast.parse(code) + compile(gast.gast_to_ast(tree), '<test>', 'exec') + norm = ("Module(body=[Match(subject=Name(id='v', ctx=Load" + "(), annotation=None, type_comment=None), cases=" + "[match_case(pattern=MatchSequence(patterns=[" + "MatchAs(pattern=None, name='a'), MatchAs(pattern" + "=None, name='b')]), guard=None, body=[Expr(value" + "=Constant(value=Ellipsis, kind=None))])])], " + "type_ignores=[])") + self.assertEqual(gast.dump(tree), norm) + + def test_MatchMapping(self): + code = 'match v:\n case {1: a}:...' + tree = gast.parse(code) + compile(gast.gast_to_ast(tree), '<test>', 'exec') + norm = ("Module(body=[Match(subject=Name(id='v', ctx=Load" + "(), annotation=None, type_comment=None), cases=[" + "match_case(pattern=MatchMapping(keys=[Constant(" + "value=1, kind=None)], patterns=[MatchAs(pattern" + "=None, name='a')], rest=None), guard=None, body=" + "[Expr(value=Constant(value=Ellipsis, kind=None))]" + ")])], type_ignores=[])") + self.assertEqual(gast.dump(tree), norm) + + def test_MatchClass(self): + code = 'match v:\n case Cls(attr=1):...' + tree = gast.parse(code) + compile(gast.gast_to_ast(tree), '<test>', 'exec') + norm = ("Module(body=[Match(subject=Name(id='v', ctx=Load" + "(), annotation=None, type_comment=None), cases=[" + "match_case(pattern=MatchClass(cls=Name(id='Cls'" + ", ctx=Load(), annotation=None, type_comment=None" + "), patterns=[], kwd_attrs=['attr'], kwd_patterns" + "=[MatchValue(value=Constant(value=1, kind=None))" + "]), guard=None, body=[Expr(value=Constant(value=" + "Ellipsis, kind=None))])])], type_ignores=[])") + self.assertEqual(gast.dump(tree), norm) + + def test_MatchStar(self): + code = 'match v:\n case [1, *other]:...' + tree = gast.parse(code) + compile(gast.gast_to_ast(tree), '<test>', 'exec') + norm = ("Module(body=[Match(subject=Name(id='v', ctx=Load" + "(), annotation=None, type_comment=None), cases=[" + "match_case(pattern=MatchSequence(patterns=[" + "MatchValue(value=Constant(value=1, kind=None)), " + "MatchStar(name='other')]), guard=None, body=" + "[Expr(value=Constant(value=Ellipsis, kind=None)" + ")])])], type_ignores=[])") + self.assertEqual(gast.dump(tree), norm) + + def test_MatchAs(self): + code = 'match v:\n case 1, other:...' + tree = gast.parse(code) + compile(gast.gast_to_ast(tree), '<test>', 'exec') + norm = ("Module(body=[Match(subject=Name(id='v', ctx=Load" + "(), annotation=None, type_comment=None), cases=[" + "match_case(pattern=MatchSequence(patterns=[" + "MatchValue(value=Constant(value=1, kind=None)), " + "MatchAs(pattern=None, name='other')]), guard=None" + ", body=[Expr(value=Constant(value=Ellipsis, kind" + "=None))])])], type_ignores=[])") + self.assertEqual(gast.dump(tree), norm) + + def test_MatchOr(self): + code = 'match v:\n case 1 | 2:...' + tree = gast.parse(code) + compile(gast.gast_to_ast(tree), '<test>', 'exec') + norm = ("Module(body=[Match(subject=Name(id='v', ctx=Load" + "(), annotation=None, type_comment=None), cases=[" + "match_case(pattern=MatchOr(patterns=[MatchValue(" + "value=Constant(value=1, kind=None)), MatchValue(" + "value=Constant(value=2, kind=None))]), guard=" + "None, body=[Expr(value=Constant(value=Ellipsis, " + "kind=None))])])], type_ignores=[])") + self.assertEqual(gast.dump(tree), norm) + + + if sys.version_info.minor >= 11: + + def test_TryStar(self): + code = ''' + try: ... + except *ValueError: ...''' + norm = ("Module(body=[TryStar(body=[Expr(value=" + "Constant(value=Ellipsis))], handlers=[" + "ExceptHandler(type=Name(id='ValueError', ctx" + "=Load()), body=[Expr(value=Constant(value=" + "Ellipsis))])], orelse=[], finalbody=[])], " + "type_ignores=[])") + pass + else: def test_Bytes(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gast-0.5.3/tox.ini new/gast-0.5.4/tox.ini --- old/gast-0.5.3/tox.ini 2021-11-13 22:38:20.000000000 +0100 +++ new/gast-0.5.4/tox.ini 2023-04-29 21:35:43.000000000 +0200 @@ -1,5 +1,5 @@ [tox] -envlist = py27,py34,py35,py36,py37,py38,py39,lint +envlist = py{27,34,35,36,37,38,39,310, 311, 312},lint [testenv] deps =