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
scitex/cli/template.py CHANGED
@@ -11,38 +11,55 @@ from pathlib import Path
11
11
  import click
12
12
 
13
13
 
14
- @click.group(context_settings={"help_option_names": ["-h", "--help"]})
15
- def template():
14
+ @click.group(
15
+ context_settings={"help_option_names": ["-h", "--help"]},
16
+ invoke_without_command=True,
17
+ )
18
+ @click.option("--help-recursive", is_flag=True, help="Show help for all subcommands")
19
+ @click.pass_context
20
+ def template(ctx, help_recursive):
16
21
  """
17
22
  Project template scaffolding
18
23
 
19
24
  \b
20
- Available templates:
25
+ Project Templates (clone):
21
26
  research - Full scientific workflow structure
22
27
  pip-project - Pip-installable Python package
23
28
  singularity - Container-based project
24
29
  paper - Academic paper writing template
25
30
 
31
+ \b
32
+ Code Templates (get):
33
+ session - @stx.session script with CONFIG docs (priority)
34
+ io - stx.io save/load patterns (priority)
35
+ config - YAML configuration file
36
+ session-minimal/plot/stats - Variants
37
+ module - Standard Python module
38
+ all - All templates combined
39
+
26
40
  \b
27
41
  Examples:
28
- scitex template list # Show available templates
29
- scitex template clone research ./my-project # Clone research template
30
- scitex template clone pip-project ./my-pkg # Clone package template
42
+ scitex template get session # Session script template
43
+ scitex template get io # I/O operations template
44
+ scitex template get all # All templates
45
+ scitex template get session -o script.py # Save to file
31
46
  """
32
- pass
47
+ if help_recursive:
48
+ _print_help_recursive(ctx)
49
+ ctx.exit(0)
50
+ elif ctx.invoked_subcommand is None:
51
+ click.echo(ctx.get_help())
33
52
 
34
53
 
35
- @template.command("help-recursive")
36
- @click.pass_context
37
- def help_recursive(ctx):
38
- """Show help for all commands recursively."""
54
+ def _print_help_recursive(ctx):
55
+ """Print help for all commands recursively."""
39
56
  fake_parent = click.Context(click.Group(), info_name="scitex")
40
57
  parent_ctx = click.Context(template, info_name="template", parent=fake_parent)
41
58
  click.secho("━━━ scitex template ━━━", fg="cyan", bold=True)
42
59
  click.echo(template.get_help(parent_ctx))
43
60
  for name in sorted(template.list_commands(ctx) or []):
44
61
  cmd = template.get_command(ctx, name)
45
- if cmd is None or name == "help-recursive":
62
+ if cmd is None:
46
63
  continue
47
64
  click.echo()
48
65
  click.secho(f"━━━ scitex template {name} ━━━", fg="cyan", bold=True)
@@ -198,6 +215,106 @@ def clone(template_type, destination, git_strategy, branch, tag):
198
215
  sys.exit(1)
199
216
 
200
217
 
218
+ @template.command()
219
+ @click.argument(
220
+ "template_id",
221
+ type=click.Choice(
222
+ [
223
+ # Core templates (priority 1-3)
224
+ "session",
225
+ "io",
226
+ "config",
227
+ # Session variants
228
+ "session-minimal",
229
+ "session-plot",
230
+ "session-stats",
231
+ # Module template
232
+ "module",
233
+ # Module usage templates
234
+ "plt",
235
+ "stats",
236
+ "scholar",
237
+ "audio",
238
+ "capture",
239
+ "diagram",
240
+ "canvas",
241
+ "writer",
242
+ # All templates
243
+ "all",
244
+ ]
245
+ ),
246
+ )
247
+ @click.option(
248
+ "--output", "-o", type=click.Path(), help="Save to file instead of printing"
249
+ )
250
+ @click.option("--docstring", "-d", help="Custom docstring for the template")
251
+ def get(template_id, output, docstring):
252
+ """
253
+ Get a code template (print or save to file)
254
+
255
+ \b
256
+ Core Templates (priority 1-3):
257
+ session - Full @stx.session script with CONFIG docs
258
+ io - stx.io.save/load patterns (30+ formats)
259
+ config - YAML configuration file
260
+
261
+ \b
262
+ Session Variants:
263
+ session-minimal - Minimal session script
264
+ session-plot - Plotting-focused session script
265
+ session-stats - Statistical analysis script
266
+ module - Standard Python module
267
+
268
+ \b
269
+ Module Usage Templates:
270
+ plt - stx.plt plotting usage
271
+ stats - stx.stats statistical analysis
272
+ scholar - stx.scholar literature management
273
+ audio - stx.audio text-to-speech
274
+ capture - stx.capture screenshots
275
+ diagram - stx.diagram Mermaid/Graphviz
276
+ canvas - stx.canvas figure composition
277
+ writer - stx.writer LaTeX compilation
278
+
279
+ \b
280
+ All:
281
+ all - All templates combined
282
+
283
+ \b
284
+ Examples:
285
+ scitex template get session # Print to stdout
286
+ scitex template get io # I/O operations template
287
+ scitex template get all # All templates
288
+ scitex template get session -o script.py # Save to file
289
+ """
290
+ try:
291
+ if template_id == "all":
292
+ from scitex.template import get_all_templates
293
+
294
+ content = get_all_templates()
295
+ else:
296
+ from scitex.template import get_code_template
297
+
298
+ filepath = output if output else None
299
+ content = get_code_template(
300
+ template_id, filepath=filepath, docstring=docstring
301
+ )
302
+
303
+ if output:
304
+ # Save to file
305
+ out_path = Path(output)
306
+ out_path.parent.mkdir(parents=True, exist_ok=True)
307
+ out_path.write_text(content)
308
+ click.secho(f"Template saved: {out_path}", fg="green")
309
+ else:
310
+ # Print to stdout
311
+ click.echo(content)
312
+
313
+ except Exception as e:
314
+ click.secho(f"Error: {e}", fg="red", err=True)
315
+ sys.exit(1)
316
+
317
+
201
318
  @template.command()
