From def0b21e38efae1269414459df1062ca5647afd5 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 24 Jul 2026 15:23:07 +0200 Subject: [PATCH 1/8] refactor: mark consts as `Final` Signed-off-by: Jan Kowalleck --- src/rfc3987_syntax2/syntax_helpers.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/rfc3987_syntax2/syntax_helpers.py b/src/rfc3987_syntax2/syntax_helpers.py index 6f64b60..a5a5b22 100644 --- a/src/rfc3987_syntax2/syntax_helpers.py +++ b/src/rfc3987_syntax2/syntax_helpers.py @@ -4,7 +4,7 @@ from pathlib import Path from threading import Lock -from typing import TYPE_CHECKING, Any, Callable, Literal, Optional +from typing import TYPE_CHECKING, Any, Callable, Final, Literal, Optional from warnings import warn from lark import Lark, ParseTree, exceptions @@ -65,9 +65,9 @@ "is_valid_syntax_pct_encoded", ] -RFC3987_SYNTAX_PARSER_TYPE: str = "earley" -RFC3987_SYNTAX_GRAMMAR_PATH: Path = Path(__file__).parent / "syntax_rfc3987.lark" -RFC3987_SYNTAX_TERMS: list[str] = [ +RFC3987_SYNTAX_PARSER_TYPE: Final[str] = "earley" +RFC3987_SYNTAX_GRAMMAR_PATH: Final[Path] = Path(__file__).parent / "syntax_rfc3987.lark" +RFC3987_SYNTAX_TERMS: Final[list[str]] = [ "iri", "iri_reference", "absolute_iri", @@ -525,7 +525,7 @@ def is_valid_syntax_pct_encoded(text: str) -> bool: is_valid_syntax_pct_encoded = make_syntax_validator("pct_encoded") -RFC3987_SYNTAX_TERM_VALIDATORS: dict[str, T_SYNTAX_VALIDATOR] = { # frozendict +RFC3987_SYNTAX_TERM_VALIDATORS: Final[dict[str, T_SYNTAX_VALIDATOR]] = { # frozendict "iri": is_valid_syntax_iri, "iri_reference": is_valid_syntax_iri_reference, "absolute_iri": is_valid_syntax_absolute_iri, @@ -577,22 +577,22 @@ def is_valid_syntax_pct_encoded(text: str) -> bool: # region lazy loaded attrs if TYPE_CHECKING: # types for lazy-loaded symbols - grammar: str + grammar: Final[str] # type:ignore[misc] """Lark grammar text for RFC 3987.""" if TYPE_CHECKING: # types for lazy-loaded symbols - syntax_parser: Lark + syntax_parser: Final[Lark] # type:ignore[misc] """Lazily initialized parser for RFC 3987 syntax.""" def __getattr__(name: str) -> Any: if name == "grammar": global grammar - grammar = _get_grammar() + grammar = _get_grammar() # type:ignore[misc] return grammar if name == "syntax_parser": global syntax_parser - syntax_parser = _get_syntax_parser() + syntax_parser = _get_syntax_parser() # type:ignore[misc] return syntax_parser raise AttributeError(f"module {__name__!r} has no attribute {name!r}") From fb7096e2a7519229bcaf988545524f21f2046ef2 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 24 Jul 2026 15:34:16 +0200 Subject: [PATCH 2/8] refactor: typing Signed-off-by: Jan Kowalleck --- src/rfc3987_syntax2/syntax_helpers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rfc3987_syntax2/syntax_helpers.py b/src/rfc3987_syntax2/syntax_helpers.py index a5a5b22..55fcb05 100644 --- a/src/rfc3987_syntax2/syntax_helpers.py +++ b/src/rfc3987_syntax2/syntax_helpers.py @@ -4,7 +4,7 @@ from pathlib import Path from threading import Lock -from typing import TYPE_CHECKING, Any, Callable, Final, Literal, Optional +from typing import TYPE_CHECKING, Any, Callable, Final, Literal, Optional, Sequence, TypeAlias from warnings import warn from lark import Lark, ParseTree, exceptions @@ -67,7 +67,7 @@ RFC3987_SYNTAX_PARSER_TYPE: Final[str] = "earley" RFC3987_SYNTAX_GRAMMAR_PATH: Final[Path] = Path(__file__).parent / "syntax_rfc3987.lark" -RFC3987_SYNTAX_TERMS: Final[list[str]] = [ +RFC3987_SYNTAX_TERMS: Final[Sequence[str]] = [ "iri", "iri_reference", "absolute_iri", @@ -123,7 +123,7 @@ Allowed values are ``"iri"``, ``"iri_reference"``, and ``"absolute_iri"``. """ -_SYNTAX_PARSER_STARTS: list[T_SYNTAX_PARSER_TERM] = ["iri", "iri_reference", "absolute_iri"] +_SYNTAX_PARSER_STARTS: Final[Sequence[T_SYNTAX_PARSER_TERM]] = ["iri", "iri_reference", "absolute_iri"] def parse(term: T_SYNTAX_PARSER_TERM, value: str) -> ParseTree: @@ -168,7 +168,7 @@ def is_valid_syntax(term: T_SYNTAX_PARSER_TERM, value: str) -> bool: return True -T_SYNTAX_VALIDATOR = Callable[[str], bool] +T_SYNTAX_VALIDATOR: TypeAlias = Callable[[str], bool] """Callable validator for one RFC 3987 grammar rule. :param text: Input text to validate. From d23c0728d29030b9866fdb9e449bdf271004959b Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 24 Jul 2026 16:01:45 +0200 Subject: [PATCH 3/8] docs Signed-off-by: Jan Kowalleck --- CHANGELOG.md | 5 +++++ src/rfc3987_syntax2/syntax_helpers.py | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7120f23..fd3e86a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ All notable changes to this project will be documented in this file. +* Refactor + * Marked exported constants/lazy globals as `Final` for downstream users (via [#]) + +[#]: + ## v1.3.1 - 2026-07-23 * Docs diff --git a/src/rfc3987_syntax2/syntax_helpers.py b/src/rfc3987_syntax2/syntax_helpers.py index 55fcb05..e216e7a 100644 --- a/src/rfc3987_syntax2/syntax_helpers.py +++ b/src/rfc3987_syntax2/syntax_helpers.py @@ -4,7 +4,7 @@ from pathlib import Path from threading import Lock -from typing import TYPE_CHECKING, Any, Callable, Final, Literal, Optional, Sequence, TypeAlias +from typing import TYPE_CHECKING, Any, Callable, Final, Literal, Mapping, Optional, Sequence, TypeAlias from warnings import warn from lark import Lark, ParseTree, exceptions @@ -525,7 +525,7 @@ def is_valid_syntax_pct_encoded(text: str) -> bool: is_valid_syntax_pct_encoded = make_syntax_validator("pct_encoded") -RFC3987_SYNTAX_TERM_VALIDATORS: Final[dict[str, T_SYNTAX_VALIDATOR]] = { # frozendict +RFC3987_SYNTAX_TERM_VALIDATORS: Final[Mapping[str, T_SYNTAX_VALIDATOR]] = { # frozendict "iri": is_valid_syntax_iri, "iri_reference": is_valid_syntax_iri_reference, "absolute_iri": is_valid_syntax_absolute_iri, @@ -577,22 +577,22 @@ def is_valid_syntax_pct_encoded(text: str) -> bool: # region lazy loaded attrs if TYPE_CHECKING: # types for lazy-loaded symbols - grammar: Final[str] # type:ignore[misc] + grammar: Final[str] # type:ignore[misc] # lazy loading is Final downstream """Lark grammar text for RFC 3987.""" if TYPE_CHECKING: # types for lazy-loaded symbols - syntax_parser: Final[Lark] # type:ignore[misc] + syntax_parser: Final[Lark] # type:ignore[misc] # lazy loading is Final downstream """Lazily initialized parser for RFC 3987 syntax.""" def __getattr__(name: str) -> Any: if name == "grammar": global grammar - grammar = _get_grammar() # type:ignore[misc] + grammar = _get_grammar() # type:ignore[misc] # lazy loading is Final downstream return grammar if name == "syntax_parser": global syntax_parser - syntax_parser = _get_syntax_parser() # type:ignore[misc] + syntax_parser = _get_syntax_parser() # type:ignore[misc] # lazy loading is Final downstream return syntax_parser raise AttributeError(f"module {__name__!r} has no attribute {name!r}") From 126eaf581fe1043f50683c51a581d542f8f5b37e Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 24 Jul 2026 16:02:45 +0200 Subject: [PATCH 4/8] docs Signed-off-by: Jan Kowalleck --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd3e86a..8934a34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,9 @@ All notable changes to this project will be documented in this file. * Refactor - * Marked exported constants/lazy globals as `Final` for downstream users (via [#]) + * Marked exported constants/lazy globals as `Final` for downstream users (via [#69]) -[#]: +[#69]: https://github.com/jkowalleck/rfc3987-syntax2/pull/69 ## v1.3.1 - 2026-07-23 From 18b605bc63a0b0afdedbe05a0897816eefb5d1f0 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 24 Jul 2026 16:14:10 +0200 Subject: [PATCH 5/8] typing Signed-off-by: Jan Kowalleck --- src/rfc3987_syntax2/syntax_helpers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rfc3987_syntax2/syntax_helpers.py b/src/rfc3987_syntax2/syntax_helpers.py index e216e7a..67a4254 100644 --- a/src/rfc3987_syntax2/syntax_helpers.py +++ b/src/rfc3987_syntax2/syntax_helpers.py @@ -118,11 +118,12 @@ defined in the RFC 3987 Lark grammar. """ -T_SYNTAX_PARSER_TERM = Literal["iri", "iri_reference", "absolute_iri"] +T_SYNTAX_PARSER_TERM: TypeAlias = Literal["iri", "iri_reference", "absolute_iri"] """Top-level RFC 3987 parser start terms accepted by :func:`parse` and :func:`check`. Allowed values are ``"iri"``, ``"iri_reference"``, and ``"absolute_iri"``. """ + _SYNTAX_PARSER_STARTS: Final[Sequence[T_SYNTAX_PARSER_TERM]] = ["iri", "iri_reference", "absolute_iri"] From e2e309fa068d51d0864fe66be4f84726a06a9055 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 24 Jul 2026 16:19:53 +0200 Subject: [PATCH 6/8] docs Signed-off-by: Jan Kowalleck --- CHANGELOG.md | 2 +- src/rfc3987_syntax2/syntax_helpers.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8934a34..e011ad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ All notable changes to this project will be documented in this file. * Refactor - * Marked exported constants/lazy globals as `Final` for downstream users (via [#69]) + * Marked exported constants/lazy globals as `Final` for downstream users (via [#69]) [#69]: https://github.com/jkowalleck/rfc3987-syntax2/pull/69 diff --git a/src/rfc3987_syntax2/syntax_helpers.py b/src/rfc3987_syntax2/syntax_helpers.py index 67a4254..ece07c1 100644 --- a/src/rfc3987_syntax2/syntax_helpers.py +++ b/src/rfc3987_syntax2/syntax_helpers.py @@ -526,7 +526,7 @@ def is_valid_syntax_pct_encoded(text: str) -> bool: is_valid_syntax_pct_encoded = make_syntax_validator("pct_encoded") -RFC3987_SYNTAX_TERM_VALIDATORS: Final[Mapping[str, T_SYNTAX_VALIDATOR]] = { # frozendict +RFC3987_SYNTAX_TERM_VALIDATORS: Final[Mapping[str, T_SYNTAX_VALIDATOR]] = { # frozendict / MappingProxyType "iri": is_valid_syntax_iri, "iri_reference": is_valid_syntax_iri_reference, "absolute_iri": is_valid_syntax_absolute_iri, @@ -578,22 +578,22 @@ def is_valid_syntax_pct_encoded(text: str) -> bool: # region lazy loaded attrs if TYPE_CHECKING: # types for lazy-loaded symbols - grammar: Final[str] # type:ignore[misc] # lazy loading is Final downstream + grammar: Final[str] # type: ignore[misc] # lazy loading is Final downstream """Lark grammar text for RFC 3987.""" if TYPE_CHECKING: # types for lazy-loaded symbols - syntax_parser: Final[Lark] # type:ignore[misc] # lazy loading is Final downstream + syntax_parser: Final[Lark] # type: ignore[misc] # lazy loading is Final downstream """Lazily initialized parser for RFC 3987 syntax.""" def __getattr__(name: str) -> Any: if name == "grammar": global grammar - grammar = _get_grammar() # type:ignore[misc] # lazy loading is Final downstream + grammar = _get_grammar() # type: ignore[misc] # lazy loading is Final downstream return grammar if name == "syntax_parser": global syntax_parser - syntax_parser = _get_syntax_parser() # type:ignore[misc] # lazy loading is Final downstream + syntax_parser = _get_syntax_parser() # type: ignore[misc] # lazy loading is Final downstream return syntax_parser raise AttributeError(f"module {__name__!r} has no attribute {name!r}") From 5b0f238f97fd581af123118cd43417e3537b2689 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 24 Jul 2026 16:20:45 +0200 Subject: [PATCH 7/8] py3.9 Signed-off-by: Jan Kowalleck --- src/rfc3987_syntax2/syntax_helpers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rfc3987_syntax2/syntax_helpers.py b/src/rfc3987_syntax2/syntax_helpers.py index ece07c1..c841ec6 100644 --- a/src/rfc3987_syntax2/syntax_helpers.py +++ b/src/rfc3987_syntax2/syntax_helpers.py @@ -4,7 +4,7 @@ from pathlib import Path from threading import Lock -from typing import TYPE_CHECKING, Any, Callable, Final, Literal, Mapping, Optional, Sequence, TypeAlias +from typing import TYPE_CHECKING, Any, Callable, Final, Literal, Mapping, Optional, Sequence from warnings import warn from lark import Lark, ParseTree, exceptions @@ -118,7 +118,7 @@ defined in the RFC 3987 Lark grammar. """ -T_SYNTAX_PARSER_TERM: TypeAlias = Literal["iri", "iri_reference", "absolute_iri"] +T_SYNTAX_PARSER_TERM = Literal["iri", "iri_reference", "absolute_iri"] """Top-level RFC 3987 parser start terms accepted by :func:`parse` and :func:`check`. Allowed values are ``"iri"``, ``"iri_reference"``, and ``"absolute_iri"``. @@ -169,7 +169,7 @@ def is_valid_syntax(term: T_SYNTAX_PARSER_TERM, value: str) -> bool: return True -T_SYNTAX_VALIDATOR: TypeAlias = Callable[[str], bool] +T_SYNTAX_VALIDATOR = Callable[[str], bool] """Callable validator for one RFC 3987 grammar rule. :param text: Input text to validate. From 7182c92dc10681c614598946dc05229324d4ff34 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Fri, 24 Jul 2026 16:28:33 +0200 Subject: [PATCH 8/8] docs Signed-off-by: Jan Kowalleck --- src/rfc3987_syntax2/syntax_helpers.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rfc3987_syntax2/syntax_helpers.py b/src/rfc3987_syntax2/syntax_helpers.py index cc8023d..689e073 100644 --- a/src/rfc3987_syntax2/syntax_helpers.py +++ b/src/rfc3987_syntax2/syntax_helpers.py @@ -67,7 +67,7 @@ RFC3987_SYNTAX_PARSER_TYPE: Final[str] = "earley" RFC3987_SYNTAX_GRAMMAR_PATH: Final[Path] = Path(__file__).parent / "syntax_rfc3987.lark" -RFC3987_SYNTAX_TERMS: Final[Sequence[str]] = [ +RFC3987_SYNTAX_TERMS: Final[Sequence[str]] = [ # TODO: BreakingChaneg: make tuple "iri", "iri_reference", "absolute_iri", @@ -161,6 +161,7 @@ def is_valid_syntax(term: T_SYNTAX_PARSER_TERM, value: str) -> bool: return False except exceptions.LarkError as err: # from Lark internals / initialization (non-UnexpectedInput) + # TODO: BreakingChange: dont catch warn("Unexpected LarkError (non-UnexpectedInput) " f"for term={term!r}: {type(err).__name__}: {err}", RuntimeWarning, @@ -526,7 +527,8 @@ def is_valid_syntax_pct_encoded(text: str) -> bool: is_valid_syntax_pct_encoded = make_syntax_validator("pct_encoded") -RFC3987_SYNTAX_TERM_VALIDATORS: Final[Mapping[str, T_SYNTAX_VALIDATOR]] = { # frozendict / MappingProxyType +RFC3987_SYNTAX_TERM_VALIDATORS: Final[Mapping[str, T_SYNTAX_VALIDATOR]] = { + # TODO: BreakingChange: make frozendict / MappingProxyType "iri": is_valid_syntax_iri, "iri_reference": is_valid_syntax_iri_reference, "absolute_iri": is_valid_syntax_absolute_iri,