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 2024-01-07 21:41:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyleri (Old)
 and      /work/SRC/openSUSE:Factory/.python-pyleri.new.28375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pyleri"

Sun Jan  7 21:41:07 2024 rev:2 rq:1137430 version:1.4.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyleri/python-pyleri.changes      
2021-07-31 18:51:23.370530553 +0200
+++ /work/SRC/openSUSE:Factory/.python-pyleri.new.28375/python-pyleri.changes   
2024-01-07 21:41:23.454395009 +0100
@@ -1,0 +2,16 @@
+Sun Jan  7 19:54:30 UTC 2024 - Dirk Müller <dmuel...@suse.com>
+
+- update to 1.4.2:
+  * Fixed typing for delimiter on the List type.
+  * Small PEP-8 fix.
+- update to 1.4.1:
+  * Added typing hints
+- update to 1.4.0:
+  * Extra keyword argument `line_number` to `.as_str(..)` method
+    to include the line number with the error.
+  * Regular expression object not with flags before the required
+    `^` character.
+- update to 1.3.4:
+  * Fixed bug with recursion in Prio element. (issue #18)
+
+-------------------------------------------------------------------

Old:
----
  pyleri-1.3.3.tar.gz

New:
----
  pyleri-1.4.2.tar.gz

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

Other differences:
------------------
++++++ python-pyleri.spec ++++++
--- /var/tmp/diff_new_pack.j5jNPK/_old  2024-01-07 21:41:23.894411015 +0100
+++ /var/tmp/diff_new_pack.j5jNPK/_new  2024-01-07 21:41:23.894411015 +0100
@@ -1,6 +1,7 @@
 #
 # spec file for package python-pyleri
 #
+# Copyright (c) 2024 SUSE LLC
 # Copyright (c) 2021, Martin Hauke <mar...@gmx.de>
 #
 # All modifications and additions to the file contributed by third parties
@@ -18,16 +19,18 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-pyleri
-Version:        1.3.3
+Version:        1.4.2
 Release:        0
 Summary:        Python Left-Right Parser
 License:        MIT
 URL:            https://github.com/transceptor-technology/pyleri
 Source:         
https://github.com/transceptor-technology/pyleri/archive/refs/tags/%{version}.tar.gz#/pyleri-%{version}.tar.gz
-BuildRequires:  python-rpm-macros
-BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module pytest}
+BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module wheel}
 BuildRequires:  fdupes
+BuildRequires:  python-rpm-macros
 BuildArch:      noarch
 %python_subpackages
 
@@ -38,10 +41,10 @@
 %setup -q -n pyleri-%{version}
 
 %build
-%python_build
+%pyproject_wheel
 
 %install
-%python_install
+%pyproject_install
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
@@ -49,6 +52,7 @@
 
 %files %{python_files}
 %license LICENSE.txt
-%doc ChangeLog README.md
-%{python_sitelib}/pyleri*
+%doc README.md
+%{python_sitelib}/pyleri
+%{python_sitelib}/pyleri-%{version}.dist-info
 

