Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pyleri for openSUSE:Factory 
checked in at 2026-07-07 21:02:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyleri (Old)
 and      /work/SRC/openSUSE:Factory/.python-pyleri.new.1982 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pyleri"

Tue Jul  7 21:02:12 2026 rev:5 rq:1364109 version:1.5.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyleri/python-pyleri.changes      
2026-04-22 17:20:58.488954218 +0200
+++ /work/SRC/openSUSE:Factory/.python-pyleri.new.1982/python-pyleri.changes    
2026-07-07 21:04:11.744326010 +0200
@@ -1,0 +2,6 @@
+Mon Jul  6 19:34:23 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 1.5.1:
+  * Stop greedy choice after full input match
+
+-------------------------------------------------------------------

Old:
----
  pyleri-1.5.0.tar.gz

New:
----
  pyleri-1.5.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pyleri.spec ++++++
--- /var/tmp/diff_new_pack.2nU2of/_old  2026-07-07 21:04:13.848398861 +0200
+++ /var/tmp/diff_new_pack.2nU2of/_new  2026-07-07 21:04:13.852399000 +0200
@@ -19,7 +19,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-pyleri
-Version:        1.5.0
+Version:        1.5.1
 Release:        0
 Summary:        Python Left-Right Parser
 License:        MIT

++++++ pyleri-1.5.0.tar.gz -> pyleri-1.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.5.0/README.md new/pyleri-1.5.1/README.md
--- old/pyleri-1.5.0/README.md  2025-11-12 21:19:22.000000000 +0100
+++ new/pyleri-1.5.1/README.md  2026-07-06 13:30:45.000000000 +0200
@@ -1,5 +1,6 @@
 