202
319
  @click.argument("template_id")
203
320
  def info(template_id):
scitex/cli/tex.py CHANGED
@@ -11,8 +11,13 @@ from pathlib import Path
11
11
  import click
12
12
 
13
13
 
14
- @click.group(context_settings={"help_option_names": ["-h", "--help"]})
15
- def tex():
14
+ @click.group(
15
+ context_settings={"help_option_names": ["-h", "--help"]},
16
+ invoke_without_command=True,
17
+ )
18
+ @click.option("--help-recursive", is_flag=True, help="Show help for all subcommands")
19
+ @click.pass_context
20
+ def tex(ctx, help_recursive):
16
21
  """
17
22
  LaTeX compilation and utilities
18
23
 
@@ -28,20 +33,22 @@ def tex():
28
33
  scitex tex preview paper.tex
29
34
  scitex tex to-vec figure.tex --format svg
30
35
  """
31
- pass
36
+ if help_recursive:
37
+ _print_help_recursive(ctx)
38
+ ctx.exit(0)
39
+ elif ctx.invoked_subcommand is None:
40
+ click.echo(ctx.get_help())
32
41
 
33
42
 
34
- @tex.command("help-recursive")
35
- @click.pass_context
36
- def help_recursive(ctx):
37
- """Show help for all commands recursively."""
43
+ def _print_help_recursive(ctx):
44
+ """Print help for all commands recursively."""
38
45
  fake_parent = click.Context(click.Group(), info_name="scitex")
39
46
  parent_ctx = click.Context(tex, info_name="tex", parent=fake_parent)
40
47
  click.secho("━━━ scitex tex ━━━", fg="cyan", bold=True)
41
48
  click.echo(tex.get_help(parent_ctx))
42
49
  for name in sorted(tex.list_commands(ctx) or []):
43
50
  cmd = tex.get_command(ctx, name)
44
- if cmd is None or name == "help-recursive":
51
+ if cmd is None:
45
52
  continue
46
53
  click.echo()
47
54
  click.secho(f"━━━ scitex tex {name} ━━━", fg="cyan", bold=True)
scitex/cli/writer.py CHANGED
@@ -11,8 +11,13 @@ from pathlib import Path
11
11
  import click
12
12
 
13
13
 
14
- @click.group(context_settings={"help_option_names": ["-h", "--help"]})
15
- def writer():
14
+ @click.group(
15
+ context_settings={"help_option_names": ["-h", "--help"]},
16
+ invoke_without_command=True,
17
+ )
18
+ @click.option("--help-recursive", is_flag=True, help="Show help for all subcommands")
19
+ @click.pass_context
20
+ def writer(ctx, help_recursive):
16
21
  """
17
22
  Manuscript writing and LaTeX compilation
18
23
 
@@ -23,13 +28,15 @@ def writer():
23
28
  - Watch mode for auto-recompilation
24
29
  - Project structure management
25
30
  """
26
- pass
31
+ if help_recursive:
32
+ _print_help_recursive(ctx)
33
+ ctx.exit(0)
34
+ elif ctx.invoked_subcommand is None:
35
+ click.echo(ctx.get_help())
27
36
 
28
37
 
