scitex 2.14.0__py3-none-any.whl → 2.15.2__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.
Files changed (300) hide show
  1. scitex/__init__.py +71 -17
  2. scitex/_env_loader.py +156 -0
  3. scitex/_mcp_resources/__init__.py +37 -0
  4. scitex/_mcp_resources/_cheatsheet.py +135 -0
  5. scitex/_mcp_resources/_figrecipe.py +138 -0
  6. scitex/_mcp_resources/_formats.py +102 -0
  7. scitex/_mcp_resources/_modules.py +337 -0
  8. scitex/_mcp_resources/_session.py +149 -0
  9. scitex/_mcp_tools/__init__.py +4 -0
  10. scitex/_mcp_tools/audio.py +66 -0
  11. scitex/_mcp_tools/diagram.py +11 -95
  12. scitex/_mcp_tools/introspect.py +210 -0
  13. scitex/_mcp_tools/plt.py +260 -305
  14. scitex/_mcp_tools/scholar.py +74 -0
  15. scitex/_mcp_tools/social.py +244 -0
  16. scitex/_mcp_tools/template.py +24 -0
  17. scitex/_mcp_tools/writer.py +21 -204
  18. scitex/ai/_gen_ai/_PARAMS.py +10 -7
  19. scitex/ai/classification/reporters/_SingleClassificationReporter.py +45 -1603
  20. scitex/ai/classification/reporters/_mixins/__init__.py +36 -0
  21. scitex/ai/classification/reporters/_mixins/_constants.py +67 -0
  22. scitex/ai/classification/reporters/_mixins/_cv_summary.py +387 -0
  23. scitex/ai/classification/reporters/_mixins/_feature_importance.py +119 -0
  24. scitex/ai/classification/reporters/_mixins/_metrics.py +275 -0
  25. scitex/ai/classification/reporters/_mixins/_plotting.py +179 -0
  26. scitex/ai/classification/reporters/_mixins/_reports.py +153 -0
  27. scitex/ai/classification/reporters/_mixins/_storage.py +160 -0
  28. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +30 -1550
  29. scitex/ai/classification/timeseries/_sliding_window_core.py +467 -0
  30. scitex/ai/classification/timeseries/_sliding_window_plotting.py +369 -0
  31. scitex/audio/README.md +40 -36
  32. scitex/audio/__init__.py +129 -61
  33. scitex/audio/_branding.py +185 -0
  34. scitex/audio/_mcp/__init__.py +32 -0
  35. scitex/audio/_mcp/handlers.py +59 -6
  36. scitex/audio/_mcp/speak_handlers.py +238 -0
  37. scitex/audio/_relay.py +225 -0
  38. scitex/audio/_tts.py +18 -10
  39. scitex/audio/engines/base.py +17 -10
  40. scitex/audio/engines/elevenlabs_engine.py +7 -2
  41. scitex/audio/mcp_server.py +228 -75
  42. scitex/canvas/README.md +1 -1
  43. scitex/canvas/editor/_dearpygui/__init__.py +25 -0
  44. scitex/canvas/editor/_dearpygui/_editor.py +147 -0
  45. scitex/canvas/editor/_dearpygui/_handlers.py +476 -0
  46. scitex/canvas/editor/_dearpygui/_panels/__init__.py +17 -0
  47. scitex/canvas/editor/_dearpygui/_panels/_control.py +119 -0
  48. scitex/canvas/editor/_dearpygui/_panels/_element_controls.py +190 -0
  49. scitex/canvas/editor/_dearpygui/_panels/_preview.py +43 -0
  50. scitex/canvas/editor/_dearpygui/_panels/_sections.py +390 -0
  51. scitex/canvas/editor/_dearpygui/_plotting.py +187 -0
  52. scitex/canvas/editor/_dearpygui/_rendering.py +504 -0
  53. scitex/canvas/editor/_dearpygui/_selection.py +295 -0
  54. scitex/canvas/editor/_dearpygui/_state.py +93 -0
  55. scitex/canvas/editor/_dearpygui/_utils.py +61 -0
  56. scitex/canvas/editor/flask_editor/_core/__init__.py +27 -0
  57. scitex/canvas/editor/flask_editor/_core/_bbox_extraction.py +200 -0
  58. scitex/canvas/editor/flask_editor/_core/_editor.py +173 -0
  59. scitex/canvas/editor/flask_editor/_core/_export_helpers.py +353 -0
  60. scitex/canvas/editor/flask_editor/_core/_routes_basic.py +190 -0
  61. scitex/canvas/editor/flask_editor/_core/_routes_export.py +332 -0
  62. scitex/canvas/editor/flask_editor/_core/_routes_panels.py +252 -0
  63. scitex/canvas/editor/flask_editor/_core/_routes_save.py +218 -0
  64. scitex/canvas/editor/flask_editor/_core.py +25 -1684
  65. scitex/canvas/editor/flask_editor/templates/__init__.py +32 -70
  66. scitex/cli/__init__.py +38 -43
  67. scitex/cli/audio.py +76 -27
  68. scitex/cli/capture.py +13 -20
  69. scitex/cli/introspect.py +481 -0
  70. scitex/cli/main.py +200 -109
  71. scitex/cli/mcp.py +60 -34
  72. scitex/cli/plt.py +357 -0
  73. scitex/cli/repro.py +15 -8
  74. scitex/cli/resource.py +15 -8
  75. scitex/cli/scholar/__init__.py +23 -8
  76. scitex/cli/scholar/_crossref_scitex.py +296 -0
  77. scitex/cli/scholar/_fetch.py +25 -3
  78. scitex/cli/social.py +314 -0
  79. scitex/cli/stats.py +15 -8
  80. scitex/cli/template.py +129 -12
  81. scitex/cli/tex.py +15 -8
  82. scitex/cli/writer.py +132 -8
  83. scitex/cloud/__init__.py +41 -2
  84. scitex/config/README.md +1 -1
  85. scitex/config/__init__.py +16 -2
  86. scitex/config/_env_registry.py +256 -0
  87. scitex/context/__init__.py +22 -0
  88. scitex/dev/__init__.py +20 -1
  89. scitex/diagram/__init__.py +42 -19
  90. scitex/diagram/mcp_server.py +13 -125
  91. scitex/gen/__init__.py +50 -14
  92. scitex/gen/_list_packages.py +4 -4
  93. scitex/introspect/__init__.py +82 -0
  94. scitex/introspect/_call_graph.py +303 -0
  95. scitex/introspect/_class_hierarchy.py +163 -0
  96. scitex/introspect/_core.py +41 -0
  97. scitex/introspect/_docstring.py +131 -0
  98. scitex/introspect/_examples.py +113 -0
  99. scitex/introspect/_imports.py +271 -0
  100. scitex/{gen/_inspect_module.py → introspect/_list_api.py} +43 -54
  101. scitex/introspect/_mcp/__init__.py +41 -0
  102. scitex/introspect/_mcp/handlers.py +233 -0
  103. scitex/introspect/_members.py +155 -0
  104. scitex/introspect/_resolve.py +89 -0
  105. scitex/introspect/_signature.py +131 -0
  106. scitex/introspect/_source.py +80 -0
  107. scitex/introspect/_type_hints.py +172 -0
  108. scitex/io/_save.py +1 -2
  109. scitex/io/bundle/README.md +1 -1
  110. scitex/logging/_formatters.py +19 -9
  111. scitex/mcp_server.py +98 -5
  112. scitex/os/__init__.py +4 -0
  113. scitex/{gen → os}/_check_host.py +4 -5
  114. scitex/plt/__init__.py +245 -550
  115. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +5 -10
  116. scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  117. scitex/plt/gallery/README.md +1 -1
  118. scitex/plt/utils/_hitmap/__init__.py +82 -0
  119. scitex/plt/utils/_hitmap/_artist_extraction.py +343 -0
  120. scitex/plt/utils/_hitmap/_color_application.py +346 -0
  121. scitex/plt/utils/_hitmap/_color_conversion.py +121 -0
  122. scitex/plt/utils/_hitmap/_constants.py +40 -0
  123. scitex/plt/utils/_hitmap/_hitmap_core.py +334 -0
  124. scitex/plt/utils/_hitmap/_path_extraction.py +357 -0
  125. scitex/plt/utils/_hitmap/_query.py +113 -0
  126. scitex/plt/utils/_hitmap.py +46 -1616
  127. scitex/plt/utils/_metadata/__init__.py +80 -0
  128. scitex/plt/utils/_metadata/_artists/__init__.py +25 -0
  129. scitex/plt/utils/_metadata/_artists/_base.py +195 -0
  130. scitex/plt/utils/_metadata/_artists/_collections.py +356 -0
  131. scitex/plt/utils/_metadata/_artists/_extract.py +57 -0
  132. scitex/plt/utils/_metadata/_artists/_images.py +80 -0
  133. scitex/plt/utils/_metadata/_artists/_lines.py +261 -0
  134. scitex/plt/utils/_metadata/_artists/_patches.py +247 -0
  135. scitex/plt/utils/_metadata/_artists/_text.py +106 -0
  136. scitex/plt/utils/_metadata/_csv.py +416 -0
  137. scitex/plt/utils/_metadata/_detect.py +225 -0
  138. scitex/plt/utils/_metadata/_legend.py +127 -0
  139. scitex/plt/utils/_metadata/_rounding.py +117 -0
  140. scitex/plt/utils/_metadata/_verification.py +202 -0
  141. scitex/schema/README.md +1 -1
  142. scitex/scholar/__init__.py +8 -0
  143. scitex/scholar/_mcp/crossref_handlers.py +265 -0
  144. scitex/scholar/core/Scholar.py +63 -1700
  145. scitex/scholar/core/_mixins/__init__.py +36 -0
  146. scitex/scholar/core/_mixins/_enrichers.py +270 -0
  147. scitex/scholar/core/_mixins/_library_handlers.py +100 -0
  148. scitex/scholar/core/_mixins/_loaders.py +103 -0
  149. scitex/scholar/core/_mixins/_pdf_download.py +375 -0
  150. scitex/scholar/core/_mixins/_pipeline.py +312 -0
  151. scitex/scholar/core/_mixins/_project_handlers.py +125 -0
  152. scitex/scholar/core/_mixins/_savers.py +69 -0
  153. scitex/scholar/core/_mixins/_search.py +103 -0
  154. scitex/scholar/core/_mixins/_services.py +88 -0
  155. scitex/scholar/core/_mixins/_url_finding.py +105 -0
  156. scitex/scholar/crossref_scitex.py +367 -0
  157. scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  158. scitex/scholar/examples/00_run_all.sh +120 -0
  159. scitex/scholar/jobs/_executors.py +27 -3
  160. scitex/scholar/pdf_download/ScholarPDFDownloader.py +38 -416
  161. scitex/scholar/pdf_download/_cli.py +154 -0
  162. scitex/scholar/pdf_download/strategies/__init__.py +11 -8
  163. scitex/scholar/pdf_download/strategies/manual_download_fallback.py +80 -3
  164. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +73 -121
  165. scitex/scholar/pipelines/ScholarPipelineParallel.py +80 -138
  166. scitex/scholar/pipelines/ScholarPipelineSingle.py +43 -63
  167. scitex/scholar/pipelines/_single_steps.py +71 -36
  168. scitex/scholar/storage/_LibraryManager.py +97 -1695
  169. scitex/scholar/storage/_mixins/__init__.py +30 -0
  170. scitex/scholar/storage/_mixins/_bibtex_handlers.py +128 -0
  171. scitex/scholar/storage/_mixins/_library_operations.py +218 -0
  172. scitex/scholar/storage/_mixins/_metadata_conversion.py +226 -0
  173. scitex/scholar/storage/_mixins/_paper_saving.py +456 -0
  174. scitex/scholar/storage/_mixins/_resolution.py +376 -0
  175. scitex/scholar/storage/_mixins/_storage_helpers.py +121 -0
  176. scitex/scholar/storage/_mixins/_symlink_handlers.py +226 -0
  177. scitex/scholar/url_finder/.tmp/open_url/KNOWN_RESOLVERS.py +462 -0
  178. scitex/scholar/url_finder/.tmp/open_url/README.md +223 -0
  179. scitex/scholar/url_finder/.tmp/open_url/_DOIToURLResolver.py +694 -0
  180. scitex/scholar/url_finder/.tmp/open_url/_OpenURLResolver.py +1160 -0
  181. scitex/scholar/url_finder/.tmp/open_url/_ResolverLinkFinder.py +344 -0
  182. scitex/scholar/url_finder/.tmp/open_url/__init__.py +24 -0
  183. scitex/security/README.md +3 -3
  184. scitex/session/README.md +1 -1
  185. scitex/session/__init__.py +26 -7
  186. scitex/session/_decorator.py +1 -1
  187. scitex/sh/README.md +1 -1
  188. scitex/sh/__init__.py +7 -4
  189. scitex/social/__init__.py +155 -0
  190. scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  191. scitex/stats/_mcp/_handlers/__init__.py +31 -0
  192. scitex/stats/_mcp/_handlers/_corrections.py +113 -0
  193. scitex/stats/_mcp/_handlers/_descriptive.py +78 -0
  194. scitex/stats/_mcp/_handlers/_effect_size.py +106 -0
  195. scitex/stats/_mcp/_handlers/_format.py +94 -0
  196. scitex/stats/_mcp/_handlers/_normality.py +110 -0
  197. scitex/stats/_mcp/_handlers/_posthoc.py +224 -0
  198. scitex/stats/_mcp/_handlers/_power.py +247 -0
  199. scitex/stats/_mcp/_handlers/_recommend.py +102 -0
  200. scitex/stats/_mcp/_handlers/_run_test.py +279 -0
  201. scitex/stats/_mcp/_handlers/_stars.py +48 -0
  202. scitex/stats/_mcp/handlers.py +19 -1171
  203. scitex/stats/auto/_stat_style.py +175 -0
  204. scitex/stats/auto/_style_definitions.py +411 -0
  205. scitex/stats/auto/_styles.py +22 -620
  206. scitex/stats/descriptive/__init__.py +11 -8
  207. scitex/stats/descriptive/_ci.py +39 -0
  208. scitex/stats/power/_power.py +15 -4
  209. scitex/str/__init__.py +2 -1
  210. scitex/str/_title_case.py +63 -0
  211. scitex/template/README.md +1 -1
  212. scitex/template/__init__.py +25 -10
  213. scitex/template/_code_templates.py +147 -0
  214. scitex/template/_mcp/handlers.py +81 -0
  215. scitex/template/_mcp/tool_schemas.py +55 -0
  216. scitex/template/_templates/__init__.py +51 -0
  217. scitex/template/_templates/audio.py +233 -0
  218. scitex/template/_templates/canvas.py +312 -0
  219. scitex/template/_templates/capture.py +268 -0
  220. scitex/template/_templates/config.py +43 -0
  221. scitex/template/_templates/diagram.py +294 -0
  222. scitex/template/_templates/io.py +107 -0
  223. scitex/template/_templates/module.py +53 -0
  224. scitex/template/_templates/plt.py +202 -0
  225. scitex/template/_templates/scholar.py +267 -0
  226. scitex/template/_templates/session.py +130 -0
  227. scitex/template/_templates/session_minimal.py +43 -0
  228. scitex/template/_templates/session_plot.py +67 -0
  229. scitex/template/_templates/session_stats.py +77 -0
  230. scitex/template/_templates/stats.py +323 -0
  231. scitex/template/_templates/writer.py +296 -0
  232. scitex/template/clone_writer_directory.py +5 -5
  233. scitex/ui/_backends/_email.py +10 -2
  234. scitex/ui/_backends/_webhook.py +5 -1
  235. scitex/web/_search_pubmed.py +10 -6
  236. scitex/writer/README.md +1 -1
  237. scitex/writer/_mcp/handlers.py +11 -744
  238. scitex/writer/_mcp/tool_schemas.py +5 -335
  239. scitex-2.15.2.dist-info/METADATA +648 -0
  240. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/RECORD +246 -150
  241. scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
  242. scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
  243. scitex/dev/plt/data/mpl/PLOTTING_FUNCTIONS.yaml +0 -90
  244. scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES.yaml +0 -1571
  245. scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES_DETAILED.yaml +0 -6262
  246. scitex/dev/plt/data/mpl/SIGNATURES_FLATTENED.yaml +0 -1274
  247. scitex/dev/plt/data/mpl/dir_ax.txt +0 -459
  248. scitex/diagram/_compile.py +0 -312
  249. scitex/diagram/_diagram.py +0 -355
  250. scitex/diagram/_mcp/__init__.py +0 -4
  251. scitex/diagram/_mcp/handlers.py +0 -400
  252. scitex/diagram/_mcp/tool_schemas.py +0 -157
  253. scitex/diagram/_presets.py +0 -173
  254. scitex/diagram/_schema.py +0 -182
  255. scitex/diagram/_split.py +0 -278
  256. scitex/gen/_ci.py +0 -12
  257. scitex/gen/_title_case.py +0 -89
  258. scitex/plt/_mcp/__init__.py +0 -4
  259. scitex/plt/_mcp/_handlers_annotation.py +0 -102
  260. scitex/plt/_mcp/_handlers_figure.py +0 -195
  261. scitex/plt/_mcp/_handlers_plot.py +0 -252
  262. scitex/plt/_mcp/_handlers_style.py +0 -219
  263. scitex/plt/_mcp/handlers.py +0 -74
  264. scitex/plt/_mcp/tool_schemas.py +0 -497
  265. scitex/plt/mcp_server.py +0 -231
  266. scitex/scholar/data/.gitkeep +0 -0
  267. scitex/scholar/data/README.md +0 -44
  268. scitex/scholar/data/bib_files/bibliography.bib +0 -1952
  269. scitex/scholar/data/bib_files/neurovista.bib +0 -277
  270. scitex/scholar/data/bib_files/neurovista_enriched.bib +0 -441
  271. scitex/scholar/data/bib_files/neurovista_enriched_enriched.bib +0 -441
  272. scitex/scholar/data/bib_files/neurovista_processed.bib +0 -338
  273. scitex/scholar/data/bib_files/openaccess.bib +0 -89
  274. scitex/scholar/data/bib_files/pac-seizure_prediction_enriched.bib +0 -2178
  275. scitex/scholar/data/bib_files/pac.bib +0 -698
  276. scitex/scholar/data/bib_files/pac_enriched.bib +0 -1061
  277. scitex/scholar/data/bib_files/pac_processed.bib +0 -0
  278. scitex/scholar/data/bib_files/pac_titles.txt +0 -75
  279. scitex/scholar/data/bib_files/paywalled.bib +0 -98
  280. scitex/scholar/data/bib_files/related-papers-by-coauthors.bib +0 -58
  281. scitex/scholar/data/bib_files/related-papers-by-coauthors_enriched.bib +0 -87
  282. scitex/scholar/data/bib_files/seizure_prediction.bib +0 -694
  283. scitex/scholar/data/bib_files/seizure_prediction_processed.bib +0 -0
  284. scitex/scholar/data/bib_files/test_complete_enriched.bib +0 -437
  285. scitex/scholar/data/bib_files/test_final_enriched.bib +0 -437
  286. scitex/scholar/data/bib_files/test_seizure.bib +0 -46
  287. scitex/scholar/data/impact_factor/JCR_IF_2022.xlsx +0 -0
  288. scitex/scholar/data/impact_factor/JCR_IF_2024.db +0 -0
  289. scitex/scholar/data/impact_factor/JCR_IF_2024.xlsx +0 -0
  290. scitex/scholar/data/impact_factor/JCR_IF_2024_v01.db +0 -0
  291. scitex/scholar/data/impact_factor.db +0 -0
  292. scitex/scholar/examples/SUGGESTIONS.md +0 -865
  293. scitex/scholar/examples/dev.py +0 -38
  294. scitex-2.14.0.dist-info/METADATA +0 -1238
  295. /scitex/{gen → context}/_detect_environment.py +0 -0
  296. /scitex/{gen → context}/_get_notebook_path.py +0 -0
  297. /scitex/{gen/_shell.py → sh/_shell_legacy.py} +0 -0
  298. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/WHEEL +0 -0
  299. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/entry_points.txt +0 -0
  300. {scitex-2.14.0.dist-info → scitex-2.15.2.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
+ }