[![CI](https://github.com/cesbit/pyleri/workflows/CI/badge.svg)](https://github.com/cesbit/pyleri/actions)
 [![Release 
Version](https://img.shields.io/github/release/cesbit/pyleri)](https://github.com/cesbit/pyleri/releases)
+[![Github 
stargazers](https://img.shields.io/github/stars/cesbit/pyleri)](https://github.com/cesbit/pyleri/stargazers)
 
 Python Left-Right Parser
 ========================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.5.0/examples/thingsdb_grammar.py 
new/pyleri-1.5.1/examples/thingsdb_grammar.py
--- old/pyleri-1.5.0/examples/thingsdb_grammar.py       1970-01-01 
01:00:00.000000000 +0100
+++ new/pyleri-1.5.1/examples/thingsdb_grammar.py       2026-07-06 
13:30:45.000000000 +0200
@@ -0,0 +1,245 @@
+"""ThingsDB (v1.8.2) language file.
+"""
+import re
+from pyleri import List
+from pyleri import Repeat
+from pyleri import Token
+from pyleri import Grammar
+from pyleri import Sequence
+from pyleri import Optional
+from pyleri import Tokens
+from pyleri import Ref
+from pyleri import Keyword
+from pyleri import Prio
+from pyleri import Regex
+from pyleri import THIS
+from pyleri import Choice
+
+
+class LangDef(Grammar):
+
+    RE_KEYWORDS = re.compile('^[A-Za-z_][0-9A-Za-z_]{0,254}(?![0-9A-Za-z_])')
+    x_array = Token('[')
+    x_assign = Tokens('+= -= *= /= %= &= ^= |= =')
+    x_block = Token('{')
+    x_chain = Tokens('.. .')
+    x_closure = Token('|')
+    x_function = Token('(')
+    x_index = Token('[')
+    x_parenthesis = Token('(')
+    x_preopr = Regex('^(\\s*~)*(\\s*!|\\s*[\\-+](?=[^0-9]))*')
+    x_ternary = Token('?')
+    x_thing = Token('{')
+    x_ano = Token('&{')
+    x_template = Token('`')
+    template = Sequence(
+        x_template,
+        Repeat(Choice(
+            Regex('^([^`{}]|``|{{|}})+'),
+            Sequence(
+                Token('{'),
+                THIS,
+                Token('}')
+            ),
+            most_greedy=False), 0, None),
+        x_template
+    )
+    t_false = Keyword('false')
+    t_float = Regex(
+        r'[-+]?(inf|nan|[0-9]*\.[0-9]+(e[+-][0-9]+)?)'
+        r'(?![0-9A-Za-z_\.])')
+    t_int = Regex(
+        r'[-+]?((0b[01]+)|(0o[0-8]+)|(0x[0-9a-fA-F]+)|([0-9]+))'
+        r'(?![0-9A-Za-z_\.])')
+    t_nil = Keyword('nil')
+    t_regex = Regex('^/((?:.(?!(?<![\\\\])/))*.?)/[a-z]*')
+    t_string = Regex('^(((?:\'(?:[^\']*)\')+)|((?:"(?:[^"]*)")+))')
+    t_true = Keyword('true')
+    name = Regex('^[A-Za-z_][0-9A-Za-z_]{0,254}(?![0-9A-Za-z_])')
+    var = Regex('^[A-Za-z_][0-9A-Za-z_]{0,254}(?![0-9A-Za-z_])')
+    chain = Ref()
+    closure = Sequence(
+        x_closure,
+        List(var, Token(','), 0, None, True),
+        Token('|'),
+        THIS
+    )
+    t_ano = Sequence(
+        x_ano,
+        List(Sequence(
+            name,
+            Token(':'),
+            Optional(THIS)
+        ), Token(','), 0, None, True),
+        Token('}')
+    )
+    thing = Sequence(
+        x_thing,
+        List(Sequence(
+            name,
+            Token(':'),
+            Optional(THIS)
+        ), Token(','), 0, None, True),
+        Token('}')
+    )
+    array = Sequence(
+        x_array,
+        List(THIS, Token(','), 0, None, True),
+        Token(']')
+    )
+    function = Sequence(
+        x_function,
+        List(THIS, Token(','), 0, None, True),
+        Token(')')
+    )
+    instance = Repeat(thing, 1, 1)
+    enum_ = Sequence(
+        x_thing,
+        Choice(
+            name,
+            closure,
+            most_greedy=False),
+        Token('}')
+    )
+    opr0_mul_div_mod = Tokens('* / %')
+    opr1_add_sub = Tokens('+ -')
+    opr2_bitwise_shift = Tokens('<< >>')
+    opr3_bitwise_and = Tokens('&')
+    opr4_bitwise_xor = Tokens('^')
+    opr5_bitwise_or = Tokens('|')
+    opr6_compare = Tokens('== != <= >= < >')
+    opr7_cmp_and = Token('&&')
+    opr8_cmp_or = Token('||')
+    opr9_ternary = Sequence(
+        x_ternary,
+        THIS,
+        Token(':')
+    )
+    operations = Sequence(
+        THIS,
+        Choice(
+            opr9_ternary,
+            opr8_cmp_or,
+            opr7_cmp_and,
+            opr2_bitwise_shift,
+            opr6_compare,
+            opr5_bitwise_or,
+            opr4_bitwise_xor,
+            opr3_bitwise_and,
+            opr1_add_sub,
+            opr0_mul_div_mod,
+            most_greedy=False),
+        THIS
+    )
+    assign = Sequence(
+        x_assign,
+        THIS
+    )
+    name_opt_more = Sequence(
+        name,
+        Optional(Choice(
+            function,
+            assign,
+            most_greedy=False))
+    )
+    var_opt_more = Sequence(
+        var,
+        Optional(Choice(
+            function,
+            assign,
+            instance,
+            enum_,
+            most_greedy=False))
+    )
+    slice = List(Optional(THIS), Token(':'), 0, 3, False)
+    index = Repeat(Sequence(
+        x_index,
+        slice,
+        Token(']'),
+        Optional(Sequence(
+            x_assign,
+            THIS
+        ))
+    ), 0, None)
+    block = Sequence(
+        x_block,
+        List(THIS, Repeat(Token(';'), 1, None), 1, None, True),
+        Token('}')
+    )
+    parenthesis = Sequence(
+        x_parenthesis,
+        THIS,
+        Token(')')
+    )
+    k_if = Keyword('if')
+    k_else = Keyword('else')
+    k_return = Keyword('return')
+    k_for = Keyword('for')
+    k_in = Keyword('in')
+    k_continue = Keyword('continue')
+    k_break = Keyword('break')
+    if_statement = Sequence(
+        k_if,
+        Token('('),
+        THIS,
+        Token(')'),
+        THIS,
+        Optional(Sequence(
+            k_else,
+            THIS
+        ))
+    )
+    return_statement = Sequence(
+        k_return,
+        List(THIS, Token(','), 0, 3, False)
+    )
+    for_statement = Sequence(
+        k_for,
+        Token('('),
+        List(var, Token(','), 1, None, False),
+        k_in,
+        THIS,
+        Token(')'),
+        THIS
+    )
+    expression = Sequence(
+        x_preopr,
+        Choice(
+            chain,
+            t_false,
+            t_nil,
+            t_true,
+            t_float,
+            t_int,
+            t_string,
+            t_regex,
+            t_ano,
+            template,
+            var_opt_more,
+            thing,
+            array,
+            parenthesis,
+            most_greedy=False),
+        index,
+        Optional(chain)
+    )
+    statement = Prio(
+        k_continue,
+        k_break,
+        Choice(
+            if_statement,
+            return_statement,
+            for_statement,
+            closure,
+            expression,
+            block,
+            most_greedy=False),
+        operations
+    )
+    START = List(statement, Repeat(Token(';'), 1, None), 0, None, True)
+    chain = Sequence(
+        x_chain,
+        name_opt_more,
+        index,
+        Optional(chain)
+    )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.5.0/pyleri/__init__.py 
new/pyleri-1.5.1/pyleri/__init__.py
--- old/pyleri-1.5.0/pyleri/__init__.py 2025-11-12 21:19:22.000000000 +0100
+++ new/pyleri-1.5.1/pyleri/__init__.py 2026-07-06 13:30:45.000000000 +0200
@@ -41,4 +41,4 @@
 __author__ = 'Jeroen van der Heijden'
 __maintainer__ = 'Jeroen van der Heijden'
 __email__ = '[email protected]'
-__version__ = '1.5.0'
+__version__ = '1.5.1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.5.0/pyleri/choice.py 
new/pyleri-1.5.1/pyleri/choice.py
--- old/pyleri-1.5.0/pyleri/choice.py   2025-11-12 21:19:22.000000000 +0100
+++ new/pyleri-1.5.1/pyleri/choice.py   2026-07-06 13:30:45.000000000 +0200
@@ -37,6 +37,8 @@
             if is_valid and pos > mg_pos:
                 node.children = children
                 mg_is_valid, mg_pos = is_valid, pos
+                if pos == root._len_string:
+                    break
 
         if mg_is_valid:
             root._append_tree(tree, node, mg_pos)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.5.0/setup.py new/pyleri-1.5.1/setup.py
--- old/pyleri-1.5.0/setup.py   2025-11-12 21:19:22.000000000 +0100
+++ new/pyleri-1.5.1/setup.py   2026-07-06 13:30:45.000000000 +0200
@@ -1,10 +1,7 @@
 """setup.py
-
-Upload to PyPI, Thx to: http://peterdowns.com/posts/first-time-with-pypi.html
-
-python3 setup.py sdist
-twine upload --repository pypitest dist/pyleri-x.x.x.tar.gz
-twine upload --repository pypi dist/pyleri-x.x.x.tar.gz
+python -m build
+twine upload --repository pypitest dist/pyleri-x.x.x*
+twine upload --repository pypi dist/pyleri-x.x.x*
 """
 from setuptools import setup
 from pyleri import __version__ as version
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.5.0/test/test_choice.py 
new/pyleri-1.5.1/test/test_choice.py
--- old/pyleri-1.5.0/test/test_choice.py        2025-11-12 21:19:22.000000000 
+0100
+++ new/pyleri-1.5.1/test/test_choice.py        2026-07-06 13:30:45.000000000 
+0200
@@ -7,10 +7,12 @@
 from pyleri import (
     KeywordError,
     create_grammar,
+    Repeat,
     Sequence,
     Choice,
     Keyword,
     Regex,
+    Token,
 )  # nopep8
 
 
@@ -28,6 +30,20 @@
         self.assertTrue(grammar.parse(' hi iris ').is_valid)
         self.assertFalse(grammar.parse(' hi sasha ').is_valid)
 
+    def test_choice_most_greedy_selects_full_match(self):
+        short = Token('a')
+        long = Token('aa')
+        grammar = create_grammar(Repeat(Choice(short, long)))
+
+        result = grammar.parse('aa')
+        repeat_node = result.tree.children[0]
+        choice_node = repeat_node.children[0]
+
+        self.assertTrue(result.is_valid)
+        self.assertEqual(len(repeat_node.children), 1)
+        self.assertEqual(choice_node.children[0].element, long)
+        self.assertEqual(choice_node.children[0].string, 'aa')
+
     def test_choice_first_match(self):
         k_hi = Keyword('hi')
         k_iris = Keyword('iris')

Reply via email to