python-introspect 0.1.12__tar.gz → 0.1.13__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.
Files changed (34) hide show
  1. {python_introspect-0.1.12/src/python_introspect.egg-info → python_introspect-0.1.13}/PKG-INFO +1 -1
  2. {python_introspect-0.1.12 → python_introspect-0.1.13}/pyproject.toml +1 -1
  3. python_introspect-0.1.13/src/python_introspect/callable_declaration.py +46 -0
  4. {python_introspect-0.1.12 → python_introspect-0.1.13/src/python_introspect.egg-info}/PKG-INFO +1 -1
  5. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_callable_declaration.py +23 -0
  6. python_introspect-0.1.12/src/python_introspect/callable_declaration.py +0 -37
  7. {python_introspect-0.1.12 → python_introspect-0.1.13}/LICENSE +0 -0
  8. {python_introspect-0.1.12 → python_introspect-0.1.13}/README.md +0 -0
  9. {python_introspect-0.1.12 → python_introspect-0.1.13}/setup.cfg +0 -0
  10. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/__init__.py +0 -0
  11. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/annotation_types.py +0 -0
  12. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/dataclass_projection.py +0 -0
  13. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/docstring_annotations.py +0 -0
  14. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/enableable.py +0 -0
  15. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/environment_projection.py +0 -0
  16. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/exceptions.py +0 -0
  17. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/runtime_parameter.py +0 -0
  18. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/signature_analyzer.py +0 -0
  19. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/unified_parameter_analyzer.py +0 -0
  20. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect/validation.py +0 -0
  21. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect.egg-info/SOURCES.txt +0 -0
  22. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect.egg-info/dependency_links.txt +0 -0
  23. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect.egg-info/requires.txt +0 -0
  24. {python_introspect-0.1.12 → python_introspect-0.1.13}/src/python_introspect.egg-info/top_level.txt +0 -0
  25. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_annotation_types.py +0 -0
  26. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_dataclass_projection.py +0 -0
  27. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_environment_projection.py +0 -0
  28. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_exceptions.py +0 -0
  29. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_init.py +0 -0
  30. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_runtime_parameter.py +0 -0
  31. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_signature_analyzer.py +0 -0
  32. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_unified_parameter_analyzer.py +0 -0
  33. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_validate_python_release_action.py +0 -0
  34. {python_introspect-0.1.12 → python_introspect-0.1.13}/tests/test_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-introspect
3
- Version: 0.1.12
3
+ Version: 0.1.13
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-introspect"
7
- version = "0.1.12"
7
+ version = "0.1.13"
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"
@@ -0,0 +1,46 @@
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
+ omit_defaults: bool = True,
19
+ ) -> dict[str, ParameterValue]:
20
+ """Project supplied kwargs in signature order, optionally omitting defaults.
21
+
22
+ Equality remains caller-owned so frameworks can supply semantics for
23
+ arrays, lazy values, and other values whose ``==`` result is not boolean.
24
+ Extra kwargs retain their relative input order after declared parameters.
25
+ Missing parameters are never populated by this projection.
26
+ """
27
+
28
+ try:
29
+ parameters = inspect.signature(func).parameters
30
+ except (TypeError, ValueError):
31
+ parameters = {}
32
+ defaults = {
33
+ name: parameter.default
34
+ for name, parameter in parameters.items()
35
+ if parameter.default is not inspect.Parameter.empty
36
+ }
37
+ return {
38
+ name: kwargs[name]
39
+ for name in dict.fromkeys((*parameters, *kwargs))
40
+ if name in kwargs
41
+ and (
42
+ not omit_defaults
43
+ or name not in defaults
44
+ or not values_equal(kwargs[name], defaults[name])
45
+ )
46
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-introspect
3
- Version: 0.1.12
3
+ Version: 0.1.13
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
@@ -2,6 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  from operator import attrgetter
4
4
 
5
+ import pytest
6
+
5
7
  from python_introspect import callable_declaration_kwargs
6
8
 
7
9
 
@@ -38,3 +40,24 @@ def test_callable_declaration_kwargs_preserves_values_for_opaque_callable() -> N
38
40
  )
39
41
 
40
42
  assert declaration == kwargs
43
+
44
+
45
+ @pytest.mark.parametrize("omit_defaults", [True, False])
46
+ def test_signature_order_precedes_extra_keywords_without_mutation(omit_defaults):
47
+ kwargs = {"extra_b": 2, "enabled": False, "threshold": 99.8, "extra_a": 1}
48
+ original = kwargs.copy()
49
+ result = callable_declaration_kwargs(
50
+ sample_function, kwargs, values_equal=lambda a, b: a == b,
51
+ omit_defaults=omit_defaults,
52
+ )
53
+ assert list(result) == ["threshold", "enabled", "extra_b", "extra_a"]
54
+ assert list(kwargs.items()) == list(original.items())
55
+ assert result == kwargs
56
+
57
+
58
+ def test_full_projection_keeps_explicit_defaults_but_does_not_insert_missing():
59
+ result = callable_declaration_kwargs(
60
+ sample_function, {"enabled": True}, values_equal=lambda a, b: a == b,
61
+ omit_defaults=False,
62
+ )
63
+ assert result == {"enabled": True}
@@ -1,37 +0,0 @@
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
- }