python-introspect 0.1.3__tar.gz → 0.1.4__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.3/src/python_introspect.egg-info → python_introspect-0.1.4}/PKG-INFO +1 -1
- {python_introspect-0.1.3 → python_introspect-0.1.4}/pyproject.toml +3 -3
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect/__init__.py +1 -1
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect/unified_parameter_analyzer.py +39 -4
- {python_introspect-0.1.3 → python_introspect-0.1.4/src/python_introspect.egg-info}/PKG-INFO +1 -1
- {python_introspect-0.1.3 → python_introspect-0.1.4}/LICENSE +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/README.md +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/setup.cfg +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect/enableable.py +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect/exceptions.py +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect/signature_analyzer.py +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect.egg-info/SOURCES.txt +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect.egg-info/dependency_links.txt +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect.egg-info/requires.txt +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect.egg-info/top_level.txt +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/tests/test_exceptions.py +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/tests/test_init.py +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/tests/test_signature_analyzer.py +0 -0
- {python_introspect-0.1.3 → python_introspect-0.1.4}/tests/test_unified_parameter_analyzer.py +0 -0
|
@@ -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.4"
|
|
8
8
|
description = "Pure Python introspection toolkit for function signatures, dataclasses, and type hints"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -58,14 +58,14 @@ python_functions = ["test_*"]
|
|
|
58
58
|
|
|
59
59
|
[tool.ruff]
|
|
60
60
|
line-length = 100
|
|
61
|
-
target-version = "0.1.
|
|
61
|
+
target-version = "0.1.4"
|
|
62
62
|
|
|
63
63
|
[tool.black]
|
|
64
64
|
line-length = 100
|
|
65
65
|
target-version = ["py39"]
|
|
66
66
|
|
|
67
67
|
[tool.mypy]
|
|
68
|
-
python_version = "0.1.
|
|
68
|
+
python_version = "0.1.4"
|
|
69
69
|
warn_return_any = true
|
|
70
70
|
warn_unused_configs = true
|
|
71
71
|
disallow_untyped_defs = true
|
|
@@ -152,12 +152,22 @@ class UnifiedParameterAnalyzer:
|
|
|
152
152
|
Always returns CLASS signature defaults (not instance values).
|
|
153
153
|
ObjectState extracts instance values separately via object.__getattribute__.
|
|
154
154
|
|
|
155
|
+
For dynamic containers like SimpleNamespace (which use **kwargs in __init__),
|
|
156
|
+
falls back to inspecting __dict__ to discover attributes and their types.
|
|
157
|
+
|
|
155
158
|
Args:
|
|
156
159
|
instance: Object instance to analyze
|
|
157
160
|
"""
|
|
161
|
+
from types import SimpleNamespace
|
|
162
|
+
import logging
|
|
163
|
+
_logger = logging.getLogger(__name__)
|
|
164
|
+
|
|
158
165
|
# Use MRO to get all constructor parameters from the inheritance chain
|
|
159
166
|
instance_class = type(instance)
|
|
160
167
|
all_params = {}
|
|
168
|
+
found_kwargs_only = False
|
|
169
|
+
|
|
170
|
+
_logger.debug(f"🔧 _analyze_object_instance: instance_class={instance_class.__name__}, MRO={[c.__name__ for c in instance_class.__mro__]}")
|
|
161
171
|
|
|
162
172
|
# Traverse MRO from most specific to most general (like dual-axis resolver)
|
|
163
173
|
for cls in instance_class.__mro__:
|
|
@@ -176,10 +186,15 @@ class UnifiedParameterAnalyzer:
|
|
|
176
186
|
if 'self' in class_params:
|
|
177
187
|
del class_params['self']
|
|
178
188
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
189
|
+
_logger.debug(f"🔧 _analyze_object_instance: cls={cls.__name__}, class_params after removing self={list(class_params.keys())}")
|
|
190
|
+
|
|
191
|
+
# Special handling for *args/**kwargs - if params are only args/kwargs, skip this class
|
|
192
|
+
# This handles dynamic containers like SimpleNamespace(self, /, *args, **kwargs)
|
|
193
|
+
variadic_only = set(class_params.keys()) <= {'args', 'kwargs'}
|
|
194
|
+
if variadic_only and class_params:
|
|
195
|
+
# This class uses only *args/**kwargs, skip it and use __dict__ fallback
|
|
196
|
+
found_kwargs_only = True
|
|
197
|
+
_logger.debug(f"🔧 _analyze_object_instance: cls={cls.__name__} has only variadic params {list(class_params.keys())}, skipping, found_kwargs_only=True")
|
|
183
198
|
continue
|
|
184
199
|
|
|
185
200
|
# Add parameters that haven't been seen yet (most specific wins)
|
|
@@ -200,6 +215,26 @@ class UnifiedParameterAnalyzer:
|
|
|
200
215
|
# in MRO might not have analyzable constructors (e.g., ABC, object)
|
|
201
216
|
continue
|
|
202
217
|
|
|
218
|
+
# Fallback for dynamic containers (SimpleNamespace, etc.): inspect __dict__
|
|
219
|
+
# This handles objects that store attrs via **kwargs and have no static signature
|
|
220
|
+
_logger.debug(f"🔧 _analyze_object_instance: after MRO loop, all_params={list(all_params.keys())}, found_kwargs_only={found_kwargs_only}")
|
|
221
|
+
if not all_params and found_kwargs_only and hasattr(instance, '__dict__'):
|
|
222
|
+
_logger.debug(f"🔧 _analyze_object_instance: FALLBACK triggered, inspecting __dict__={list(instance.__dict__.keys())}")
|
|
223
|
+
for attr_name, attr_value in instance.__dict__.items():
|
|
224
|
+
if attr_name.startswith('_'):
|
|
225
|
+
continue
|
|
226
|
+
# Infer type from value
|
|
227
|
+
attr_type = type(attr_value) if attr_value is not None else type(None)
|
|
228
|
+
all_params[attr_name] = UnifiedParameterInfo(
|
|
229
|
+
name=attr_name,
|
|
230
|
+
param_type=attr_type,
|
|
231
|
+
default_value=attr_value,
|
|
232
|
+
is_required=False,
|
|
233
|
+
description=None,
|
|
234
|
+
source_type="dynamic_attr"
|
|
235
|
+
)
|
|
236
|
+
_logger.debug(f"🔧 _analyze_object_instance: after fallback, all_params={list(all_params.keys())}")
|
|
237
|
+
|
|
203
238
|
return all_params
|
|
204
239
|
|
|
205
240
|
@staticmethod
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect/signature_analyzer.py
RENAMED
|
File without changes
|
{python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect.egg-info/requires.txt
RENAMED
|
File without changes
|
{python_introspect-0.1.3 → python_introspect-0.1.4}/src/python_introspect.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_introspect-0.1.3 → python_introspect-0.1.4}/tests/test_unified_parameter_analyzer.py
RENAMED
|
File without changes
|