++++++ pyleri-1.3.3.tar.gz -> pyleri-1.4.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/.github/FUNDING.yml 
new/pyleri-1.4.2/.github/FUNDING.yml
--- old/pyleri-1.3.3/.github/FUNDING.yml        1970-01-01 01:00:00.000000000 
+0100
+++ new/pyleri-1.4.2/.github/FUNDING.yml        2023-03-16 09:49:04.000000000 
+0100
@@ -0,0 +1 @@
+github: cesbit
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/.github/workflows/ci.yml 
new/pyleri-1.4.2/.github/workflows/ci.yml
--- old/pyleri-1.3.3/.github/workflows/ci.yml   1970-01-01 01:00:00.000000000 
+0100
+++ new/pyleri-1.4.2/.github/workflows/ci.yml   2023-03-16 09:49:04.000000000 
+0100
@@ -0,0 +1,33 @@
+name: CI
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version: ["3.7", "3.8", "3.9", "3.10"]
+
+    steps:
+      - uses: actions/checkout@v3
+      - name: Set up Python ${{ matrix.python-version }}
+        uses: actions/setup-python@v4
+        with:
+          python-version: ${{ matrix.python-version }}
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install pytest pycodestyle
+          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+      - name: Run tests with pytest
+        run: |
+          pytest
+      - name: Lint with PyCodeStyle
+        run: |
+          find . -name \*.py -exec pycodestyle {} +
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/.travis.yml new/pyleri-1.4.2/.travis.yml
--- old/pyleri-1.3.3/.travis.yml        2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/.travis.yml        1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-language: python
-python:
-  - "3.4"
-  - "3.5"
-  - "3.6"
-before_install:
-  - pip install pycodestyle
-script:
-  - pytest -v
-  - find . -name \*.py -exec pycodestyle {} +
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/ChangeLog new/pyleri-1.4.2/ChangeLog
--- old/pyleri-1.3.3/ChangeLog  2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/ChangeLog  1970-01-01 01:00:00.000000000 +0100
@@ -1,79 +0,0 @@
-2020.12.01, Version 1.3.3 (Stable)
-
-  * Fixed bug with single and double quote characters in export. (issue #16)
-
-2018.10.29, Version 1.3.2 (Stable)
-
-  * Replace / with _ in function name.
-
-2018.10.25, Version 1.3.1 (Stable)
-
-  * Fixed exporting `Repeat` element to C. (issue #9)
-  * Added header file name option to `export_c()` method.
-
-2018.10.15, Version 1.3.0 (Stable)
-
-  * Added element properties:
-    - `Keyword.ign_case`
-    - `Choice.most_greedy`
-    - `List.min`, `List.max`, `List.opt_closing`
-    - `Repeat.min`, 'Repeat.max`
-  * Added `Result.as_str` for returning a textual parse result.
-  * Fixed correct expecting for `List` element.
-  * Added `MaxRecursionError` exception for `Prio` element.
-
-2018.07.09, Version 1.2.2 (Stable)
-
-  * Added export to JavaScript using class (es6) syntax.
-  * Use jsleri Ref.set() method instead of Object.assign.
-
-2018.07.05, Version 1.2.1 (Stable)
-
-  * Format readme on PyPi
-
-2018.07.05, Version 1.2.0 (Stable)
-
-  * Fixed typo in List mi/ma exception.
-  * Do not allow duplicate names in lower or upper case.
-  * Added export to Java for the jleri module.
-  * Fixed typo indentation.
-  * Added grammar check for missing START point.
-
-2017.06.23, Version 1.1.8 (Stable)
-
-  * Rename cleri_object_t to cleri_t.
-
-2017.06.22, Version 1.1.7 (Stable)
-
-  * Added support for cleri_dup() in export to C. (issue #5)
-  * Fixed header guards while exporting to C. (issue #6)
-
-2017.06.20, Version 1.1.6 (Stable)
-
-  * Fixed exporting ref to C. (issue #4)
-
-2017.03.13, Version 1.1.5 (Stable)
-
-  * Fixed exporting keywords (case sensitive) to C.
-  * Added export to Go language for the goleri module.
-
-2016.10.25, Version 1.1.4 (Stable)
-
-  * Fixed exporting Tokens to JavaScript and Python. (issue #2)
-
-2016.10.24, Version 1.1.3 (Stable)
-
-  * Added export to Python method. This can be useful even if the source is
-    already defined in Python language. (see issue #1)
-
-2016.07.02, Version 1.1.2 (Stable)
-
-  * Fixed export_c() to support Ref(). An update to cleri is not needed since
-    in C we can simply pre-define a variable and later assign the actual
-    object.
-
-2016.03.07, Version 1.1.0 (BETA)
-
-  * Added Ref() support which can be used to create forward references.
-  * Updated jsleri to support Ref() and updated export_js() method to support
-    this new class.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/LICENSE.txt new/pyleri-1.4.2/LICENSE.txt
--- old/pyleri-1.3.3/LICENSE.txt        2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/LICENSE.txt        2023-03-16 09:49:04.000000000 +0100
@@ -1,19 +1,19 @@
-Copyright (c) 2016 Jeroen van der Heijden / Transceptor Technology
+Copyright (c) 2021 Jeroen van der Heijden <jer...@cesbit.com>
 
-Permission is hereby granted, free of charge, to any person obtaining a copy 
of 
-this software and associated documentation files (the "Software"), to deal in 
-the Software without restriction, including without limitation the rights to 
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
-of the Software, and to permit persons to whom the Software is furnished to do 
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
 so, subject to the following conditions:
 
-The above copyright notice and this permission notice shall be included in all 
+The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/README.md new/pyleri-1.4.2/README.md
--- old/pyleri-1.3.3/README.md  2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/README.md  2023-03-16 09:49:04.000000000 +0100
@@ -1,6 +1,11 @@
+[![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)
+
 Python Left-Right Parser
 ========================
-Pyleri is an easy-to-use parser created for [SiriDB](http://siridb.net/). We 
first used [lrparsing](http://lrparsing.sourceforge.net/doc/html/) and wrote 
[jsleri](https://github.com/transceptor-technology/jsleri) for auto-completion 
and suggestions in our web console. Later we found small issues within the 
`lrparsing` module and also had difficulties keeping the language the same in 
all projects. That is when we decided to create Pyleri which can export a 
created grammar to JavaScript, C, Python, Go and Java.
+Pyleri is an easy-to-use parser created for [SiriDB](http://siridb.net/). We 
first used [lrparsing](http://lrparsing.sourceforge.net/doc/html/) and wrote 
[jsleri](https://github.com/cesbit/jsleri) for auto-completion and suggestions 
in our web console. Later we found small issues within the `lrparsing` module 
and also had difficulties keeping the language the same in all projects. That 
is when we decided to create Pyleri which can export a created grammar to 
JavaScript, C, Python, Go and Java.
+
+Gabriele Tomassetti [wrote a tutorial](https://tomassetti.me/pyleri-tutorial/) 
about the pyleri library.
 
 ---------------------------------------
   * [Related projects](#related-projects)
@@ -34,10 +39,10 @@
 
 ---------------------------------------
 ## Related projects
-- [jsleri](https://github.com/transceptor-technology/jsleri): JavaScript parser
-- [libcleri](https://github.com/transceptor-technology/libcleri): C parser
-- [goleri](https://github.com/transceptor-technology/goleri): Go parser
-- [jleri](https://github.com/transceptor-technology/jleri): Java parser
+- [jsleri](https://github.com/cesbit/jsleri): JavaScript parser
+- [libcleri](https://github.com/cesbit/libcleri): C parser
+- [goleri](https://github.com/cesbit/goleri): Go parser
+- [jleri](https://github.com/cesbit/jleri): Java parser
 
 ## Installation
 The easiest way is to use PyPI:
@@ -240,7 +245,7 @@
 import (
         "regexp"
 
-        "github.com/transceptor-technology/goleri"
+        "github.com/cesbit/goleri"
 )
 
 // Element indentifiers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/examples/json_grammar.py 
new/pyleri-1.4.2/examples/json_grammar.py
--- old/pyleri-1.3.3/examples/json_grammar.py   2020-12-01 21:35:27.000000000 
+0100
+++ new/pyleri-1.4.2/examples/json_grammar.py   2023-03-16 09:49:04.000000000 
+0100
@@ -1,4 +1,4 @@
-'''JSON Grammar.'''
+"""JSON Grammar."""
 from pyleri import (
     Ref,
     Choice,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/__init__.py 
new/pyleri-1.4.2/pyleri/__init__.py
--- old/pyleri-1.3.3/pyleri/__init__.py 2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/__init__.py 2023-03-16 09:49:04.000000000 +0100
@@ -1,4 +1,4 @@
-'''Py-LeRi (pyleri) Python LR-parsing module.
+"""Py-LeRi (pyleri) Python LR-parsing module.
 
 This module is inspired by lrparsing (http://lrparsing.sourceforge.net/),
 a Python parser written by Russell Stuart, 2014-05-29.
@@ -8,9 +8,9 @@
 Javascript JS-LeRi (jsleri) module so we can exchange grammars written by this
 module with JavaScript projects.
 
-:copyright: 2016, Jeroen van der Heijden (Transceptor Technology)
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
 :license: MIT
-'''
+"""
 
 from .choice import Choice
 from .endofstatement import end_of_statement
@@ -40,5 +40,5 @@
 
 __author__ = 'Jeroen van der Heijden'
 __maintainer__ = 'Jeroen van der Heijden'
-__email__ = 'jeroen@transceptor.technology'
-__version__ = '1.3.3'
+__email__ = 'jer...@cesbit.com'
+__version__ = '1.4.2'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/choice.py 
new/pyleri-1.4.2/pyleri/choice.py
--- old/pyleri-1.3.3/pyleri/choice.py   2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/choice.py   2023-03-16 09:49:04.000000000 +0100
@@ -1,27 +1,29 @@
-'''pyleri.Choice Class.
+"""pyleri.Choice Class.
 
 Choose one of the given elements. When most_greedy is True we will choose
 the 'longest' element when multiple elements are valid. If most_greedy is
 False we will return the first match.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
-
-from .elements import NamedElement, c_export, go_export, java_export
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+from .elements import Element, NamedElement, c_export, go_export, java_export
 
 
 class Choice(NamedElement):
 
     __slots__ = ('_elements', '_get_node_result')
 
-    def __init__(self, *elements, most_greedy=True):
+    def __init__(
+            self,
+            *elements: Element,
+            most_greedy: bool = True):
         self._elements = self._validate_elements(elements)
         self._get_node_result = \
             self._most_greedy_result if most_greedy else \
             self._stop_at_first_match
 
     @property
-    def most_greedy(self):
+    def most_greedy(self) -> bool:
         return self._get_node_result == self._most_greedy_result
 
     def _most_greedy_result(self, root, tree, rule, s, node):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/elements.py 
new/pyleri-1.4.2/pyleri/elements.py
--- old/pyleri-1.3.3/pyleri/elements.py 2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/elements.py 2023-03-16 09:49:04.000000000 +0100
@@ -1,18 +1,19 @@
-'''Element and NamedElement Class.
+"""Element and NamedElement Class.
 
 These are the base classes used for all other elements.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+import typing as t
 
 
-def camel_case(s):
+def camel_case(s: str) -> str:
     return ''.join(
         p[0].upper() + p[1:] if n else p
         for n, p in enumerate(s.split('_')))
 
 
-def cap_case(s):
+def cap_case(s: str) -> str:
     return ''.join(p[0].upper() + p[1:] for p in s.split('_') if p)
 
 
@@ -63,18 +64,20 @@
 
     __slots__ = tuple()
 
+    name: t.Optional[str]
+
     @staticmethod
-    def _validate_element(element):
+    def _validate_element(element: t.Union[str, 'Element']) -> 'Element':
         if isinstance(element, str):
             return Token(element)
         if isinstance(element, Element):
             return element
         raise TypeError(
-            'Expecting an element or string but received type: {}'.format(
-                type(element)))
+            'Expecting an element or string '
+            'but received type: {}'.format(type(element)))
 
     @classmethod
-    def _validate_elements(cls, elements):
+    def _validate_elements(cls, elements) -> t.List['Element']:
         return [cls._validate_element(elem) for elem in elements]
 
 
@@ -82,7 +85,12 @@
 
     __slots__ = ('name',)
 
-    def _export_js(self, js_indent, indent, classes, cname):
+    def _export_js(
+            self,
+            js_indent: int,
+            indent: int,
+            classes,
+            cname) -> str:
         classes.add(self.__class__.__name__.lstrip('_'))
         if hasattr(self, 'name') and indent > 0:
             return '{}.{}'.format(cname, self.name) if cname else self.name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/endofstatement.py 
new/pyleri-1.4.2/pyleri/endofstatement.py
--- old/pyleri-1.3.3/pyleri/endofstatement.py   2020-12-01 21:35:27.000000000 
+0100
+++ new/pyleri-1.4.2/pyleri/endofstatement.py   2023-03-16 09:49:04.000000000 
+0100
@@ -1,10 +1,10 @@
-'''end_of_statement Variable.
+"""end_of_statement Variable.
 
 end_of_statement is an instance of _EndOfStatement and will be added to
 an 'expecting' in a node result when an 'End of Statement' is possible.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 
 
 class _EndOfStatement:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/exceptions.py 
new/pyleri-1.4.2/pyleri/exceptions.py
--- old/pyleri-1.3.3/pyleri/exceptions.py       2020-12-01 21:35:27.000000000 
+0100
+++ new/pyleri-1.4.2/pyleri/exceptions.py       2023-03-16 09:49:04.000000000 
+0100
@@ -1,7 +1,7 @@
-'''Exceptions.
+"""Exceptions.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 
 
 class CompileError(Exception):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/expecting.py 
new/pyleri-1.4.2/pyleri/expecting.py
--- old/pyleri-1.3.3/pyleri/expecting.py        2020-12-01 21:35:27.000000000 
+0100
+++ new/pyleri-1.4.2/pyleri/expecting.py        2023-03-16 09:49:04.000000000 
+0100
@@ -1,11 +1,14 @@
-'''Expecting Class.
+"""Expecting Class.
 
 Expecting Class is used to return possible elements at a position when a given
 statement is not correct. This helps building auto-completion, suggestions or
 returning nice messages to the user.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+import typing as t
+if t.TYPE_CHECKING:
+    from .elements import Element
 
 
 class Expecting:
@@ -13,12 +16,12 @@
     __slots__ = ('required', 'optional', 'pos', '_modes')
 
     def __init__(self):
-        self.required = set()
-        self.optional = set()
-        self.pos = 0
-        self._modes = {self.pos: self.required}
+        self.required: t.Set['Element'] = set()
+        self.optional: t.Set['Element'] = set()
+        self.pos: int = 0
+        self._modes: t.Dict[int, t.Set['Element']] = {self.pos: self.required}
 
-    def set_mode_required(self, pos, is_required):
+    def set_mode_required(self, pos: int, is_required: bool):
         # do nothing when mode is already set to optional
         if pos in self._modes and self._modes[pos] is self.optional:
             return
@@ -29,7 +32,7 @@
         self.required.clear()
         self.optional.clear()
 
-    def update(self, element, pos):
+    def update(self, element: 'Element', pos: int):
         if pos > self.pos:
             self.empty()
             self.pos = pos
@@ -37,5 +40,5 @@
         if pos == self.pos:
             self._modes[pos].add(element)
 
-    def get_expecting(self):
+    def get_expecting(self) -> t.Set['Element']:
         return self.required | self.optional
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/grammar.py 
new/pyleri-1.4.2/pyleri/grammar.py
--- old/pyleri-1.3.3/pyleri/grammar.py  2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/grammar.py  2023-03-16 09:49:04.000000000 +0100
@@ -1,4 +1,4 @@
-'''pyleri.Grammar Class.
+"""pyleri.Grammar Class.
 
 When creating a new grammar this class should be used as the base class.
 
@@ -8,8 +8,8 @@
     ...
 
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 
 
 import re
@@ -284,7 +284,7 @@
 import (
 \t"regexp"
 
-\t"github.com/transceptor-technology/goleri"
+\t"github.com/cesbit/goleri"
 )
 
 // Element indentifiers
@@ -328,11 +328,11 @@
 '''.lstrip()
 
     def __init__(self):
-        '''Initialize the grammar.
+        """Initialize the grammar.
 
         Note: usually you should only initialize a Grammar instance
         once in a project.
-        '''
+        """
         self._element = self.START
         self._string = None
         self._expecting = None
@@ -342,14 +342,14 @@
             self,
             js_module_name=JS_MODULE_NAME,
             js_template=JS_ES6_IMPORT_EXPORT_TEMPLATE,
-            js_indent=JS_INDENTATION):
-        '''Export the grammar to a JavaScript file which can be
+            js_indent=JS_INDENTATION) -> str:
+        """Export the grammar to a JavaScript file which can be
         used with the js-lrparsing module.
 
         Two templates are available:
             Grammar.JS_WINDOW_TEMPLATE
             Grammar.JS_ES6_IMPORT_EXPORT_TEMPLATE (default)
-        '''
+        """
 
         language = []
         refs = []
@@ -405,11 +405,11 @@
             self,
             py_module_name=PY_MODULE_NAME,
             py_template=PY_TEMPLATE,
-            py_indent=PY_INDENTATION):
-        '''Export the grammar to a python file which can be
+            py_indent=PY_INDENTATION) -> str:
+        """Export the grammar to a python file which can be
         used with the pyleri module. This can be useful when python code
         if used to auto-create a grammar and an export of the final result is
-        required.'''
+        required."""
 
         language = []
         classes = {'Grammar'}
@@ -449,9 +449,13 @@
                     ' '.join(['from', py_module_name, 'import', n])
                     for n in classes if n != 'Rule'])))
 
-    def export_c(self, target=C_TARGET, c_indent=C_INDENTATION, headerf=None):
-        '''Export the grammar to a c (source and header) file which can be
-        used with the libcleri module.'''
+    def export_c(
+            self,
+            target=C_TARGET,
+            c_indent=C_INDENTATION,
+            headerf=None) -> str:
+        """Export the grammar to a c (source and header) file which can be
+        used with the libcleri module."""
         language = []
         indent = 0
         enums = set()
@@ -517,9 +521,9 @@
             self,
             go_template=GO_TEMPLATE,
             go_indent=GO_INDENTATION,
-            go_package=GO_PACKAGE):
-        '''Export the grammar to a Go file which can be
-        used with the goleri module.'''
+            go_package=GO_PACKAGE) -> str:
+        """Export the grammar to a Go file which can be
+        used with the goleri module."""
 
         language = []
         enums = set()
@@ -568,9 +572,9 @@
             java_template=JAVA_TEMPLATE,
             java_indent=JAVA_INDENTATION,
             java_package=JAVA_PACKAGE,
-            is_public=True):
-        '''Export the grammar to a Java file which can be
-        used with the jleri module.'''
+            is_public=True) -> str:
+        """Export the grammar to a Java file which can be
+        used with the jleri module."""
 
         language = []
         enums = set()
@@ -629,8 +633,8 @@
             enums=enum_str,
             public='public ' if is_public else '')
 
-    def parse(self, string):
-        '''Parse some string to the Grammar.
+    def parse(self, string) -> Result:
+        """Parse some string to the Grammar.
 
         Returns a nodeResult with the following attributes:
          - is_valid: True when the string is successfully parsed
@@ -641,7 +645,7 @@
                       'pos' in the string.
          - tree: the parse_tree containing a structured
                  result for the given string.
-        '''
+        """
         self._string = string
         self._expecting = Expecting()
         self._cached_kw_match.clear()
@@ -653,7 +657,8 @@
             0,
             tree.children,
             self._element,
-            True))
+            True),
+            tree)
 
         # get rest if anything
         rest = self._string[node_res.pos:].lstrip()
@@ -673,8 +678,6 @@
         if not node_res.is_valid:
             node_res.pos = self._expecting.pos
 
-        node_res.tree = tree
-
         return node_res
 
     def _append_tree(self, tree, node, pos):
@@ -693,7 +696,9 @@
         return element._get_node_result(self, tree, rule, self._s, node)
 
 
-def create_grammar(elem, re_keywords=_RE_KEYWORDS):
+def create_grammar(
+        elem: Element,
+        re_keywords: 're.Pattern' = _RE_KEYWORDS) -> Grammar:
     class _Grammar(Grammar):
         RE_KEYWORDS = _RE_KEYWORDS
         START = elem
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/keyword.py 
new/pyleri-1.4.2/pyleri/keyword.py
--- old/pyleri-1.3.3/pyleri/keyword.py  2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/keyword.py  2023-03-16 09:49:04.000000000 +0100
@@ -1,11 +1,11 @@
-'''pyleri.Keyword Class.
+"""pyleri.Keyword Class.
 
 Try matching a given keyword string. The keyword should match
 Grammer.RE_KEYWORDS otherwise the keyword will not be found. It's possible
 however to overwrite the default RE_KEYWORDS in you own Grammar class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 from .elements import NamedElement, c_export, go_export, java_export
 
 
@@ -13,7 +13,7 @@
 
     __slots__ = ('_keyword', '_ign_case')
 
-    def __init__(self, keyword, ign_case=False):
+    def __init__(self, keyword: str, ign_case: bool = False):
 
         if not isinstance(keyword, str):
             raise TypeError(
@@ -23,7 +23,7 @@
         self._ign_case = bool(ign_case)
 
     @property
-    def ign_case(self):
+    def ign_case(self) -> bool:
         return self._ign_case
 
     def __repr__(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/list.py 
new/pyleri-1.4.2/pyleri/list.py
--- old/pyleri-1.3.3/pyleri/list.py     2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/list.py     2023-03-16 09:49:04.000000000 +0100
@@ -1,4 +1,4 @@
-'''pyleri.List Class.
+"""pyleri.List Class.
 
 The grammar must find given elements separated by a delimiter. When no
 delimiter is given we split using a comma. All arguments:
@@ -9,16 +9,23 @@
     ma: Maximum elements the parser will search for. (default: None, unlimited)
     opt: When set to True the list may end with a delimiter. (default: False)
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
-from .elements import NamedElement, c_export, go_export, java_export
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+import typing as t
+from .elements import Element, NamedElement, c_export, go_export, java_export
 
 
 class List(NamedElement):
 
     __slots__ = ('_element', '_delimiter', '_min', '_max', '_opt')
 
-    def __init__(self, element, delimiter=',', mi=0, ma=None, opt=False):
+    def __init__(
+            self,
+            element: Element,
+            delimiter: t.Union[str, Element] = ',',
+            mi: int = 0,
+            ma: t.Optional[int] = None,
+            opt: bool = False):
         self._element, self._delimiter = \
             map(self._validate_element, (element, delimiter))
 
@@ -38,15 +45,15 @@
         self._opt = bool(opt)
 
     @property
-    def min(self):
+    def min(self) -> int:
         return self._min
 
     @property
-    def max(self):
+    def max(self) -> t.Optional[int]:
         return self._max
 
     @property
-    def opt_closing(self):
+    def opt_closing(self) -> bool:
         return self._opt
 
     @property
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/node.py 
new/pyleri-1.4.2/pyleri/node.py
--- old/pyleri-1.3.3/pyleri/node.py     2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/node.py     2023-03-16 09:49:04.000000000 +0100
@@ -1,20 +1,28 @@
-'''Node class.
+"""Node class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+import typing as t
+if t.TYPE_CHECKING:
+    from .elements import Element
 
 
 class Node:
 
     __slots__ = ('element', '_string', 'start', 'end', 'children')
 
-    def __init__(self, element, string, start, end=None):
+    def __init__(
+            self,
+            element: 'Element',
+            string: str,
+            start: int,
+            end: t.Optional[int] = None):
         self.element = element
         self.start = start
         self.end = end
         self._string = string
-        self.children = []
+        self.children: t.List['Node'] = []
 
     @property
-    def string(self):
+    def string(self) -> str:
         return self._string[self.start:self.end]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/optional.py 
new/pyleri-1.4.2/pyleri/optional.py
--- old/pyleri-1.3.3/pyleri/optional.py 2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/optional.py 2023-03-16 09:49:04.000000000 +0100
@@ -1,7 +1,7 @@
-'''Optional class.
+"""Optional class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 from .elements import NamedElement, c_export, go_export, java_export
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/prio.py 
new/pyleri-1.4.2/pyleri/prio.py
--- old/pyleri-1.3.3/pyleri/prio.py     2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/prio.py     2023-03-16 09:49:04.000000000 +0100
@@ -1,8 +1,8 @@
-'''Prio class.
+"""Prio class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
-from .elements import NamedElement
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+from .elements import NamedElement, Element
 from .rule import Rule
 from .exceptions import MaxRecursionError
 
@@ -13,7 +13,7 @@
 
     __slots__ = ('_elements', '_name')
 
-    def __init__(self, *elements):
+    def __init__(self, *elements: Element):
         self._elements = self._validate_elements(elements)
 
     def _get_node_result(self, root, tree, rule, s, node):
@@ -34,6 +34,8 @@
                 node.children = rule._tree[node.start] = children
                 rule._tested[node.start] = is_valid, pos
 
+        rule._depth -= 1
+
         if rule._tested[node.start][0]:
             root._append_tree(tree, node, rule._tested[node.start][1])
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/ref.py 
new/pyleri-1.4.2/pyleri/ref.py
--- old/pyleri-1.3.3/pyleri/ref.py      2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/ref.py      2023-03-16 09:49:04.000000000 +0100
@@ -1,16 +1,16 @@
-'''pyleri.Ref Class.
+"""pyleri.Ref Class.
 
 When a forward reference is used the grammar must contain a final
 reference with the same name. The Grammar class is used to validate
 a valid grammer and set element.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
-from .elements import NamedElement
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+from .elements import NamedElement, Element
 
 
 class Ref(NamedElement):
-    '''Ref class.'''
+    """Ref class."""
 
     __slots__ = ('_element', '_get_node_result')
 
@@ -19,7 +19,7 @@
         return getattr(self, '_element', None)
 
     @element.setter
-    def element(self, element):
+    def element(self, element: Element):
         self._element = self._validate_element(element)
         self._get_node_result = self._element._get_node_result
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/regex.py 
new/pyleri-1.4.2/pyleri/regex.py
--- old/pyleri-1.3.3/pyleri/regex.py    2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/regex.py    2023-03-16 09:49:04.000000000 +0100
@@ -1,18 +1,35 @@
-'''Regex class.
+"""Regex class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 import re
 from .elements import NamedElement, c_export, go_export, java_export
 
+_RE_FLAGS = re.compile(
+    r'^('
+    r'(\(\?i\))|'
+    r'(\(\?m\))|'
+    r'(\(\?s\))|'
+    r'(\(\?A\))|'
+    r'(\(\?x\))|'
+    r'(\(\?X\))|'
+    r'(\(\?U\))|'
+    r'(\(\?:\))'
+    r')(.)')
+
 
 class Regex(NamedElement):
 
     __slots__ = ('_compiled',)
 
-    def __init__(self, pattern, flags=0):
+    def __init__(self, pattern: str, flags: int = 0):
         if not pattern.startswith('^'):
-            pattern = '^' + pattern
+            m = _RE_FLAGS.match(pattern)
+            if not m:
+                pattern = '^' + pattern
+            elif m.group(2) != '^':
+                pos = m.end() - 1
+                pattern = pattern[:pos] + '^' + pattern[pos:]
         assert flags == 0 or flags == re.IGNORECASE, \
             'Only re.IGNORECASE is currently accepted as flag'
         self._compiled = re.compile(pattern, flags=flags)
@@ -44,7 +61,7 @@
 
     @c_export
     def _run_export_c(self, c_indent, indent, enums, gid):
-        assert not(self._compiled.flags & re.IGNORECASE), \
+        assert not (self._compiled.flags & re.IGNORECASE), \
             'libcleri has currently no support for the re.IGNORECASE flag'
         return 'cleri_regex({}, "{}")'.format(
             gid,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/repeat.py 
new/pyleri-1.4.2/pyleri/repeat.py
--- old/pyleri-1.3.3/pyleri/repeat.py   2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/repeat.py   2023-03-16 09:49:04.000000000 +0100
@@ -1,20 +1,25 @@
-'''Repeat class.
+"""Repeat class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
-from .elements import NamedElement, c_export, go_export, java_export
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+import typing as t
+from .elements import Element, NamedElement, c_export, go_export, java_export
 
 
 class Repeat(NamedElement):
 
     __slots__ = ('_element', '_min', '_max')
 
-    def __init__(self, element, mi=0, ma=None):
+    def __init__(
+            self,
+            element: Element,
+            mi: int = 0,
+            ma: t.Optional[int] = None):
         self._element = self._validate_element(element)
 
         if not isinstance(mi, int) or mi < 0:
             raise TypeError('Repeat(): "mi" must be an integer value larger '
-                            'than or equal to 0, got: {}'.format(mi))
+                            'than or equal to 0, got: {mi}'.format(mi))
 
         self._min = mi
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/result.py 
new/pyleri-1.4.2/pyleri/result.py
--- old/pyleri-1.3.3/pyleri/result.py   2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/result.py   2023-03-16 09:49:04.000000000 +0100
@@ -1,11 +1,15 @@
-'''Result class.
+"""Result class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+import typing as t
 from .keyword import Keyword
 from .token import Token
 from .tokens import Tokens
 from .endofstatement import _EndOfStatement
+if t.TYPE_CHECKING:
+    from .node import Node
+    from .expecting import Expecting
 
 
 TOSTR = (Keyword, Token, Tokens, _EndOfStatement)
@@ -15,16 +19,22 @@
 
     __slots__ = ('is_valid', 'pos', 'expecting', 'tree')
 
-    def __init__(self, is_valid, pos):
-        self.is_valid = is_valid
-        self.pos = pos
-        self.expecting = None
-        self.tree = None
+    def __init__(self, is_valid: bool, pos: int, tree: 'Node'):
+        self.is_valid: bool = is_valid
+        self.pos: int = pos
+        self.expecting: t.Optional['Expecting'] = None
+        self.tree: 'Node' = tree
 
-    def as_str(self, translate=None):
+    def as_str(self, translate=None, line_number=False):
         if self.is_valid:
             return 'parsed successfully'
-        res = ['error at position {}'.format(self.pos)]
+        if line_number:
+            string = self.tree._string
+            lnr = string.count('\n', 0, self.pos) + 1
+            pos = self.pos - string.rfind('\n', 0, self.pos)
+            res = ['error at line {}, col {}'.format(lnr, pos)]
+        else:
+            res = ['error at position {}'.format(self.pos)]
         arr = []
         for elem in (self.expecting):
             expectstr = translate(elem) if translate else None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/rule.py 
new/pyleri-1.4.2/pyleri/rule.py
--- old/pyleri-1.3.3/pyleri/rule.py     2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/rule.py     2023-03-16 09:49:04.000000000 +0100
@@ -1,15 +1,15 @@
-'''Rule class.
+"""Rule class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
-from .elements import NamedElement
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+from .elements import NamedElement, Element
 
 
 class Rule(NamedElement):
 
     __slots__ = ('_element', '_tested', '_tree', '_depth')
 
-    def __init__(self, element):
+    def __init__(self, element: Element):
         self._element = element
 
     def _get_node_result(self, root, tree, rule, _s, node):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/sequence.py 
new/pyleri-1.4.2/pyleri/sequence.py
--- old/pyleri-1.3.3/pyleri/sequence.py 2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/sequence.py 2023-03-16 09:49:04.000000000 +0100
@@ -1,15 +1,15 @@
-'''Sequence class.
+"""Sequence class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
-from .elements import NamedElement, c_export
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
+from .elements import Element, NamedElement, c_export
 
 
 class Sequence(NamedElement):
 
     __slots__ = ('_elements',)
 
-    def __init__(self, *elements):
+    def __init__(self, *elements: Element):
         self._elements = self._validate_elements(elements)
 
     def _get_node_result(self, root, tree, rule, _s, node):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/this.py 
new/pyleri-1.4.2/pyleri/this.py
--- old/pyleri-1.3.3/pyleri/this.py     2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/this.py     2023-03-16 09:49:04.000000000 +0100
@@ -1,7 +1,7 @@
-'''This class and THIS instance.
+"""This class and THIS instance.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 from .elements import Element
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/token.py 
new/pyleri-1.4.2/pyleri/token.py
--- old/pyleri-1.3.3/pyleri/token.py    2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/token.py    2023-03-16 09:49:04.000000000 +0100
@@ -1,7 +1,7 @@
-'''Token class.
+"""Token class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 from .elements import NamedElement, c_export, go_export, java_export
 
 
@@ -9,7 +9,7 @@
 
     __slots__ = ('_token',)
 
-    def __init__(self, token):
+    def __init__(self, token: str):
         if not isinstance(token, str):
             raise TypeError('Token(): first argument must be a string '
                             'value, got {}'.format(token))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/pyleri/tokens.py 
new/pyleri-1.4.2/pyleri/tokens.py
--- old/pyleri-1.3.3/pyleri/tokens.py   2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/pyleri/tokens.py   2023-03-16 09:49:04.000000000 +0100
@@ -1,7 +1,7 @@
-'''Tokens class.
+"""Tokens class.
 
-:copyright: 2018, Jeroen van der Heijden (Transceptor Technology)
-'''
+:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com>
+"""
 from .elements import NamedElement, c_export, go_export, java_export
 
 
@@ -9,7 +9,7 @@
 
     __slots__ = ('_tokens',)
 
-    def __init__(self, tokens):
+    def __init__(self, tokens: str):
         self._tokens = tokens.split()
         self._tokens.sort(key=len, reverse=True)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/setup.py new/pyleri-1.4.2/setup.py
--- old/pyleri-1.3.3/setup.py   2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/setup.py   2023-03-16 09:49:04.000000000 +0100
@@ -23,10 +23,10 @@
     long_description=long_description,
     long_description_content_type='text/markdown',
     author='Jeroen van der Heijden',
-    author_email='jeroen@transceptor.technology',
-    url='https://github.com/transceptor-technology/pyleri',
+    author_email='jer...@cesbit.com',
+    url='https://github.com/cesbit/pyleri',
     download_url=(
-        'https://github.com/transceptor-technology/'
+        'https://github.com/cesbit/'
         'pyleri/tarball/{}'.format(version)),
     keywords=['parser', 'grammar', 'autocompletion'],
     classifiers=[
@@ -35,12 +35,10 @@
         'License :: OSI Approved :: MIT License',
         'Operating System :: OS Independent',
         'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.0',
-        'Programming Language :: Python :: 3.1',
-        'Programming Language :: Python :: 3.2',
-        'Programming Language :: Python :: 3.3',
-        'Programming Language :: Python :: 3.4',
-        'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
+        'Programming Language :: Python :: 3.9',
+        'Programming Language :: Python :: 3.10',
         'Programming Language :: Python :: 3 :: Only',
         'Topic :: Software Development :: Libraries :: Python Modules',
         'Topic :: Text Processing :: Linguistic'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/test/test_json_lang.py 
new/pyleri-1.4.2/test/test_json_lang.py
--- old/pyleri-1.3.3/test/test_json_lang.py     2020-12-01 21:35:27.000000000 
+0100
+++ new/pyleri-1.4.2/test/test_json_lang.py     2023-03-16 09:49:04.000000000 
+0100
@@ -17,7 +17,7 @@
     def test_json(self):
         grammar = JsonGrammar()
         # should be true
-        self.assertTrue(grammar.parse('''
+        self.assertTrue(grammar.parse("""
             {
                 "hoi \\"Iris\\"": [
                     5,
@@ -27,7 +27,7 @@
                         "b": false
                     }
                 ]
-            }''').is_valid)
+            }""").is_valid)
 
         # keys must be strings
         self.assertFalse(grammar.parse('{5: true}').is_valid)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/test/test_list.py 
new/pyleri-1.4.2/test/test_list.py
--- old/pyleri-1.3.3/test/test_list.py  2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/test/test_list.py  2023-03-16 09:49:04.000000000 +0100
@@ -63,6 +63,18 @@
             'error at position 0, expecting: hi'
         )
 
+        self.assertEqual(
+            grammar.parse('').as_str(line_number=True),
+            'error at line 1, col 1, expecting: hi'
+        )
+
+        self.assertEqual(
+            grammar.parse("""
+                hi-hi-hi-hi-hi
+            """).as_str(line_number=True),
+            'error at line 2, col 26, expecting: end_of_statement'
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/test/test_prio.py 
new/pyleri-1.4.2/test/test_prio.py
--- old/pyleri-1.3.3/test/test_prio.py  2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/test/test_prio.py  2023-03-16 09:49:04.000000000 +0100
@@ -10,6 +10,7 @@
     Sequence,
     Keyword,
     Prio,
+    List,
     THIS,
     MaxRecursionError,
 )  # nopep8
@@ -46,6 +47,28 @@
                 ')))))))))))))))))))))))))))))))))))))))))))))))))))'
             )
 
+    def test_prio_list(self):
+        arr = Sequence('[', List(THIS), ']')
+        prio = Prio(Keyword('nil'), arr)
+        grammar = create_grammar(prio)
+        self.assertTrue(grammar.parse('[]').is_valid)
+        self.assertTrue(grammar.parse('[[nil]]').is_valid)
+        self.assertTrue(
+            grammar.parse(
+                '['
+                'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,'
+                'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,'
+                'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,'
+                'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,'
+                'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,'
+                'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil'
+                ']').is_valid)
+        with self.assertRaises(MaxRecursionError):
+            grammar.parse(
+                '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[hi'
+                ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
+            )
+
 
 if __name__ == '__main__':
     unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyleri-1.3.3/test/test_regex.py 
new/pyleri-1.4.2/test/test_regex.py
--- old/pyleri-1.3.3/test/test_regex.py 2020-12-01 21:35:27.000000000 +0100
+++ new/pyleri-1.4.2/test/test_regex.py 2023-03-16 09:49:04.000000000 +0100
@@ -28,6 +28,15 @@
                 if elem is regex else None),
             'error at position 0, expecting: single_quoted_string'
         )
+        self.assertTrue(grammar.parse("'hi'").is_valid)
+
+    def test_flags_regex(self):
+        regex = Regex(r'(?s)//.*?(\r?\n|$)')
+        grammar = create_grammar(regex)
+
+        self.assertTrue(grammar.parse("""
+                //test
+        """).is_valid)
 
 
 if __name__ == '__main__':

Reply via email to