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.
Files changed (264) 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 +27 -0
  16. scitex/_mcp_tools/template.py +24 -0
  17. scitex/_mcp_tools/writer.py +17 -210
  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 +160 -41
  68. scitex/cli/capture.py +133 -20
  69. scitex/cli/introspect.py +488 -0
  70. scitex/cli/main.py +200 -109
  71. scitex/cli/mcp.py +60 -34
  72. scitex/cli/plt.py +414 -0
  73. scitex/cli/repro.py +15 -8
  74. scitex/cli/resource.py +15 -8
  75. scitex/cli/scholar/__init__.py +154 -8
  76. scitex/cli/scholar/_crossref_scitex.py +296 -0
  77. scitex/cli/scholar/_fetch.py +25 -3
  78. scitex/cli/social.py +355 -0
  79. scitex/cli/stats.py +136 -11
  80. scitex/cli/template.py +129 -12
  81. scitex/cli/tex.py +15 -8
  82. scitex/cli/writer.py +49 -299
  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} +48 -56
  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/security/README.md +3 -3
  178. scitex/session/README.md +1 -1
  179. scitex/session/__init__.py +26 -7
  180. scitex/session/_decorator.py +1 -1
  181. scitex/sh/README.md +1 -1
  182. scitex/sh/__init__.py +7 -4
  183. scitex/social/__init__.py +155 -0
  184. scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  185. scitex/stats/_mcp/_handlers/__init__.py +31 -0
  186. scitex/stats/_mcp/_handlers/_corrections.py +113 -0
  187. scitex/stats/_mcp/_handlers/_descriptive.py +78 -0
  188. scitex/stats/_mcp/_handlers/_effect_size.py +106 -0
  189. scitex/stats/_mcp/_handlers/_format.py +94 -0
  190. scitex/stats/_mcp/_handlers/_normality.py +110 -0
  191. scitex/stats/_mcp/_handlers/_posthoc.py +224 -0
  192. scitex/stats/_mcp/_handlers/_power.py +247 -0
  193. scitex/stats/_mcp/_handlers/_recommend.py +102 -0
  194. scitex/stats/_mcp/_handlers/_run_test.py +279 -0
  195. scitex/stats/_mcp/_handlers/_stars.py +48 -0
  196. scitex/stats/_mcp/handlers.py +19 -1171
  197. scitex/stats/auto/_stat_style.py +175 -0
  198. scitex/stats/auto/_style_definitions.py +411 -0
  199. scitex/stats/auto/_styles.py +22 -620
  200. scitex/stats/descriptive/__init__.py +11 -8
  201. scitex/stats/descriptive/_ci.py +39 -0
  202. scitex/stats/power/_power.py +15 -4
  203. scitex/str/__init__.py +2 -1
  204. scitex/str/_title_case.py +63 -0
  205. scitex/template/README.md +1 -1
  206. scitex/template/__init__.py +25 -10
  207. scitex/template/_code_templates.py +147 -0
  208. scitex/template/_mcp/handlers.py +81 -0
  209. scitex/template/_mcp/tool_schemas.py +55 -0
  210. scitex/template/_templates/__init__.py +51 -0
  211. scitex/template/_templates/audio.py +233 -0
  212. scitex/template/_templates/canvas.py +312 -0
  213. scitex/template/_templates/capture.py +268 -0
  214. scitex/template/_templates/config.py +43 -0
  215. scitex/template/_templates/diagram.py +294 -0
  216. scitex/template/_templates/io.py +107 -0
  217. scitex/template/_templates/module.py +53 -0
  218. scitex/template/_templates/plt.py +202 -0
  219. scitex/template/_templates/scholar.py +267 -0
  220. scitex/template/_templates/session.py +130 -0
  221. scitex/template/_templates/session_minimal.py +43 -0
  222. scitex/template/_templates/session_plot.py +67 -0
  223. scitex/template/_templates/session_stats.py +77 -0
  224. scitex/template/_templates/stats.py +323 -0
  225. scitex/template/_templates/writer.py +296 -0
  226. scitex/template/clone_writer_directory.py +5 -5
  227. scitex/ui/_backends/_email.py +10 -2
  228. scitex/ui/_backends/_webhook.py +5 -1
  229. scitex/web/_search_pubmed.py +10 -6
  230. scitex/writer/README.md +1 -1
  231. scitex/writer/__init__.py +43 -34
  232. scitex/writer/_mcp/handlers.py +11 -744
  233. scitex/writer/_mcp/tool_schemas.py +5 -335
  234. scitex-2.15.3.dist-info/METADATA +667 -0
  235. {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/RECORD +241 -120
  236. scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
  237. scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
  238. scitex/diagram/_compile.py +0 -312
  239. scitex/diagram/_diagram.py +0 -355
  240. scitex/diagram/_mcp/__init__.py +0 -4
  241. scitex/diagram/_mcp/handlers.py +0 -400
  242. scitex/diagram/_mcp/tool_schemas.py +0 -157
  243. scitex/diagram/_presets.py +0 -173
  244. scitex/diagram/_schema.py +0 -182
  245. scitex/diagram/_split.py +0 -278
  246. scitex/gen/_ci.py +0 -12
  247. scitex/gen/_title_case.py +0 -89
  248. scitex/plt/_mcp/__init__.py +0 -4
  249. scitex/plt/_mcp/_handlers_annotation.py +0 -102
  250. scitex/plt/_mcp/_handlers_figure.py +0 -195
  251. scitex/plt/_mcp/_handlers_plot.py +0 -252
  252. scitex/plt/_mcp/_handlers_style.py +0 -219
  253. scitex/plt/_mcp/handlers.py +0 -74
  254. scitex/plt/_mcp/tool_schemas.py +0 -497
  255. scitex/plt/mcp_server.py +0 -231
  256. scitex/scholar/examples/SUGGESTIONS.md +0 -865
  257. scitex/scholar/examples/dev.py +0 -38
  258. scitex-2.14.0.dist-info/METADATA +0 -1238
  259. /scitex/{gen → context}/_detect_environment.py +0 -0
  260. /scitex/{gen → context}/_get_notebook_path.py +0 -0
  261. /scitex/{gen/_shell.py → sh/_shell_legacy.py} +0 -0
  262. {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/WHEEL +0 -0
  263. {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/entry_points.txt +0 -0
  264. {scitex-2.14.0.dist-info → scitex-2.15.3.dist-info}/licenses/LICENSE +0 -0
scitex/cli/stats.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 stats():
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 stats(ctx, help_recursive):
16
21
  """
17
22
  Statistical analysis and testing utilities
18
23
 
@@ -29,20 +34,22 @@ def stats():
29
34
  scitex stats describe data.csv
30
35
  scitex stats save results.json --output analysis.stats
31
36
  """
32
- pass
37
+ if help_recursive:
38
+ _print_help_recursive(ctx)
39
+ ctx.exit(0)
40
+ elif ctx.invoked_subcommand is None:
41
+ click.echo(ctx.get_help())
33
42
 
34
43
 
35
- @stats.command("help-recursive")
36
- @click.pass_context
37
- def help_recursive(ctx):
38
- """Show help for all commands recursively."""
44
+ def _print_help_recursive(ctx):
45
+ """Print help for all commands recursively."""
39
46
  fake_parent = click.Context(click.Group(), info_name="scitex")
40
47
  parent_ctx = click.Context(stats, info_name="stats", parent=fake_parent)
41
48
  click.secho("━━━ scitex stats ━━━", fg="cyan", bold=True)
42
49
  click.echo(stats.get_help(parent_ctx))
43
50
  for name in sorted(stats.list_commands(ctx) or []):
44
51
  cmd = stats.get_command(ctx, name)
45
- if cmd is None or name == "help-recursive":
52
+ if cmd is None:
46
53
  continue
47
54
  click.echo()
48
55
  click.secho(f"━━━ scitex stats {name} ━━━", fg="cyan", bold=True)
@@ -132,9 +139,9 @@ def recommend(
132
139
  output = {
133
140
  "context": {
134
141
  "n_groups": n_groups,
135
- "sample_sizes": list(sample_sizes)
136
- if sample_sizes
137
- else [30] * n_groups,
142
+ "sample_sizes": (
143
+ list(sample_sizes) if sample_sizes else [30] * n_groups
144
+ ),
138
145
  "outcome_type": outcome_type,
139
146
  "design": design,
140
147
  "paired": paired,
@@ -339,5 +346,123 @@ def tests():
339
346
  sys.exit(1)
340
347
 
341
348
 
349
+ @stats.group(invoke_without_command=True)
350
+ @click.pass_context
351
+ def mcp(ctx):
352
+ """
353
+ MCP (Model Context Protocol) server operations
354
+
355
+ \b
356
+ Commands:
357
+ start - Start the MCP server
358
+ doctor - Check MCP server health
359
+ list-tools - List available MCP tools
360
+
361
+ \b
362
+ Examples:
363
+ scitex stats mcp start
364
+ scitex stats mcp list-tools
365
+ """
366
+ if ctx.invoked_subcommand is None:
367
+ click.echo(ctx.get_help())
368
+
369
+
370
+ @mcp.command()
371
+ @click.option(
372
+ "-t",
373
+ "--transport",
374
+ type=click.Choice(["stdio", "sse", "http"]),
375
+ default="stdio",
376
+ help="Transport protocol (default: stdio)",
377
+ )
378
+ @click.option("--host", default="0.0.0.0", help="Host for HTTP/SSE (default: 0.0.0.0)")
379
+ @click.option(
380
+ "--port", default=8095, type=int, help="Port for HTTP/SSE (default: 8095)"
381
+ )
382
+ def start(transport, host, port):
383
+ """
384
+ Start the stats MCP server
385
+
386
+ \b
387
+ Examples:
388
+ scitex stats mcp start
389
+ scitex stats mcp start -t http --port 8095
390
+ """
391
+ try:
392
+ from scitex.stats.mcp_server import main as run_server
393
+
394
+ if transport != "stdio":
395
+ click.secho(f"Starting stats MCP server ({transport})", fg="cyan")
396
+ click.echo(f" Host: {host}")
397
+ click.echo(f" Port: {port}")
398
+
399
+ run_server()
400
+
401
+ except ImportError as e:
402
+ click.secho(f"Error: {e}", fg="red", err=True)
403
+ click.echo("\nInstall dependencies: pip install fastmcp")
404
+ sys.exit(1)
405
+ except Exception as e:
406
+ click.secho(f"Error: {e}", fg="red", err=True)
407
+ sys.exit(1)
408
+
409
+
410
+ @mcp.command()
411
+ def doctor():
412
+ """
413
+ Check MCP server health and dependencies
414
+
415
+ \b
416
+ Example:
417
+ scitex stats mcp doctor
418
+ """
419
+ click.secho("Stats MCP Server Health Check", fg="cyan", bold=True)
420
+ click.echo()
421
+
422
+ click.echo("Checking FastMCP... ", nl=False)
423
+ try:
424
+ import fastmcp # noqa: F401
425
+
426
+ click.secho("OK", fg="green")
427
+ except ImportError:
428
+ click.secho("NOT INSTALLED", fg="red")
429
+ click.echo(" Install with: pip install fastmcp")
430
+
431
+ click.echo("Checking stats module... ", nl=False)
432
+ try:
433
+ from scitex import stats as _ # noqa: F401
434
+
435
+ click.secho("OK", fg="green")
436
+ except ImportError as e:
437
+ click.secho(f"FAIL ({e})", fg="red")
438
+
439
+
440
+ @mcp.command("list-tools")
441
+ def list_tools():
442
+ """
443
+ List available MCP tools
444
+
445
+ \b
446
+ Example:
447
+ scitex stats mcp list-tools
448
+ """
449
+ click.secho("Stats MCP Tools", fg="cyan", bold=True)
450
+ click.echo()
451
+ tools = [
452
+ ("stats_recommend_tests", "Recommend appropriate statistical tests"),
453
+ ("stats_run_test", "Execute a statistical test on data"),
454
+ ("stats_format_results", "Format results in journal style"),
455
+ ("stats_power_analysis", "Calculate power or sample size"),
456
+ ("stats_correct_pvalues", "Apply multiple comparison correction"),
457
+ ("stats_describe", "Calculate descriptive statistics"),
458
+ ("stats_effect_size", "Calculate effect size"),
459
+ ("stats_normality_test", "Test for normal distribution"),
460
+ ("stats_posthoc_test", "Run post-hoc pairwise comparisons"),
461
+ ("stats_p_to_stars", "Convert p-value to significance stars"),
462
+ ]
463
+ for name, desc in tools:
464
+ click.echo(f" {name}: {desc}")
465
+
466
+
342
467
  if __name__ == "__main__":
343
468
  stats()
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)