scitex 2.14.0__py3-none-any.whl → 2.15.3__py3-none-any.whl
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.
- scitex/__init__.py +71 -17
- scitex/_env_loader.py +156 -0
- scitex/_mcp_resources/__init__.py +37 -0
- scitex/_mcp_resources/_cheatsheet.py +135 -0
- scitex/_mcp_resources/_figrecipe.py +138 -0
- scitex/_mcp_resources/_formats.py +102 -0
- scitex/_mcp_resources/_modules.py +337 -0
- scitex/_mcp_resources/_session.py +149 -0
- scitex/_mcp_tools/__init__.py +4 -0
- scitex/_mcp_tools/audio.py +66 -0
- scitex/_mcp_tools/diagram.py +11 -95
- scitex/_mcp_tools/introspect.py +210 -0
- scitex/_mcp_tools/plt.py +260 -305
- scitex/_mcp_tools/scholar.py +74 -0
- scitex/_mcp_tools/social.py +27 -0
- scitex/_mcp_tools/template.py +24 -0
- scitex/_mcp_tools/writer.py +17 -210
- scitex/ai/_gen_ai/_PARAMS.py +10 -7
- scitex/ai/classification/reporters/_SingleClassificationReporter.py +45 -1603
- scitex/ai/classification/reporters/_mixins/__init__.py +36 -0
- scitex/ai/classification/reporters/_mixins/_constants.py +67 -0
- scitex/ai/classification/reporters/_mixins/_cv_summary.py +387 -0
- scitex/ai/classification/reporters/_mixins/_feature_importance.py +119 -0
- scitex/ai/classification/reporters/_mixins/_metrics.py +275 -0
- scitex/ai/classification/reporters/_mixins/_plotting.py +179 -0
- scitex/ai/classification/reporters/_mixins/_reports.py +153 -0
- scitex/ai/classification/reporters/_mixins/_storage.py +160 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +30 -1550
- scitex/ai/classification/timeseries/_sliding_window_core.py +467 -0
- scitex/ai/classification/timeseries/_sliding_window_plotting.py +369 -0
- scitex/audio/README.md +40 -36
- scitex/audio/__init__.py +129 -61
- scitex/audio/_branding.py +185 -0
- scitex/audio/_mcp/__init__.py +32 -0
- scitex/audio/_mcp/handlers.py +59 -6
- scitex/audio/_mcp/speak_handlers.py +238 -0
- scitex/audio/_relay.py +225 -0
- scitex/audio/_tts.py +18 -10
- scitex/audio/engines/base.py +17 -10
- scitex/audio/engines/elevenlabs_engine.py +7 -2
- scitex/audio/mcp_server.py +228 -75
- scitex/canvas/README.md +1 -1
- scitex/canvas/editor/_dearpygui/__init__.py +25 -0
- scitex/canvas/editor/_dearpygui/_editor.py +147 -0
- scitex/canvas/editor/_dearpygui/_handlers.py +476 -0
- scitex/canvas/editor/_dearpygui/_panels/__init__.py +17 -0
- scitex/canvas/editor/_dearpygui/_panels/_control.py +119 -0
- scitex/canvas/editor/_dearpygui/_panels/_element_controls.py +190 -0
- scitex/canvas/editor/_dearpygui/_panels/_preview.py +43 -0
- scitex/canvas/editor/_dearpygui/_panels/_sections.py +390 -0
- scitex/canvas/editor/_dearpygui/_plotting.py +187 -0
- scitex/canvas/editor/_dearpygui/_rendering.py +504 -0
- scitex/canvas/editor/_dearpygui/_selection.py +295 -0
- scitex/canvas/editor/_dearpygui/_state.py +93 -0
- scitex/canvas/editor/_dearpygui/_utils.py +61 -0
- scitex/canvas/editor/flask_editor/_core/__init__.py +27 -0
- scitex/canvas/editor/flask_editor/_core/_bbox_extraction.py +200 -0
- scitex/canvas/editor/flask_editor/_core/_editor.py +173 -0
- scitex/canvas/editor/flask_editor/_core/_export_helpers.py +353 -0
- scitex/canvas/editor/flask_editor/_core/_routes_basic.py +190 -0
- scitex/canvas/editor/flask_editor/_core/_routes_export.py +332 -0
- scitex/canvas/editor/flask_editor/_core/_routes_panels.py +252 -0
- scitex/canvas/editor/flask_editor/_core/_routes_save.py +218 -0
- scitex/canvas/editor/flask_editor/_core.py +25 -1684
- scitex/canvas/editor/flask_editor/templates/__init__.py +32 -70
- scitex/cli/__init__.py +38 -43
- scitex/cli/audio.py +160 -41
- scitex/cli/capture.py +133 -20
- scitex/cli/introspect.py +488 -0
- scitex/cli/main.py +200 -109
- scitex/cli/mcp.py +60 -34
- scitex/cli/plt.py +414 -0
- scitex/cli/repro.py +15 -8
- scitex/cli/resource.py +15 -8
- scitex/cli/scholar/__init__.py +154 -8
- scitex/cli/scholar/_crossref_scitex.py +296 -0
- scitex/cli/scholar/_fetch.py +25 -3
- scitex/cli/social.py +355 -0
- scitex/cli/stats.py +136 -11
- scitex/cli/template.py +129 -12
- scitex/cli/tex.py +15 -8
- scitex/cli/writer.py +49 -299
- scitex/cloud/__init__.py +41 -2
- scitex/config/README.md +1 -1
- scitex/config/__init__.py +16 -2
- scitex/config/_env_registry.py +256 -0
- scitex/context/__init__.py +22 -0
- scitex/dev/__init__.py +20 -1
- scitex/diagram/__init__.py +42 -19
- scitex/diagram/mcp_server.py +13 -125
- scitex/gen/__init__.py +50 -14
- scitex/gen/_list_packages.py +4 -4
- scitex/introspect/__init__.py +82 -0
- scitex/introspect/_call_graph.py +303 -0
- scitex/introspect/_class_hierarchy.py +163 -0
- scitex/introspect/_core.py +41 -0
- scitex/introspect/_docstring.py +131 -0
- scitex/introspect/_examples.py +113 -0
- scitex/introspect/_imports.py +271 -0
- scitex/{gen/_inspect_module.py → introspect/_list_api.py} +48 -56
- scitex/introspect/_mcp/__init__.py +41 -0
- scitex/introspect/_mcp/handlers.py +233 -0
- scitex/introspect/_members.py +155 -0
- scitex/introspect/_resolve.py +89 -0
- scitex/introspect/_signature.py +131 -0
- scitex/introspect/_source.py +80 -0
- scitex/introspect/_type_hints.py +172 -0
- scitex/io/_save.py +1 -2
- scitex/io/bundle/README.md +1 -1
- scitex/logging/_formatters.py +19 -9
- scitex/mcp_server.py +98 -5
- scitex/os/__init__.py +4 -0
- scitex/{gen → os}/_check_host.py +4 -5
- scitex/plt/__init__.py +245 -550
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +5 -10
- scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/plt/gallery/README.md +1 -1
- scitex/plt/utils/_hitmap/__init__.py +82 -0
- scitex/plt/utils/_hitmap/_artist_extraction.py +343 -0
- scitex/plt/utils/_hitmap/_color_application.py +346 -0
- scitex/plt/utils/_hitmap/_color_conversion.py +121 -0
- scitex/plt/utils/_hitmap/_constants.py +40 -0
- scitex/plt/utils/_hitmap/_hitmap_core.py +334 -0
- scitex/plt/utils/_hitmap/_path_extraction.py +357 -0
- scitex/plt/utils/_hitmap/_query.py +113 -0
- scitex/plt/utils/_hitmap.py +46 -1616
- scitex/plt/utils/_metadata/__init__.py +80 -0
- scitex/plt/utils/_metadata/_artists/__init__.py +25 -0
- scitex/plt/utils/_metadata/_artists/_base.py +195 -0
- scitex/plt/utils/_metadata/_artists/_collections.py +356 -0
- scitex/plt/utils/_metadata/_artists/_extract.py +57 -0
- scitex/plt/utils/_metadata/_artists/_images.py +80 -0
- scitex/plt/utils/_metadata/_artists/_lines.py +261 -0
- scitex/plt/utils/_metadata/_artists/_patches.py +247 -0
- scitex/plt/utils/_metadata/_artists/_text.py +106 -0
- scitex/plt/utils/_metadata/_csv.py +416 -0
- scitex/plt/utils/_metadata/_detect.py +225 -0
- scitex/plt/utils/_metadata/_legend.py +127 -0
- scitex/plt/utils/_metadata/_rounding.py +117 -0
- scitex/plt/utils/_metadata/_verification.py +202 -0
- scitex/schema/README.md +1 -1
- scitex/scholar/__init__.py +8 -0
- scitex/scholar/_mcp/crossref_handlers.py +265 -0
- scitex/scholar/core/Scholar.py +63 -1700
- scitex/scholar/core/_mixins/__init__.py +36 -0
- scitex/scholar/core/_mixins/_enrichers.py +270 -0
- scitex/scholar/core/_mixins/_library_handlers.py +100 -0
- scitex/scholar/core/_mixins/_loaders.py +103 -0
- scitex/scholar/core/_mixins/_pdf_download.py +375 -0
- scitex/scholar/core/_mixins/_pipeline.py +312 -0
- scitex/scholar/core/_mixins/_project_handlers.py +125 -0
- scitex/scholar/core/_mixins/_savers.py +69 -0
- scitex/scholar/core/_mixins/_search.py +103 -0
- scitex/scholar/core/_mixins/_services.py +88 -0
- scitex/scholar/core/_mixins/_url_finding.py +105 -0
- scitex/scholar/crossref_scitex.py +367 -0
- scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/scholar/examples/00_run_all.sh +120 -0
- scitex/scholar/jobs/_executors.py +27 -3
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +38 -416
- scitex/scholar/pdf_download/_cli.py +154 -0
- scitex/scholar/pdf_download/strategies/__init__.py +11 -8
- scitex/scholar/pdf_download/strategies/manual_download_fallback.py +80 -3
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +73 -121
- scitex/scholar/pipelines/ScholarPipelineParallel.py +80 -138
- scitex/scholar/pipelines/ScholarPipelineSingle.py +43 -63
- scitex/scholar/pipelines/_single_steps.py +71 -36
- scitex/scholar/storage/_LibraryManager.py +97 -1695
- scitex/scholar/storage/_mixins/__init__.py +30 -0
- scitex/scholar/storage/_mixins/_bibtex_handlers.py +128 -0
- scitex/scholar/storage/_mixins/_library_operations.py +218 -0
- scitex/scholar/storage/_mixins/_metadata_conversion.py +226 -0
- scitex/scholar/storage/_mixins/_paper_saving.py +456 -0
- scitex/scholar/storage/_mixins/_resolution.py +376 -0
- scitex/scholar/storage/_mixins/_storage_helpers.py +121 -0
- scitex/scholar/storage/_mixins/_symlink_handlers.py +226 -0
- scitex/security/README.md +3 -3
- scitex/session/README.md +1 -1
- scitex/session/__init__.py +26 -7
- scitex/session/_decorator.py +1 -1
- scitex/sh/README.md +1 -1
- scitex/sh/__init__.py +7 -4
- scitex/social/__init__.py +155 -0
- scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/stats/_mcp/_handlers/__init__.py +31 -0
- scitex/stats/_mcp/_handlers/_corrections.py +113 -0
- scitex/stats/_mcp/_handlers/_descriptive.py +78 -0
- scitex/stats/_mcp/_handlers/_effect_size.py +106 -0
- scitex/stats/_mcp/_handlers/_format.py +94 -0
- scitex/stats/_mcp/_handlers/_normality.py +110 -0
- scitex/stats/_mcp/_handlers/_posthoc.py +224 -0
- scitex/stats/_mcp/_handlers/_power.py +247 -0
- scitex/stats/_mcp/_handlers/_recommend.py +102 -0
- scitex/stats/_mcp/_handlers/_run_test.py +279 -0
- scitex/stats/_mcp/_handlers/_stars.py +48 -0
- scitex/stats/_mcp/handlers.py +19 -1171
- scitex/stats/auto/_stat_style.py +175 -0
- scitex/stats/auto/_style_definitions.py +411 -0
- scitex/stats/auto/_styles.py +22 -620
- scitex/stats/descriptive/__init__.py +11 -8
- scitex/stats/descriptive/_ci.py +39 -0
- scitex/stats/power/_power.py +15 -4
- scitex/str/__init__.py +2 -1
- scitex/str/_title_case.py +63 -0
- scitex/template/README.md +1 -1
- scitex/template/__init__.py +25 -10
- scitex/template/_code_templates.py +147 -0
- scitex/template/_mcp/handlers.py +81 -0
- scitex/template/_mcp/tool_schemas.py +55 -0
- scitex/template/_templates/__init__.py +51 -0
- scitex/template/_templates/audio.py +233 -0
- scitex/template/_templates/canvas.py +312 -0
- scitex/template/_templates/capture.py +268 -0
- scitex/template/_templates/config.py +43 -0
- scitex/template/_templates/diagram.py +294 -0
- scitex/template/_templates/io.py +107 -0
- scitex/template/_templates/module.py +53 -0
- scitex/template/_templates/plt.py +202 -0
- scitex/template/_templates/scholar.py +267 -0
- scitex/template/_templates/session.py +130 -0
- scitex/template/_templates/session_minimal.py +43 -0
- scitex/template/_templates/session_plot.py +67 -0
- scitex/template/_templates/session_stats.py +77 -0
- scitex/template/_templates/stats.py +323 -0
- scitex/template/_templates/writer.py +296 -0
- scitex/template/clone_writer_directory.py +5 -5
- scitex/ui/_backends/_email.py +10 -2
- scitex/ui/_backends/_webhook.py +5 -1
- scitex/web/_search_pubmed.py +10 -6
- scitex/writer/README.md +1 -1
- scitex/writer/__init__.py +43 -34
- scitex/writer/_mcp/handlers.py +11 -744
- scitex/writer/_mcp/tool_schemas.py +5 -335
- scitex-2.15.3.dist-info/METADATA +667 -0
- {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/RECORD +241 -120
- scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
- scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
- scitex/diagram/_compile.py +0 -312
- scitex/diagram/_diagram.py +0 -355
- scitex/diagram/_mcp/__init__.py +0 -4
- scitex/diagram/_mcp/handlers.py +0 -400
- scitex/diagram/_mcp/tool_schemas.py +0 -157
- scitex/diagram/_presets.py +0 -173
- scitex/diagram/_schema.py +0 -182
- scitex/diagram/_split.py +0 -278
- scitex/gen/_ci.py +0 -12
- scitex/gen/_title_case.py +0 -89
- scitex/plt/_mcp/__init__.py +0 -4
- scitex/plt/_mcp/_handlers_annotation.py +0 -102
- scitex/plt/_mcp/_handlers_figure.py +0 -195
- scitex/plt/_mcp/_handlers_plot.py +0 -252
- scitex/plt/_mcp/_handlers_style.py +0 -219
- scitex/plt/_mcp/handlers.py +0 -74
- scitex/plt/_mcp/tool_schemas.py +0 -497
- scitex/plt/mcp_server.py +0 -231
- scitex/scholar/examples/SUGGESTIONS.md +0 -865
- scitex/scholar/examples/dev.py +0 -38
- scitex-2.14.0.dist-info/METADATA +0 -1238
- /scitex/{gen → context}/_detect_environment.py +0 -0
- /scitex/{gen → context}/_get_notebook_path.py +0 -0
- /scitex/{gen/_shell.py → sh/_shell_legacy.py} +0 -0
- {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/WHEEL +0 -0
- {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/entry_points.txt +0 -0
- {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2025-01-20
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/introspect/_mcp/__init__.py
|
|
4
|
+
|
|
5
|
+
"""MCP tools for introspection."""
|
|
6
|
+
|
|
7
|
+
from .handlers import (
|
|
8
|
+
# Advanced
|
|
9
|
+
call_graph_handler,
|
|
10
|
+
class_hierarchy_handler,
|
|
11
|
+
dependencies_handler,
|
|
12
|
+
# IPython-style names
|
|
13
|
+
dir_handler,
|
|
14
|
+
# Basic
|
|
15
|
+
docstring_handler,
|
|
16
|
+
examples_handler,
|
|
17
|
+
exports_handler,
|
|
18
|
+
imports_handler,
|
|
19
|
+
list_api_handler,
|
|
20
|
+
q_handler,
|
|
21
|
+
qq_handler,
|
|
22
|
+
type_hints_handler,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
# IPython-style names
|
|
27
|
+
"q_handler",
|
|
28
|
+
"qq_handler",
|
|
29
|
+
"dir_handler",
|
|
30
|
+
"list_api_handler",
|
|
31
|
+
# Basic
|
|
32
|
+
"docstring_handler",
|
|
33
|
+
"exports_handler",
|
|
34
|
+
"examples_handler",
|
|
35
|
+
# Advanced
|
|
36
|
+
"class_hierarchy_handler",
|
|
37
|
+
"type_hints_handler",
|
|
38
|
+
"imports_handler",
|
|
39
|
+
"dependencies_handler",
|
|
40
|
+
"call_graph_handler",
|
|
41
|
+
]
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2025-01-20
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/introspect/_mcp/handlers.py
|
|
4
|
+
|
|
5
|
+
"""MCP handlers for introspection tools."""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Literal
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def q_handler(
|
|
13
|
+
dotted_path: str,
|
|
14
|
+
include_defaults: bool = True,
|
|
15
|
+
include_annotations: bool = True,
|
|
16
|
+
) -> dict:
|
|
17
|
+
"""Get the signature of a function, method, or class (like IPython's func?)."""
|
|
18
|
+
try:
|
|
19
|
+
from .. import q
|
|
20
|
+
|
|
21
|
+
result = q(
|
|
22
|
+
dotted_path,
|
|
23
|
+
include_defaults=include_defaults,
|
|
24
|
+
include_annotations=include_annotations,
|
|
25
|
+
)
|
|
26
|
+
return result
|
|
27
|
+
except Exception as e:
|
|
28
|
+
return {"success": False, "error": str(e)}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
async def docstring_handler(
|
|
32
|
+
dotted_path: str,
|
|
33
|
+
format: Literal["raw", "parsed", "summary"] = "raw",
|
|
34
|
+
) -> dict:
|
|
35
|
+
"""Get the docstring of a Python object."""
|
|
36
|
+
try:
|
|
37
|
+
from .. import get_docstring
|
|
38
|
+
|
|
39
|
+
result = get_docstring(dotted_path, format=format)
|
|
40
|
+
return result
|
|
41
|
+
except Exception as e:
|
|
42
|
+
return {"success": False, "error": str(e)}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async def qq_handler(
|
|
46
|
+
dotted_path: str,
|
|
47
|
+
max_lines: int | None = None,
|
|
48
|
+
include_decorators: bool = True,
|
|
49
|
+
) -> dict:
|
|
50
|
+
"""Get the source code of a Python object (like IPython's func??)."""
|
|
51
|
+
try:
|
|
52
|
+
from .. import qq
|
|
53
|
+
|
|
54
|
+
result = qq(
|
|
55
|
+
dotted_path,
|
|
56
|
+
max_lines=max_lines,
|
|
57
|
+
include_decorators=include_decorators,
|
|
58
|
+
)
|
|
59
|
+
return result
|
|
60
|
+
except Exception as e:
|
|
61
|
+
return {"success": False, "error": str(e)}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
async def dir_handler(
|
|
65
|
+
dotted_path: str,
|
|
66
|
+
filter: Literal["all", "public", "private", "dunder"] = "public",
|
|
67
|
+
kind: Literal["all", "functions", "classes", "data", "modules"] | None = None,
|
|
68
|
+
include_inherited: bool = False,
|
|
69
|
+
) -> dict:
|
|
70
|
+
"""List members of a module or class (like dir())."""
|
|
71
|
+
try:
|
|
72
|
+
from .. import dir
|
|
73
|
+
|
|
74
|
+
result = dir(
|
|
75
|
+
dotted_path,
|
|
76
|
+
filter=filter,
|
|
77
|
+
kind=kind,
|
|
78
|
+
include_inherited=include_inherited,
|
|
79
|
+
)
|
|
80
|
+
return result
|
|
81
|
+
except Exception as e:
|
|
82
|
+
return {"success": False, "error": str(e)}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
async def exports_handler(dotted_path: str) -> dict:
|
|
86
|
+
"""Get the __all__ exports of a module."""
|
|
87
|
+
try:
|
|
88
|
+
from .. import get_exports
|
|
89
|
+
|
|
90
|
+
result = get_exports(dotted_path)
|
|
91
|
+
return result
|
|
92
|
+
except Exception as e:
|
|
93
|
+
return {"success": False, "error": str(e)}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
async def examples_handler(
|
|
97
|
+
dotted_path: str,
|
|
98
|
+
search_paths: list[str] | None = None,
|
|
99
|
+
max_results: int = 10,
|
|
100
|
+
) -> dict:
|
|
101
|
+
"""Find usage examples of a function/class in tests and examples."""
|
|
102
|
+
try:
|
|
103
|
+
from .. import find_examples
|
|
104
|
+
|
|
105
|
+
result = find_examples(
|
|
106
|
+
dotted_path,
|
|
107
|
+
search_paths=search_paths,
|
|
108
|
+
max_results=max_results,
|
|
109
|
+
)
|
|
110
|
+
return result
|
|
111
|
+
except Exception as e:
|
|
112
|
+
return {"success": False, "error": str(e)}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# Advanced handlers
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
async def class_hierarchy_handler(
|
|
119
|
+
dotted_path: str,
|
|
120
|
+
include_builtins: bool = False,
|
|
121
|
+
max_depth: int = 10,
|
|
122
|
+
) -> dict:
|
|
123
|
+
"""Get the inheritance hierarchy of a class."""
|
|
124
|
+
try:
|
|
125
|
+
from .. import get_class_hierarchy
|
|
126
|
+
|
|
127
|
+
result = get_class_hierarchy(
|
|
128
|
+
dotted_path,
|
|
129
|
+
include_builtins=include_builtins,
|
|
130
|
+
max_depth=max_depth,
|
|
131
|
+
)
|
|
132
|
+
return result
|
|
133
|
+
except Exception as e:
|
|
134
|
+
return {"success": False, "error": str(e)}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
async def type_hints_handler(
|
|
138
|
+
dotted_path: str,
|
|
139
|
+
include_extras: bool = True,
|
|
140
|
+
) -> dict:
|
|
141
|
+
"""Get detailed type hint information."""
|
|
142
|
+
try:
|
|
143
|
+
from .. import get_type_hints_detailed
|
|
144
|
+
|
|
145
|
+
result = get_type_hints_detailed(
|
|
146
|
+
dotted_path,
|
|
147
|
+
include_extras=include_extras,
|
|
148
|
+
)
|
|
149
|
+
return result
|
|
150
|
+
except Exception as e:
|
|
151
|
+
return {"success": False, "error": str(e)}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
async def imports_handler(
|
|
155
|
+
dotted_path: str,
|
|
156
|
+
categorize: bool = True,
|
|
157
|
+
) -> dict:
|
|
158
|
+
"""Get all imports from a module."""
|
|
159
|
+
try:
|
|
160
|
+
from .. import get_imports
|
|
161
|
+
|
|
162
|
+
result = get_imports(
|
|
163
|
+
dotted_path,
|
|
164
|
+
categorize=categorize,
|
|
165
|
+
)
|
|
166
|
+
return result
|
|
167
|
+
except Exception as e:
|
|
168
|
+
return {"success": False, "error": str(e)}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
async def dependencies_handler(
|
|
172
|
+
dotted_path: str,
|
|
173
|
+
recursive: bool = False,
|
|
174
|
+
max_depth: int = 3,
|
|
175
|
+
) -> dict:
|
|
176
|
+
"""Get module dependencies."""
|
|
177
|
+
try:
|
|
178
|
+
from .. import get_dependencies
|
|
179
|
+
|
|
180
|
+
result = get_dependencies(
|
|
181
|
+
dotted_path,
|
|
182
|
+
recursive=recursive,
|
|
183
|
+
max_depth=max_depth,
|
|
184
|
+
)
|
|
185
|
+
return result
|
|
186
|
+
except Exception as e:
|
|
187
|
+
return {"success": False, "error": str(e)}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
async def call_graph_handler(
|
|
191
|
+
dotted_path: str,
|
|
192
|
+
max_depth: int = 2,
|
|
193
|
+
timeout_seconds: int = 10,
|
|
194
|
+
internal_only: bool = True,
|
|
195
|
+
) -> dict:
|
|
196
|
+
"""Get the call graph of a function or module."""
|
|
197
|
+
try:
|
|
198
|
+
from .. import get_call_graph
|
|
199
|
+
|
|
200
|
+
result = get_call_graph(
|
|
201
|
+
dotted_path,
|
|
202
|
+
max_depth=max_depth,
|
|
203
|
+
timeout_seconds=timeout_seconds,
|
|
204
|
+
internal_only=internal_only,
|
|
205
|
+
)
|
|
206
|
+
return result
|
|
207
|
+
except Exception as e:
|
|
208
|
+
return {"success": False, "error": str(e)}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
async def list_api_handler(
|
|
212
|
+
dotted_path: str,
|
|
213
|
+
max_depth: int = 5,
|
|
214
|
+
docstring: bool = False,
|
|
215
|
+
root_only: bool = False,
|
|
216
|
+
) -> dict:
|
|
217
|
+
"""List the API tree of a module recursively."""
|
|
218
|
+
try:
|
|
219
|
+
from .. import list_api
|
|
220
|
+
|
|
221
|
+
df = list_api(
|
|
222
|
+
dotted_path,
|
|
223
|
+
max_depth=max_depth,
|
|
224
|
+
docstring=docstring,
|
|
225
|
+
root_only=root_only,
|
|
226
|
+
)
|
|
227
|
+
return {
|
|
228
|
+
"success": True,
|
|
229
|
+
"api": df.to_dict(orient="records"),
|
|
230
|
+
"count": len(df),
|
|
231
|
+
}
|
|
232
|
+
except Exception as e:
|
|
233
|
+
return {"success": False, "error": str(e)}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2025-01-20
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/introspect/_members.py
|
|
4
|
+
|
|
5
|
+
"""Member listing utilities."""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import builtins
|
|
10
|
+
import inspect
|
|
11
|
+
from typing import Literal
|
|
12
|
+
|
|
13
|
+
from ._resolve import get_type_info, resolve_object
|
|
14
|
+
|
|
15
|
+
# Save reference to built-in dir before shadowing
|
|
16
|
+
_builtin_dir = builtins.dir
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def dir(
|
|
20
|
+
dotted_path: str,
|
|
21
|
+
filter: Literal["all", "public", "private", "dunder"] = "public",
|
|
22
|
+
kind: Literal["all", "functions", "classes", "data", "modules"] | None = None,
|
|
23
|
+
include_inherited: bool = False,
|
|
24
|
+
) -> dict:
|
|
25
|
+
"""
|
|
26
|
+
List members of a module or class.
|
|
27
|
+
|
|
28
|
+
Like Python's `dir()` but with filtering and metadata.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
dotted_path : str
|
|
33
|
+
Dotted path to the module or class
|
|
34
|
+
filter : str
|
|
35
|
+
'all' - All members
|
|
36
|
+
'public' - Only public (no leading _)
|
|
37
|
+
'private' - Only private (single _)
|
|
38
|
+
'dunder' - Only dunder (__name__)
|
|
39
|
+
kind : str | None
|
|
40
|
+
Filter by type: 'functions', 'classes', 'data', 'modules'
|
|
41
|
+
include_inherited : bool
|
|
42
|
+
For classes, include inherited members
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
dict
|
|
47
|
+
members: list[dict] - Each with name, kind, summary
|
|
48
|
+
count: int
|
|
49
|
+
type_info: dict
|
|
50
|
+
"""
|
|
51
|
+
obj, error = resolve_object(dotted_path)
|
|
52
|
+
if error:
|
|
53
|
+
return {"success": False, "error": error}
|
|
54
|
+
|
|
55
|
+
type_info = get_type_info(obj)
|
|
56
|
+
|
|
57
|
+
if inspect.isclass(obj) and not include_inherited:
|
|
58
|
+
member_names = list(obj.__dict__.keys())
|
|
59
|
+
else:
|
|
60
|
+
member_names = _builtin_dir(obj)
|
|
61
|
+
|
|
62
|
+
if filter == "public":
|
|
63
|
+
member_names = [n for n in member_names if not n.startswith("_")]
|
|
64
|
+
elif filter == "private":
|
|
65
|
+
member_names = [
|
|
66
|
+
n for n in member_names if n.startswith("_") and not n.startswith("__")
|
|
67
|
+
]
|
|
68
|
+
elif filter == "dunder":
|
|
69
|
+
member_names = [
|
|
70
|
+
n for n in member_names if n.startswith("__") and n.endswith("__")
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
members = []
|
|
74
|
+
for name in sorted(member_names):
|
|
75
|
+
try:
|
|
76
|
+
member = getattr(obj, name)
|
|
77
|
+
except AttributeError:
|
|
78
|
+
continue
|
|
79
|
+
|
|
80
|
+
member_type_info = get_type_info(member)
|
|
81
|
+
member_kind = member_type_info["kind"]
|
|
82
|
+
|
|
83
|
+
if kind:
|
|
84
|
+
kind_map = {
|
|
85
|
+
"functions": ("function", "method", "builtin_function_or_method"),
|
|
86
|
+
"classes": ("class",),
|
|
87
|
+
"data": ("data",),
|
|
88
|
+
"modules": ("module",),
|
|
89
|
+
}
|
|
90
|
+
if kind in kind_map and member_kind not in kind_map[kind]:
|
|
91
|
+
continue
|
|
92
|
+
|
|
93
|
+
doc = inspect.getdoc(member) or ""
|
|
94
|
+
summary = doc.split("\n")[0] if doc else ""
|
|
95
|
+
|
|
96
|
+
members.append(
|
|
97
|
+
{
|
|
98
|
+
"name": name,
|
|
99
|
+
"kind": member_kind,
|
|
100
|
+
"summary": summary[:100] + "..." if len(summary) > 100 else summary,
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
"success": True,
|
|
106
|
+
"members": members,
|
|
107
|
+
"count": len(members),
|
|
108
|
+
"type_info": type_info,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def get_exports(dotted_path: str) -> dict:
|
|
113
|
+
"""
|
|
114
|
+
Get the __all__ exports of a module.
|
|
115
|
+
|
|
116
|
+
Parameters
|
|
117
|
+
----------
|
|
118
|
+
dotted_path : str
|
|
119
|
+
Dotted path to the module
|
|
120
|
+
|
|
121
|
+
Returns
|
|
122
|
+
-------
|
|
123
|
+
dict
|
|
124
|
+
exports: list[str] - Names in __all__
|
|
125
|
+
has_all: bool - Whether __all__ is defined
|
|
126
|
+
type_info: dict
|
|
127
|
+
"""
|
|
128
|
+
obj, error = resolve_object(dotted_path)
|
|
129
|
+
if error:
|
|
130
|
+
return {"success": False, "error": error}
|
|
131
|
+
|
|
132
|
+
type_info = get_type_info(obj)
|
|
133
|
+
|
|
134
|
+
if not inspect.ismodule(obj):
|
|
135
|
+
return {
|
|
136
|
+
"success": False,
|
|
137
|
+
"error": f"'{dotted_path}' is not a module",
|
|
138
|
+
"type_info": type_info,
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
exports = getattr(obj, "__all__", None)
|
|
142
|
+
|
|
143
|
+
if exports is None:
|
|
144
|
+
exports = [n for n in _builtin_dir(obj) if not n.startswith("_")]
|
|
145
|
+
has_all = False
|
|
146
|
+
else:
|
|
147
|
+
has_all = True
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
"success": True,
|
|
151
|
+
"exports": list(exports),
|
|
152
|
+
"has_all": has_all,
|
|
153
|
+
"count": len(exports),
|
|
154
|
+
"type_info": type_info,
|
|
155
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2025-01-20
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/introspect/_resolve.py
|
|
4
|
+
|
|
5
|
+
"""Object resolution and type information utilities."""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import importlib
|
|
10
|
+
import inspect
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def resolve_object(dotted_path: str) -> tuple[Any, str | None]:
|
|
15
|
+
"""
|
|
16
|
+
Resolve a dotted path to a Python object.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
dotted_path : str
|
|
21
|
+
Dotted path like 'scitex.plt.plot' or 'scitex.audio'
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
tuple[Any, str | None]
|
|
26
|
+
(resolved_object, error_message)
|
|
27
|
+
If successful, error_message is None
|
|
28
|
+
|
|
29
|
+
Examples
|
|
30
|
+
--------
|
|
31
|
+
>>> obj, err = resolve_object("scitex.plt")
|
|
32
|
+
>>> obj, err = resolve_object("scitex.audio.speak")
|
|
33
|
+
"""
|
|
34
|
+
parts = dotted_path.split(".")
|
|
35
|
+
obj = None
|
|
36
|
+
last_error = None
|
|
37
|
+
|
|
38
|
+
for i in range(len(parts), 0, -1):
|
|
39
|
+
module_path = ".".join(parts[:i])
|
|
40
|
+
try:
|
|
41
|
+
obj = importlib.import_module(module_path)
|
|
42
|
+
for attr_name in parts[i:]:
|
|
43
|
+
obj = getattr(obj, attr_name)
|
|
44
|
+
return obj, None
|
|
45
|
+
except (ImportError, AttributeError) as e:
|
|
46
|
+
last_error = str(e)
|
|
47
|
+
continue
|
|
48
|
+
|
|
49
|
+
return None, f"Could not resolve '{dotted_path}': {last_error}"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_type_info(obj: Any) -> dict:
|
|
53
|
+
"""
|
|
54
|
+
Get type information about an object.
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
dict
|
|
59
|
+
type: str - The type name
|
|
60
|
+
kind: str - 'module', 'class', 'function', 'method', 'property', 'data'
|
|
61
|
+
module: str - Module where defined
|
|
62
|
+
qualname: str - Qualified name
|
|
63
|
+
"""
|
|
64
|
+
type_name = type(obj).__name__
|
|
65
|
+
|
|
66
|
+
if inspect.ismodule(obj):
|
|
67
|
+
kind = "module"
|
|
68
|
+
elif inspect.isclass(obj):
|
|
69
|
+
kind = "class"
|
|
70
|
+
elif inspect.isfunction(obj) or inspect.isbuiltin(obj):
|
|
71
|
+
kind = "function"
|
|
72
|
+
elif inspect.ismethod(obj):
|
|
73
|
+
kind = "method"
|
|
74
|
+
elif isinstance(obj, property):
|
|
75
|
+
kind = "property"
|
|
76
|
+
elif callable(obj):
|
|
77
|
+
kind = "callable"
|
|
78
|
+
else:
|
|
79
|
+
kind = "data"
|
|
80
|
+
|
|
81
|
+
module_name = getattr(obj, "__module__", None)
|
|
82
|
+
qualname = getattr(obj, "__qualname__", getattr(obj, "__name__", str(obj)))
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
"type": type_name,
|
|
86
|
+
"kind": kind,
|
|
87
|
+
"module": module_name,
|
|
88
|
+
"qualname": qualname,
|
|
89
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2025-01-20
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/introspect/_signature.py
|
|
4
|
+
|
|
5
|
+
"""Signature extraction utilities."""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import inspect
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from ._resolve import get_type_info, resolve_object
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _format_annotation(annotation: Any) -> str:
|
|
16
|
+
"""Format a type annotation as a string."""
|
|
17
|
+
if annotation is None:
|
|
18
|
+
return "None"
|
|
19
|
+
if hasattr(annotation, "__name__"):
|
|
20
|
+
return annotation.__name__
|
|
21
|
+
return str(annotation).replace("typing.", "")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _build_signature_string(
|
|
25
|
+
obj: Any,
|
|
26
|
+
parameters: list[dict],
|
|
27
|
+
return_annotation: str | None,
|
|
28
|
+
) -> str:
|
|
29
|
+
"""Build a human-readable signature string."""
|
|
30
|
+
name = getattr(obj, "__name__", "?")
|
|
31
|
+
|
|
32
|
+
param_strs = []
|
|
33
|
+
for p in parameters:
|
|
34
|
+
s = p["name"]
|
|
35
|
+
if "annotation" in p:
|
|
36
|
+
s += f": {p['annotation']}"
|
|
37
|
+
if "default" in p:
|
|
38
|
+
s += f" = {p['default']}"
|
|
39
|
+
param_strs.append(s)
|
|
40
|
+
|
|
41
|
+
sig = f"{name}({', '.join(param_strs)})"
|
|
42
|
+
if return_annotation:
|
|
43
|
+
sig += f" -> {return_annotation}"
|
|
44
|
+
|
|
45
|
+
return sig
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def q(
|
|
49
|
+
dotted_path: str,
|
|
50
|
+
include_defaults: bool = True,
|
|
51
|
+
include_annotations: bool = True,
|
|
52
|
+
) -> dict:
|
|
53
|
+
"""
|
|
54
|
+
Get the signature of a function, method, or class.
|
|
55
|
+
|
|
56
|
+
Like IPython's `func?` (quick info).
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
dotted_path : str
|
|
61
|
+
Dotted path to the callable (e.g., 'scitex.plt.plot')
|
|
62
|
+
include_defaults : bool
|
|
63
|
+
Include default values in signature
|
|
64
|
+
include_annotations : bool
|
|
65
|
+
Include type annotations
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
dict
|
|
70
|
+
name: str
|
|
71
|
+
signature: str - Human-readable signature
|
|
72
|
+
parameters: list[dict] - Detailed parameter info
|
|
73
|
+
return_annotation: str | None
|
|
74
|
+
type_info: dict
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
>>> q("scitex.plt.plot")
|
|
79
|
+
{'name': 'plot', 'signature': 'plot(spec: dict, ...) -> dict', ...}
|
|
80
|
+
"""
|
|
81
|
+
obj, error = resolve_object(dotted_path)
|
|
82
|
+
if error:
|
|
83
|
+
return {"success": False, "error": error}
|
|
84
|
+
|
|
85
|
+
type_info = get_type_info(obj)
|
|
86
|
+
|
|
87
|
+
callable_obj = obj
|
|
88
|
+
if inspect.isclass(obj):
|
|
89
|
+
callable_obj = obj.__init__
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
sig = inspect.signature(callable_obj)
|
|
93
|
+
except (ValueError, TypeError) as e:
|
|
94
|
+
return {
|
|
95
|
+
"success": False,
|
|
96
|
+
"error": f"Cannot get signature: {e}",
|
|
97
|
+
"type_info": type_info,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
parameters = []
|
|
101
|
+
for name, param in sig.parameters.items():
|
|
102
|
+
if name == "self":
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
param_info = {
|
|
106
|
+
"name": name,
|
|
107
|
+
"kind": str(param.kind).split(".")[-1],
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if include_annotations and param.annotation != inspect.Parameter.empty:
|
|
111
|
+
param_info["annotation"] = _format_annotation(param.annotation)
|
|
112
|
+
|
|
113
|
+
if include_defaults and param.default != inspect.Parameter.empty:
|
|
114
|
+
param_info["default"] = repr(param.default)
|
|
115
|
+
|
|
116
|
+
parameters.append(param_info)
|
|
117
|
+
|
|
118
|
+
return_annotation = None
|
|
119
|
+
if include_annotations and sig.return_annotation != inspect.Signature.empty:
|
|
120
|
+
return_annotation = _format_annotation(sig.return_annotation)
|
|
121
|
+
|
|
122
|
+
sig_str = _build_signature_string(obj, parameters, return_annotation)
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
"success": True,
|
|
126
|
+
"name": getattr(obj, "__name__", dotted_path.split(".")[-1]),
|
|
127
|
+
"signature": sig_str,
|
|
128
|
+
"parameters": parameters,
|
|
129
|
+
"return_annotation": return_annotation,
|
|
130
|
+
"type_info": type_info,
|
|
131
|
+
}
|