-
Notifications
You must be signed in to change notification settings - Fork 6
Lazy import (after #11) #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,37 @@ | ||
| from . import syntax_helpers as _syntax_helpers | ||
|
|
||
| from .syntax_helpers import * | ||
|
|
||
|
|
||
| def __dir__(): | ||
| result = _syntax_helpers.__all__.copy() | ||
| for start_rule in ALL_START_RULES: | ||
| result.append(SYNTAX_VALIDATOR_PREFIX + start_rule) | ||
| return result | ||
|
|
||
|
|
||
| # Cache for lazily created validators | ||
| _attr_cache = {} | ||
|
|
||
|
|
||
| def __getattr__(name): | ||
| """ | ||
| Lazily create attributes, in particular syntax validators, when accessed. | ||
|
|
||
| When an attribute like 'is_valid_syntax_iri' is accessed, this function | ||
| will create and cache the corresponding validator function. | ||
|
|
||
| We also create the syntax parser lazily. | ||
| """ | ||
| try: | ||
| return _attr_cache[name] | ||
| except KeyError: | ||
| if name == "syntax_parser": | ||
| parser = _syntax_helpers.syntax_parser | ||
| _attr_cache[name] = parser | ||
| return parser | ||
| if validator := get_syntax_validator(name): | ||
| _attr_cache[name] = validator | ||
| return validator | ||
|
|
||
| raise AttributeError(f"module '{__name__}' has no attribute '{name}'") | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,6 @@ | ||||||||||||||||||||||||||
| from lark import Lark, ParseTree, exceptions | ||||||||||||||||||||||||||
| import sys | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| from functools import partial | ||||||||||||||||||||||||||
| from pathlib import Path | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| from rfc3987_syntax.utils import load_grammar | ||||||||||||||||||||||||||
|
|
@@ -12,7 +13,7 @@ | |||||||||||||||||||||||||
| "absolute_iri", | ||||||||||||||||||||||||||
| "scheme", | ||||||||||||||||||||||||||
| "irelative_ref", | ||||||||||||||||||||||||||
| "irelative_part" | ||||||||||||||||||||||||||
| "irelative_part", | ||||||||||||||||||||||||||
| "ihier_part", | ||||||||||||||||||||||||||
| "iauthority", | ||||||||||||||||||||||||||
| "iuserinfo", | ||||||||||||||||||||||||||
|
|
@@ -45,108 +46,98 @@ | |||||||||||||||||||||||||
| "pct_encoded", | ||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| # All start rules needed by validators | ||||||||||||||||||||||||||
| ALL_START_RULES: list[str] = RFC3987_SYNTAX_TERMS.copy() | ||||||||||||||||||||||||||
| for term in ("non_zero", "pct_encoded", "scheme"): | ||||||||||||||||||||||||||
| ALL_START_RULES.remove(term) | ||||||||||||||||||||||||||
| ALL_START_RULES.extend( | ||||||||||||||||||||||||||
| ["ipath", "ipath_absolute", "ipath_empty", "ipath_noscheme", "ipath_rootless"] | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
|
Comment on lines
+49
to
+55
|
||||||||||||||||||||||||||
| # All start rules needed by validators | |
| ALL_START_RULES: list[str] = RFC3987_SYNTAX_TERMS.copy() | |
| for term in ("non_zero", "pct_encoded", "scheme"): | |
| ALL_START_RULES.remove(term) | |
| ALL_START_RULES.extend( | |
| ["ipath", "ipath_absolute", "ipath_empty", "ipath_noscheme", "ipath_rootless"] | |
| ) | |
| # All start rules needed by validators and public parse()/is_valid_syntax() calls | |
| ALL_START_RULES: list[str] = RFC3987_SYNTAX_TERMS.copy() | |
| for term in ("ipath", "ipath_absolute", "ipath_empty", "ipath_noscheme", "ipath_rootless"): | |
| if term not in ALL_START_RULES: | |
| ALL_START_RULES.append(term) |
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return type annotation -> sys.modules[__name__].lark.ParseTree is evaluated at import time (no postponed-evaluation import is present), which will trigger the lazy lark import and defeats the purpose of this PR. It’s also an unusual/fragile typing pattern. Use postponed evaluation (e.g., from __future__ import annotations) and/or a string/TYPE_CHECKING-based annotation so lark isn’t imported just to define parse().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defining
__all__in syntax_helpers meansfrom .syntax_helpers import *(used here) now exports only names listed in syntax_helpers.all. Since the term-specific validators (e.g.,is_valid_syntax_iri) are no longer in all,from rfc3987_syntax import *will stop exporting them compared to the previous behavior. If that’s not intended, include the validator names (as strings) in an appropriate all (package-level and/or syntax_helpers) without eagerly constructing the parser.