From 56dddc358fc774383e3dd4b14afc493ff0f22408 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 16 Jul 2026 12:04:20 +0200 Subject: [PATCH 1/6] feat: typing Signed-off-by: Jan Kowalleck --- .mypy.ini | 34 +++++++++++++++++++++++++++ pyproject.toml | 3 +++ src/rfc3987_syntax2/py.typed | 1 + src/rfc3987_syntax2/syntax_helpers.py | 8 ++++--- src/rfc3987_syntax2/utils.py | 2 +- tests/__init__.py | 4 ++-- tests/test_syntax.py | 4 ++-- 7 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 .mypy.ini create mode 100644 src/rfc3987_syntax2/py.typed diff --git a/.mypy.ini b/.mypy.ini new file mode 100644 index 0000000..13fb917 --- /dev/null +++ b/.mypy.ini @@ -0,0 +1,34 @@ +[mypy] + +files = src/ + +show_error_codes = True +pretty = True + +warn_unreachable = True +allow_redefinition = False + +# ignore_missing_imports = False +# follow_imports = normal +# follow_imports_for_stubs = True + +### Strict mode ### +warn_unused_configs = True +disallow_subclassing_any = True +disallow_any_generics = True +disallow_untyped_calls = True +disallow_untyped_defs = True +disallow_incomplete_defs = True +check_untyped_defs = True +disallow_untyped_decorators = True +no_implicit_optional = True +warn_redundant_casts = True +warn_unused_ignores = True +warn_return_any = True +no_implicit_reexport = True + +[mypy-pytest.*] +ignore_missing_imports = True + +[mypy-tests.*] +disallow_untyped_decorators = False \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 43251d8..17bf8f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,9 @@ Issues = "https://github.com/jkowalleck/rfc3987-syntax2/issues" Source = "https://github.com/jkowalleck/rfc3987-syntax2" [project.optional-dependencies] +typing = [ + "mypy>=1.20,<3", +] testing = [ "typing_extensions>=4.16.0", "pytest>=8.3.5", diff --git a/src/rfc3987_syntax2/py.typed b/src/rfc3987_syntax2/py.typed new file mode 100644 index 0000000..161a597 --- /dev/null +++ b/src/rfc3987_syntax2/py.typed @@ -0,0 +1 @@ +# see https://peps.python.org/pep-0561/ \ No newline at end of file diff --git a/src/rfc3987_syntax2/syntax_helpers.py b/src/rfc3987_syntax2/syntax_helpers.py index 117a2ce..2e3876e 100644 --- a/src/rfc3987_syntax2/syntax_helpers.py +++ b/src/rfc3987_syntax2/syntax_helpers.py @@ -1,3 +1,5 @@ +from typing import Callable + from lark import Lark, ParseTree, exceptions from pathlib import Path @@ -54,7 +56,7 @@ def parse(term: str, value: str) -> ParseTree: return syntax_parser.parse(value, start=term) -def is_valid_syntax(term: str, value: str): +def is_valid_syntax(term: str, value: str) -> bool: try: parse(term=term, value=value) return True @@ -62,10 +64,10 @@ def is_valid_syntax(term: str, value: str): return False -def make_syntax_validator(rule_name): +def make_syntax_validator(rule_name: str) -> Callable[[str], bool]: parser = Lark(grammar, start=rule_name, parser=RFC3987_SYNTAX_PARSER_TYPE) - def syntax_validator(text): + def syntax_validator(text: str) -> bool: try: parser.parse(text) return True diff --git a/src/rfc3987_syntax2/utils.py b/src/rfc3987_syntax2/utils.py index a310886..af16a5d 100644 --- a/src/rfc3987_syntax2/utils.py +++ b/src/rfc3987_syntax2/utils.py @@ -1,6 +1,6 @@ from pathlib import Path -def load_grammar(path: Path): +def load_grammar(path: Path) -> str: with open(path, "r", encoding="utf-8") as file: return file.read() diff --git a/tests/__init__.py b/tests/__init__.py index d6eb5d2..553eb81 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -23,8 +23,8 @@ class SyntaxCase(TypedDict): def valid_syntax_data() -> T_syntax_file: with open(TESTS_DATA_FILES['valid_syntax'], "r", encoding="utf-8") as f: - return json.load(f) + return json.load(f) # type:ignore def invalid_syntax_data() -> T_syntax_file: with open(TESTS_DATA_FILES['invalid_syntax'], "r", encoding="utf-8") as f: - return json.load(f) \ No newline at end of file + return json.load(f) # type:ignore \ No newline at end of file diff --git a/tests/test_syntax.py b/tests/test_syntax.py index e50a767..4262b88 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -1,14 +1,14 @@ from typing import TYPE_CHECKING import pytest -from typing import Callable +from typing import Any, Callable import rfc3987_syntax2 as sut from . import valid_syntax_data, invalid_syntax_data, SyntaxCase, T_syntax_file -def syntax_data_as_params(src_cb: Callable[[], T_syntax_file]): +def syntax_data_as_params(src_cb: Callable[[], T_syntax_file]) -> Any: for term, examples in src_cb().items(): for example in examples: yield pytest.param(term, example, id=f"{term}-{example['value']}") From 11fca17e6904afb8b2782bed6bf172ca1eb25de7 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 16 Jul 2026 12:12:01 +0200 Subject: [PATCH 2/6] feat: typing Signed-off-by: Jan Kowalleck --- .github/workflows/python-tests.yml | 28 ++++++++++++++++++++++++++++ pyproject.toml | 4 +--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 72d5a39..4cd8c66 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -27,6 +27,34 @@ permissions: contents: read jobs: + static-code-analysis: + name: StaticCodingAnalysis (py${{ matrix.python-version}} ${{ matrix.toxenv-factors }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + include: + - python-version: '3.14' # latest + os: ubuntu-latest + - python-version: '3.9' # lowest + os: ubuntu-latest + steps: + - name: Checkout + # see https://github.com/actions/checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Setup Python Environment + # see https://github.com/actions/setup-python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: ${{ matrix.python-version }} + architecture: 'x64' + - name: Install project + run: pip install --user -e ".[testing]" + - name: Run Tests + run: python -m mypy -v build-and-test: name: Test (${{ matrix.os }} py${{ matrix.python-version }} ${{ matrix.toxenv-factors }}) runs-on: ${{ matrix.os }} diff --git a/pyproject.toml b/pyproject.toml index 17bf8f7..cadd02e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,10 +40,8 @@ Issues = "https://github.com/jkowalleck/rfc3987-syntax2/issues" Source = "https://github.com/jkowalleck/rfc3987-syntax2" [project.optional-dependencies] -typing = [ - "mypy>=1.20,<3", -] testing = [ + "mypy>=1.20,<3", "typing_extensions>=4.16.0", "pytest>=8.3.5", ] From 989db131fc5c45c74ea328e09e5f31401f90a943 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 16 Jul 2026 12:12:48 +0200 Subject: [PATCH 3/6] feat: typing Signed-off-by: Jan Kowalleck --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index cadd02e..bfe3d6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,8 @@ classifiers = [ "Programming Language :: Python :: 3", "Topic :: Scientific/Engineering", "Topic :: Software Development", - "Topic :: Utilities" + "Topic :: Utilities", + "Typing :: Typed", ] dependencies = ["lark>=1.2.2"] From ad3e202b63d478fd0b83ce2376c2ac151b39fa9f Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 16 Jul 2026 12:14:04 +0200 Subject: [PATCH 4/6] feat: typing Signed-off-by: Jan Kowalleck --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3964458..58fbe21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ All notable changes to this project will be documented in this file. +* Added + * Assert static typing (via [#16]) + +[#16]: https://github.com/jkowalleck/rfc3987-syntax2/pull/16 + ## v1.1.1 - 2026-07-14 ### Fork release `rfc3987-syntax2` From 057179d2496a65790d97e6c247ca27ba7e8bd68c Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 16 Jul 2026 12:16:23 +0200 Subject: [PATCH 5/6] feat: typing Signed-off-by: Jan Kowalleck --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bfe3d6d..cbcc0e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ Source = "https://github.com/jkowalleck/rfc3987-syntax2" [project.optional-dependencies] testing = [ - "mypy>=1.20,<3", + "mypy>=1.15,<2", "typing_extensions>=4.16.0", "pytest>=8.3.5", ] From 6f93251e5245202ba97123c7b9773abc7c1125e2 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Thu, 16 Jul 2026 12:28:56 +0200 Subject: [PATCH 6/6] feat: typing Signed-off-by: Jan Kowalleck --- .github/workflows/python-tests.yml | 2 +- tests/__init__.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 4cd8c66..e0262eb 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -53,7 +53,7 @@ jobs: architecture: 'x64' - name: Install project run: pip install --user -e ".[testing]" - - name: Run Tests + - name: Run Mypy run: python -m mypy -v build-and-test: name: Test (${{ matrix.os }} py${{ matrix.python-version }} ${{ matrix.toxenv-factors }}) diff --git a/tests/__init__.py b/tests/__init__.py index 553eb81..4585dbd 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -23,8 +23,8 @@ class SyntaxCase(TypedDict): def valid_syntax_data() -> T_syntax_file: with open(TESTS_DATA_FILES['valid_syntax'], "r", encoding="utf-8") as f: - return json.load(f) # type:ignore + return json.load(f) # type:ignore[no-any-return] def invalid_syntax_data() -> T_syntax_file: with open(TESTS_DATA_FILES['invalid_syntax'], "r", encoding="utf-8") as f: - return json.load(f) # type:ignore \ No newline at end of file + return json.load(f) # type:ignore[no-any-return] \ No newline at end of file