29
- @writer.command("help-recursive")
30
- @click.pass_context
31
- def help_recursive(ctx):
32
- """Show help for all commands recursively."""
38
+ def _print_help_recursive(ctx):
39
+ """Print help for all commands recursively."""
33
40
  fake_parent = click.Context(click.Group(), info_name="scitex")
34
41
  parent_ctx = click.Context(writer, info_name="writer", parent=fake_parent)
35
42
 
@@ -38,7 +45,7 @@ def help_recursive(ctx):
38
45
 
39
46
  for name in sorted(writer.list_commands(ctx) or []):
40
47
  cmd = writer.get_command(ctx, name)
41
- if cmd is None or name == "help-recursive":
48
+ if cmd is None:
42
49
  continue
43
50
  click.echo()
44
51
  click.secho(f"━━━ scitex writer {name} ━━━", fg="cyan", bold=True)
@@ -280,6 +287,123 @@ def info(dir):
280
287
  sys.exit(1)
281
288
 
282
289
 
290
+ @writer.group()
291
+ def mcp():
292
+ """
293
+ MCP (Model Context Protocol) tools for writer module.
294
+
295
+ \b
296
+ Examples:
297
+ scitex writer mcp list-tools # List available MCP tools
298
+ scitex writer mcp usage # Show tool usage and parameters
299
+ """
300
+ pass
301
+
302
+
303
+ @mcp.command("list-tools")
304
+ @click.option("--json", "as_json", is_flag=True, help="Output as JSON")
305
+ def list_tools(as_json: bool):
306
+ """
307
+ List available MCP tools for writer module.
308
+
309
+ \b
310
+ Examples:
311
+ scitex writer mcp list-tools
312
+ scitex writer mcp list-tools --json
313
+ """
314
+ from scitex.writer._mcp.tool_schemas import get_tool_schemas
315
+
316
+ tools = get_tool_schemas()
317
+
318
+ if as_json:
319
+ import json
320
+
321
+ output = {
322
+ "module": "writer",
323
+ "count": len(tools),
324
+ "tools": [
325
+ {
326
+ "name": t.name,
327
+ "description": t.description,
328
+ "parameters": list(t.inputSchema.get("properties", {}).keys()),
329
+ "required": t.inputSchema.get("required", []),
330
+ }
331
+ for t in tools
332
+ ],
333
+ }
334
+ click.echo(json.dumps(output, indent=2))
335
+ else:
336
+ click.secho(
337
+ f"SciTeX Writer MCP Tools ({len(tools)} total)", fg="cyan", bold=True
338
+ )
339
+ click.echo()
340
+
341
+ for tool in tools:
342
+ click.secho(f" {tool.name}", fg="green", bold=True)
343
+ # First line of description
344
+ desc = tool.description.split("\n")[0] if tool.description else ""
345
+ click.echo(f" {desc}")
346
+
347
+ # Parameters
348
+ props = tool.inputSchema.get("properties", {})
349
+ required = tool.inputSchema.get("required", [])
350
+ if props:
351
+ params = []
352
+ for pname, pinfo in props.items():
353
+ req_marker = "*" if pname in required else ""
354
+ params.append(f"{pname}{req_marker}")
355
+ click.echo(f" Parameters: {', '.join(params)}")
356
+ click.echo()
357
+
358
+
359
+ @mcp.command("usage")
360
+ @click.argument("tool_name", required=False)
361
+ def usage(tool_name: str):
362
+ """
363
+ Show detailed usage for writer MCP tools.
364
+
365
+ \b
366
+ Examples:
367
+ scitex writer mcp usage # Show all tools
368
+ scitex writer mcp usage compile_manuscript # Show specific tool
369
+ """
370
+ from scitex.writer._mcp.tool_schemas import get_tool_schemas
371
+
372
+ tools = get_tool_schemas()
373
+
374
+ if tool_name:
375
+ # Find specific tool
376
+ tool = next((t for t in tools if t.name == tool_name), None)
377
+ if not tool:
378
+ click.secho(f"Tool '{tool_name}' not found", fg="red", err=True)
379
+ click.echo(f"Available tools: {', '.join(t.name for t in tools)}")
380
+ raise SystemExit(1)
381
+ tools = [tool]
382
+
383
+ for tool in tools:
384
+ click.secho(f"━━━ {tool.name} ━━━", fg="cyan", bold=True)
385
+ click.echo()
386
+ click.echo(f"Description: {tool.description}")
387
+ click.echo()
388
+
389
+ props = tool.inputSchema.get("properties", {})
390
+ required = tool.inputSchema.get("required", [])
391
+
392
+ if props:
393
+ click.secho("Parameters:", bold=True)
394
+ for pname, pinfo in props.items():
395
+ req = " (required)" if pname in required else ""
396
+ ptype = pinfo.get("type", "any")
397
+ pdesc = pinfo.get("description", "")
398
+ default = pinfo.get("default")
399
+ default_str = f" [default: {default}]" if default is not None else ""
400
+
401
+ click.echo(f" {pname}: {ptype}{req}{default_str}")
402
+ if pdesc:
403
+ click.echo(f" {pdesc}")
404
+ click.echo()
405
+
406
+
283
407
  @writer.command()
