python-introspect 0.1.9__tar.gz → 0.1.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_introspect-0.1.9/src/python_introspect.egg-info → python_introspect-0.1.11}/PKG-INFO +7 -2
- {python_introspect-0.1.9 → python_introspect-0.1.11}/README.md +6 -1
- {python_introspect-0.1.9 → python_introspect-0.1.11}/pyproject.toml +1 -1
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/__init__.py +7 -1
- python_introspect-0.1.11/src/python_introspect/callable_declaration.py +37 -0
- python_introspect-0.1.11/src/python_introspect/runtime_parameter.py +85 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11/src/python_introspect.egg-info}/PKG-INFO +7 -2
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect.egg-info/SOURCES.txt +4 -0
- python_introspect-0.1.11/tests/test_callable_declaration.py +40 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_init.py +9 -1
- python_introspect-0.1.11/tests/test_runtime_parameter.py +58 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/LICENSE +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/setup.cfg +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/annotation_types.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/dataclass_projection.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/enableable.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/environment_projection.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/exceptions.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/signature_analyzer.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/unified_parameter_analyzer.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/validation.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect.egg-info/dependency_links.txt +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect.egg-info/requires.txt +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect.egg-info/top_level.txt +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_annotation_types.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_dataclass_projection.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_environment_projection.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_exceptions.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_signature_analyzer.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_unified_parameter_analyzer.py +0 -0
- {python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_validation.py +0 -0
{python_introspect-0.1.9/src/python_introspect.egg-info → python_introspect-0.1.11}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-introspect
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: Pure Python introspection toolkit for function signatures, dataclasses, and type hints
|
|
5
5
|
Author-email: Tristan Simas <tristan.simas@mail.mcgill.ca>
|
|
6
6
|
License: MIT
|
|
@@ -37,7 +37,7 @@ Dynamic: license-file
|
|
|
37
37
|
# python-introspect
|
|
38
38
|
|
|
39
39
|
Extensible analysis of callable signatures, dataclass fields, type hints, and
|
|
40
|
-
docstrings.
|
|
40
|
+
docstrings, plus signature-derived callable declaration projection.
|
|
41
41
|
|
|
42
42
|
[](https://www.python.org/downloads/)
|
|
43
43
|
[](https://badge.fury.io/py/python-introspect)
|
|
@@ -66,6 +66,11 @@ for name, info in parameters.items():
|
|
|
66
66
|
dataclass types, and instances. It returns a mapping of names to
|
|
67
67
|
``ParameterInfo`` records.
|
|
68
68
|
|
|
69
|
+
Use ``callable_declaration_kwargs`` when declaration identity should omit
|
|
70
|
+
keyword arguments equal to their signature defaults. The caller supplies value
|
|
71
|
+
equality so array, lazy, or other framework-specific values keep their owning
|
|
72
|
+
semantics.
|
|
73
|
+
|
|
69
74
|
## Extension points
|
|
70
75
|
|
|
71
76
|
Use ``register_namespace_provider`` to contribute names used while resolving
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# python-introspect
|
|
2
2
|
|
|
3
3
|
Extensible analysis of callable signatures, dataclass fields, type hints, and
|
|
4
|
-
docstrings.
|
|
4
|
+
docstrings, plus signature-derived callable declaration projection.
|
|
5
5
|
|
|
6
6
|
[](https://www.python.org/downloads/)
|
|
7
7
|
[](https://badge.fury.io/py/python-introspect)
|
|
@@ -30,6 +30,11 @@ for name, info in parameters.items():
|
|
|
30
30
|
dataclass types, and instances. It returns a mapping of names to
|
|
31
31
|
``ParameterInfo`` records.
|
|
32
32
|
|
|
33
|
+
Use ``callable_declaration_kwargs`` when declaration identity should omit
|
|
34
|
+
keyword arguments equal to their signature defaults. The caller supplies value
|
|
35
|
+
equality so array, lazy, or other framework-specific values keep their owning
|
|
36
|
+
semantics.
|
|
37
|
+
|
|
33
38
|
## Extension points
|
|
34
39
|
|
|
35
40
|
Use ``register_namespace_provider`` to contribute names used while resolving
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-introspect"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.11"
|
|
8
8
|
description = "Pure Python introspection toolkit for function signatures, dataclasses, and type hints"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -9,7 +9,7 @@ Extensibility:
|
|
|
9
9
|
type resolution for framework-specific types (lazy configs, proxies, etc.)
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
-
__version__ = "0.1.
|
|
12
|
+
__version__ = "0.1.11"
|
|
13
13
|
|
|
14
14
|
from .signature_analyzer import (
|
|
15
15
|
SignatureAnalyzer,
|
|
@@ -71,6 +71,8 @@ from .annotation_types import (
|
|
|
71
71
|
resolve_annotated,
|
|
72
72
|
resolve_optional,
|
|
73
73
|
)
|
|
74
|
+
from .callable_declaration import callable_declaration_kwargs
|
|
75
|
+
from .runtime_parameter import RuntimeParameterDeclarationABC
|
|
74
76
|
|
|
75
77
|
__all__ = [
|
|
76
78
|
# Version
|
|
@@ -127,4 +129,8 @@ __all__ = [
|
|
|
127
129
|
"optional_member_type",
|
|
128
130
|
"resolve_annotated",
|
|
129
131
|
"resolve_optional",
|
|
132
|
+
# Callable declarations
|
|
133
|
+
"callable_declaration_kwargs",
|
|
134
|
+
# Runtime-supplied callable parameters
|
|
135
|
+
"RuntimeParameterDeclarationABC",
|
|
130
136
|
]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Declaration projections derived from callable signatures."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import inspect
|
|
6
|
+
from collections.abc import Callable, Mapping
|
|
7
|
+
from typing import TypeVar
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
ParameterValue = TypeVar("ParameterValue")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def callable_declaration_kwargs(
|
|
14
|
+
func: Callable,
|
|
15
|
+
kwargs: Mapping[str, ParameterValue],
|
|
16
|
+
*,
|
|
17
|
+
values_equal: Callable[[object, object], bool],
|
|
18
|
+
) -> dict[str, ParameterValue]:
|
|
19
|
+
"""Return declared kwargs whose values differ from signature defaults.
|
|
20
|
+
|
|
21
|
+
Equality remains caller-owned so frameworks can supply semantics for
|
|
22
|
+
arrays, lazy values, and other values whose ``==`` result is not boolean.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
defaults = {
|
|
27
|
+
name: parameter.default
|
|
28
|
+
for name, parameter in inspect.signature(func).parameters.items()
|
|
29
|
+
if parameter.default is not inspect.Parameter.empty
|
|
30
|
+
}
|
|
31
|
+
except (TypeError, ValueError):
|
|
32
|
+
defaults = {}
|
|
33
|
+
return {
|
|
34
|
+
name: value
|
|
35
|
+
for name, value in kwargs.items()
|
|
36
|
+
if name not in defaults or not values_equal(value, defaults[name])
|
|
37
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Nominal declarations for runtime-supplied callable parameters."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import inspect
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from collections.abc import Iterable
|
|
8
|
+
from typing import ClassVar
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RuntimeParameterDeclarationABC(ABC):
|
|
12
|
+
"""Semantic owner for one parameter supplied by runtime infrastructure."""
|
|
13
|
+
|
|
14
|
+
preserve_for_execution: ClassVar[bool] = False
|
|
15
|
+
is_semantic_control: ClassVar[bool] = False
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def require_parameter_name(cls) -> str:
|
|
20
|
+
"""Return the public callable parameter name."""
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def parameter(cls) -> inspect.Parameter:
|
|
25
|
+
"""Return the complete callable signature parameter declaration."""
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def validated_parameter(cls) -> inspect.Parameter:
|
|
29
|
+
"""Return the parameter after proving its nominal declaration is coherent."""
|
|
30
|
+
|
|
31
|
+
parameter = cls.parameter()
|
|
32
|
+
if not isinstance(parameter, inspect.Parameter):
|
|
33
|
+
raise TypeError(f"{cls.__name__}.parameter() must return inspect.Parameter.")
|
|
34
|
+
parameter_name = cls.require_parameter_name()
|
|
35
|
+
if not isinstance(parameter_name, str) or not parameter_name.strip():
|
|
36
|
+
raise TypeError(
|
|
37
|
+
f"{cls.__name__}.require_parameter_name() must return a non-empty string."
|
|
38
|
+
)
|
|
39
|
+
if parameter.name != parameter_name:
|
|
40
|
+
raise TypeError(
|
|
41
|
+
f"{cls.__name__}.parameter() name {parameter.name!r} does not "
|
|
42
|
+
f"match require_parameter_name() {parameter_name!r}."
|
|
43
|
+
)
|
|
44
|
+
return parameter
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def require_declaration_type(
|
|
48
|
+
cls,
|
|
49
|
+
candidate: object,
|
|
50
|
+
*,
|
|
51
|
+
boundary: str,
|
|
52
|
+
) -> type[RuntimeParameterDeclarationABC]:
|
|
53
|
+
"""Require one nominal runtime-parameter declaration type."""
|
|
54
|
+
|
|
55
|
+
if not isinstance(candidate, type) or not issubclass(candidate, cls):
|
|
56
|
+
raise TypeError(
|
|
57
|
+
f"{boundary} must contain {cls.__name__} subclasses, got {candidate!r}."
|
|
58
|
+
)
|
|
59
|
+
candidate.validated_parameter()
|
|
60
|
+
return candidate
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def require_declaration_types(
|
|
64
|
+
cls,
|
|
65
|
+
candidates: Iterable[object],
|
|
66
|
+
*,
|
|
67
|
+
boundary: str,
|
|
68
|
+
) -> tuple[type[RuntimeParameterDeclarationABC], ...]:
|
|
69
|
+
"""Require coherent declarations with unique public parameter names."""
|
|
70
|
+
|
|
71
|
+
declarations: list[type[RuntimeParameterDeclarationABC]] = []
|
|
72
|
+
seen_names: set[str] = set()
|
|
73
|
+
for candidate in candidates:
|
|
74
|
+
declaration = cls.require_declaration_type(candidate, boundary=boundary)
|
|
75
|
+
parameter_name = declaration.require_parameter_name()
|
|
76
|
+
if parameter_name in seen_names:
|
|
77
|
+
raise ValueError(
|
|
78
|
+
f"{boundary} declares duplicate runtime parameter {parameter_name!r}."
|
|
79
|
+
)
|
|
80
|
+
declarations.append(declaration)
|
|
81
|
+
seen_names.add(parameter_name)
|
|
82
|
+
return tuple(declarations)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
__all__ = ("RuntimeParameterDeclarationABC",)
|
{python_introspect-0.1.9 → python_introspect-0.1.11/src/python_introspect.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-introspect
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: Pure Python introspection toolkit for function signatures, dataclasses, and type hints
|
|
5
5
|
Author-email: Tristan Simas <tristan.simas@mail.mcgill.ca>
|
|
6
6
|
License: MIT
|
|
@@ -37,7 +37,7 @@ Dynamic: license-file
|
|
|
37
37
|
# python-introspect
|
|
38
38
|
|
|
39
39
|
Extensible analysis of callable signatures, dataclass fields, type hints, and
|
|
40
|
-
docstrings.
|
|
40
|
+
docstrings, plus signature-derived callable declaration projection.
|
|
41
41
|
|
|
42
42
|
[](https://www.python.org/downloads/)
|
|
43
43
|
[](https://badge.fury.io/py/python-introspect)
|
|
@@ -66,6 +66,11 @@ for name, info in parameters.items():
|
|
|
66
66
|
dataclass types, and instances. It returns a mapping of names to
|
|
67
67
|
``ParameterInfo`` records.
|
|
68
68
|
|
|
69
|
+
Use ``callable_declaration_kwargs`` when declaration identity should omit
|
|
70
|
+
keyword arguments equal to their signature defaults. The caller supplies value
|
|
71
|
+
equality so array, lazy, or other framework-specific values keep their owning
|
|
72
|
+
semantics.
|
|
73
|
+
|
|
69
74
|
## Extension points
|
|
70
75
|
|
|
71
76
|
Use ``register_namespace_provider`` to contribute names used while resolving
|
{python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect.egg-info/SOURCES.txt
RENAMED
|
@@ -3,10 +3,12 @@ README.md
|
|
|
3
3
|
pyproject.toml
|
|
4
4
|
src/python_introspect/__init__.py
|
|
5
5
|
src/python_introspect/annotation_types.py
|
|
6
|
+
src/python_introspect/callable_declaration.py
|
|
6
7
|
src/python_introspect/dataclass_projection.py
|
|
7
8
|
src/python_introspect/enableable.py
|
|
8
9
|
src/python_introspect/environment_projection.py
|
|
9
10
|
src/python_introspect/exceptions.py
|
|
11
|
+
src/python_introspect/runtime_parameter.py
|
|
10
12
|
src/python_introspect/signature_analyzer.py
|
|
11
13
|
src/python_introspect/unified_parameter_analyzer.py
|
|
12
14
|
src/python_introspect/validation.py
|
|
@@ -16,10 +18,12 @@ src/python_introspect.egg-info/dependency_links.txt
|
|
|
16
18
|
src/python_introspect.egg-info/requires.txt
|
|
17
19
|
src/python_introspect.egg-info/top_level.txt
|
|
18
20
|
tests/test_annotation_types.py
|
|
21
|
+
tests/test_callable_declaration.py
|
|
19
22
|
tests/test_dataclass_projection.py
|
|
20
23
|
tests/test_environment_projection.py
|
|
21
24
|
tests/test_exceptions.py
|
|
22
25
|
tests/test_init.py
|
|
26
|
+
tests/test_runtime_parameter.py
|
|
23
27
|
tests/test_signature_analyzer.py
|
|
24
28
|
tests/test_unified_parameter_analyzer.py
|
|
25
29
|
tests/test_validation.py
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from operator import attrgetter
|
|
4
|
+
|
|
5
|
+
from python_introspect import callable_declaration_kwargs
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def sample_function(value, threshold: float = 1.0, enabled: bool = True):
|
|
9
|
+
return value
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_callable_declaration_kwargs_projects_signature_defaults() -> None:
|
|
13
|
+
kwargs = {
|
|
14
|
+
"threshold": 1,
|
|
15
|
+
"enabled": False,
|
|
16
|
+
"extension_parameter": "preserved",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declaration = callable_declaration_kwargs(
|
|
20
|
+
sample_function,
|
|
21
|
+
kwargs,
|
|
22
|
+
values_equal=lambda left, right: left == right,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
assert declaration == {
|
|
26
|
+
"enabled": False,
|
|
27
|
+
"extension_parameter": "preserved",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_callable_declaration_kwargs_preserves_values_for_opaque_callable() -> None:
|
|
32
|
+
kwargs = {"extension_parameter": "preserved"}
|
|
33
|
+
|
|
34
|
+
declaration = callable_declaration_kwargs(
|
|
35
|
+
attrgetter("value"),
|
|
36
|
+
kwargs,
|
|
37
|
+
values_equal=lambda left, right: left == right,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
assert declaration == kwargs
|
|
@@ -11,42 +11,48 @@ class TestPackageImports:
|
|
|
11
11
|
"""Test that __version__ is available."""
|
|
12
12
|
assert hasattr(python_introspect, "__version__")
|
|
13
13
|
assert isinstance(python_introspect.__version__, str)
|
|
14
|
-
assert python_introspect.__version__ == "0.1.
|
|
14
|
+
assert python_introspect.__version__ == "0.1.11"
|
|
15
15
|
|
|
16
16
|
def test_signature_analyzer_import(self):
|
|
17
17
|
"""Test SignatureAnalyzer is importable."""
|
|
18
18
|
assert hasattr(python_introspect, "SignatureAnalyzer")
|
|
19
19
|
from python_introspect import SignatureAnalyzer
|
|
20
|
+
|
|
20
21
|
assert SignatureAnalyzer is not None
|
|
21
22
|
|
|
22
23
|
def test_parameter_info_import(self):
|
|
23
24
|
"""Test ParameterInfo is importable."""
|
|
24
25
|
assert hasattr(python_introspect, "ParameterInfo")
|
|
25
26
|
from python_introspect import ParameterInfo
|
|
27
|
+
|
|
26
28
|
assert ParameterInfo is not None
|
|
27
29
|
|
|
28
30
|
def test_docstring_info_import(self):
|
|
29
31
|
"""Test DocstringInfo is importable."""
|
|
30
32
|
assert hasattr(python_introspect, "DocstringInfo")
|
|
31
33
|
from python_introspect import DocstringInfo
|
|
34
|
+
|
|
32
35
|
assert DocstringInfo is not None
|
|
33
36
|
|
|
34
37
|
def test_docstring_extractor_import(self):
|
|
35
38
|
"""Test DocstringExtractor is importable."""
|
|
36
39
|
assert hasattr(python_introspect, "DocstringExtractor")
|
|
37
40
|
from python_introspect import DocstringExtractor
|
|
41
|
+
|
|
38
42
|
assert DocstringExtractor is not None
|
|
39
43
|
|
|
40
44
|
def test_unified_parameter_analyzer_import(self):
|
|
41
45
|
"""Test UnifiedParameterAnalyzer is importable."""
|
|
42
46
|
assert hasattr(python_introspect, "UnifiedParameterAnalyzer")
|
|
43
47
|
from python_introspect import UnifiedParameterAnalyzer
|
|
48
|
+
|
|
44
49
|
assert UnifiedParameterAnalyzer is not None
|
|
45
50
|
|
|
46
51
|
def test_unified_parameter_info_import(self):
|
|
47
52
|
"""Test UnifiedParameterInfo is importable."""
|
|
48
53
|
assert hasattr(python_introspect, "UnifiedParameterInfo")
|
|
49
54
|
from python_introspect import UnifiedParameterInfo
|
|
55
|
+
|
|
50
56
|
assert UnifiedParameterInfo is not None
|
|
51
57
|
|
|
52
58
|
def test_exceptions_import(self):
|
|
@@ -57,6 +63,7 @@ class TestPackageImports:
|
|
|
57
63
|
DocstringParsingError,
|
|
58
64
|
TypeResolutionError,
|
|
59
65
|
)
|
|
66
|
+
|
|
60
67
|
assert IntrospectionError is not None
|
|
61
68
|
assert SignatureAnalysisError is not None
|
|
62
69
|
assert DocstringParsingError is not None
|
|
@@ -98,6 +105,7 @@ class TestPublicAPI:
|
|
|
98
105
|
"""Test that 'from python_introspect import *' works."""
|
|
99
106
|
# This is a sanity check that __all__ is properly defined
|
|
100
107
|
import python_introspect
|
|
108
|
+
|
|
101
109
|
all_names = python_introspect.__all__
|
|
102
110
|
|
|
103
111
|
for name in all_names:
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Tests for nominal runtime-parameter declarations."""
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from python_introspect import RuntimeParameterDeclarationABC
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ExampleRuntimeParameter(RuntimeParameterDeclarationABC):
|
|
11
|
+
@classmethod
|
|
12
|
+
def require_parameter_name(cls) -> str:
|
|
13
|
+
return "runtime_value"
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def parameter(cls) -> inspect.Parameter:
|
|
17
|
+
return inspect.Parameter(
|
|
18
|
+
cls.require_parameter_name(),
|
|
19
|
+
inspect.Parameter.KEYWORD_ONLY,
|
|
20
|
+
annotation=int,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class StructuralImpostor:
|
|
25
|
+
@classmethod
|
|
26
|
+
def require_parameter_name(cls) -> str:
|
|
27
|
+
return "runtime_value"
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def parameter(cls) -> inspect.Parameter:
|
|
31
|
+
return inspect.Parameter("runtime_value", inspect.Parameter.KEYWORD_ONLY)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class MismatchedRuntimeParameter(ExampleRuntimeParameter):
|
|
35
|
+
@classmethod
|
|
36
|
+
def parameter(cls) -> inspect.Parameter:
|
|
37
|
+
return inspect.Parameter("different_name", inspect.Parameter.KEYWORD_ONLY)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_runtime_parameter_requires_nominal_subclass() -> None:
|
|
41
|
+
with pytest.raises(TypeError, match="RuntimeParameterDeclarationABC subclasses"):
|
|
42
|
+
RuntimeParameterDeclarationABC.require_declaration_type(
|
|
43
|
+
StructuralImpostor,
|
|
44
|
+
boundary="test declarations",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_runtime_parameter_requires_matching_declared_name() -> None:
|
|
49
|
+
with pytest.raises(TypeError, match="does not match require_parameter_name"):
|
|
50
|
+
MismatchedRuntimeParameter.validated_parameter()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_runtime_parameter_collection_requires_unique_names() -> None:
|
|
54
|
+
with pytest.raises(ValueError, match="duplicate runtime parameter 'runtime_value'"):
|
|
55
|
+
RuntimeParameterDeclarationABC.require_declaration_types(
|
|
56
|
+
(ExampleRuntimeParameter, ExampleRuntimeParameter),
|
|
57
|
+
boundary="test declarations",
|
|
58
|
+
)
|
|
File without changes
|
|
File without changes
|
{python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/annotation_types.py
RENAMED
|
File without changes
|
{python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/dataclass_projection.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/environment_projection.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect/signature_analyzer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect.egg-info/requires.txt
RENAMED
|
File without changes
|
{python_introspect-0.1.9 → python_introspect-0.1.11}/src/python_introspect.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_introspect-0.1.9 → python_introspect-0.1.11}/tests/test_unified_parameter_analyzer.py
RENAMED
|
File without changes
|
|
File without changes
|