284
408
  @click.option(
285
409
  "--dir",
scitex/cloud/__init__.py CHANGED
@@ -1,14 +1,44 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
2
  # SciTeX Cloud Integration Module
4
3
  # Provides cloud-specific functionality for SciTeX running in SciTeX Cloud
4
+ #
5
+ # This module wraps the scitex-cloud package (if installed) and provides
6
+ # additional cloud environment utilities.
5
7
 
8
+ import base64
6
9
  import os
7
10
  import sys
8
- import base64
9
11
  from pathlib import Path
10
12
  from typing import Optional
11
13
 
14
+ # ============================================================================
15
+ # Optional scitex-cloud package integration
16
+ # Pattern: scitex-cloud → scitex.cloud (like figrecipe → scitex.plt)
17
+ # ============================================================================
18
+ try:
19
+ from scitex_cloud import (
20
+ DockerManager,
21
+ Environment,
22
+ get_environment,
23
+ )
24
+ from scitex_cloud import __version__ as cloud_version
25
+ from scitex_cloud import (
26
+ config as cloud_config,
27
+ )
28
+ from scitex_cloud import (
29
+ utils as cloud_utils,
30
+ )
31
+
32
+ HAS_CLOUD_CLI = True
33
+ except ImportError:
34
+ HAS_CLOUD_CLI = False
35
+ cloud_version = None
36
+ DockerManager = None
37
+ Environment = None
38
+ get_environment = None
39
+ cloud_config = None
40
+ cloud_utils = None
41
+
12
42
 
13
43
  def is_cloud_environment() -> bool:
14
44
  """Check if running in SciTeX Cloud environment."""
@@ -116,11 +146,20 @@ def emit_file_link(file_path: str, line_number: Optional[int] = None) -> None:
116
146
 
117
147
 
118
148
  __all__ = [
149
+ # Local cloud environment utilities
119
150
  "is_cloud_environment",
120
151
  "get_cloud_backend",
121
152
  "get_project_root",
122
153
  "emit_inline_image",
123
154
  "emit_file_link",
155
+ # scitex-cloud package integration (if installed)
156
+ "HAS_CLOUD_CLI",
157
+ "cloud_version",
158
+ "DockerManager",
159
+ "Environment",
160
+ "get_environment",
161
+ "cloud_config",
162
+ "cloud_utils",
124
163
  ]
125
164
 
126
165
  # Auto-import matplotlib hook to enable inline plotting
scitex/config/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- ---
2
2
  !-- Timestamp: 2025-12-09
3
3
  !-- Author: ywatanabe
4
- !-- File: /home/ywatanabe/proj/scitex-code/src/scitex/config/README.md
4
+ !-- File: /home/ywatanabe/proj/scitex-python/src/scitex/config/README.md
5
5
  !-- --- -->
6
6
 
7
7
  # SciTeX Configuration Module
scitex/config/__init__.py CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
2
  # Timestamp: "2025-12-09 (ywatanabe)"
4
3
  # File: ./src/scitex/config/__init__.py
5
4
 
@@ -34,8 +33,16 @@ Usage:
34
33
  cache_dir = paths.resolve("cache", user_provided_path)
35
34
  """
36
35
 
37
- from ._PriorityConfig import PriorityConfig, get_scitex_dir, load_dotenv
36
+ from ._env_registry import (
37
+ ENV_REGISTRY,
38
+ EnvVar,
39
+ generate_template,
40
+ get_all_modules,
41
+ get_env_by_module,
42
+ get_env_docs,
43
+ )
38
44
  from ._paths import ScitexPaths, get_paths
45
+ from ._PriorityConfig import PriorityConfig, get_scitex_dir, load_dotenv
39
46
  from ._ScitexConfig import ScitexConfig, get_config, load_yaml
40
47
 
41
48
  __all__ = [
@@ -50,6 +57,13 @@ __all__ = [
50
57
  "PriorityConfig",
51
58
  "get_scitex_dir",
52
59
  "load_dotenv",
60
+ # Environment variable registry
61
+ "ENV_REGISTRY",
62
+ "EnvVar",
63
+ "generate_template",
64
+ "get_all_modules",
65
+ "get_env_by_module",
66
+ "get_env_docs",
53
67
  ]
54
68
 
55
69