scitex 2.16.0__py3-none-any.whl → 2.16.1__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 (64) hide show
  1. scitex/_mcp_tools/audio.py +11 -65
  2. scitex/audio/README.md +40 -12
  3. scitex/audio/__init__.py +27 -235
  4. scitex/audio/_audio_check.py +93 -0
  5. scitex/audio/_mcp/speak_handlers.py +56 -8
  6. scitex/audio/_speak.py +295 -0
  7. scitex/audio/mcp_server.py +98 -73
  8. scitex/social/__init__.py +1 -24
  9. scitex/writer/README.md +25 -409
  10. scitex/writer/__init__.py +98 -13
  11. {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/METADATA +6 -1
  12. {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/RECORD +15 -62
  13. scitex/writer/Writer.py +0 -487
  14. scitex/writer/_clone_writer_project.py +0 -160
  15. scitex/writer/_compile/__init__.py +0 -41
  16. scitex/writer/_compile/_compile_async.py +0 -130
  17. scitex/writer/_compile/_compile_unified.py +0 -148
  18. scitex/writer/_compile/_parser.py +0 -63
  19. scitex/writer/_compile/_runner.py +0 -457
  20. scitex/writer/_compile/_validator.py +0 -46
  21. scitex/writer/_compile/manuscript.py +0 -110
  22. scitex/writer/_compile/revision.py +0 -82
  23. scitex/writer/_compile/supplementary.py +0 -100
  24. scitex/writer/_dataclasses/__init__.py +0 -44
  25. scitex/writer/_dataclasses/config/_CONSTANTS.py +0 -46
  26. scitex/writer/_dataclasses/config/_WriterConfig.py +0 -175
  27. scitex/writer/_dataclasses/config/__init__.py +0 -9
  28. scitex/writer/_dataclasses/contents/_ManuscriptContents.py +0 -236
  29. scitex/writer/_dataclasses/contents/_RevisionContents.py +0 -136
  30. scitex/writer/_dataclasses/contents/_SupplementaryContents.py +0 -114
  31. scitex/writer/_dataclasses/contents/__init__.py +0 -9
  32. scitex/writer/_dataclasses/core/_Document.py +0 -146
  33. scitex/writer/_dataclasses/core/_DocumentSection.py +0 -546
  34. scitex/writer/_dataclasses/core/__init__.py +0 -7
  35. scitex/writer/_dataclasses/results/_CompilationResult.py +0 -165
  36. scitex/writer/_dataclasses/results/_LaTeXIssue.py +0 -102
  37. scitex/writer/_dataclasses/results/_SaveSectionsResponse.py +0 -118
  38. scitex/writer/_dataclasses/results/_SectionReadResponse.py +0 -131
  39. scitex/writer/_dataclasses/results/__init__.py +0 -11
  40. scitex/writer/_dataclasses/tree/MINIMUM_FILES.md +0 -121
  41. scitex/writer/_dataclasses/tree/_ConfigTree.py +0 -86
  42. scitex/writer/_dataclasses/tree/_ManuscriptTree.py +0 -84
  43. scitex/writer/_dataclasses/tree/_RevisionTree.py +0 -97
  44. scitex/writer/_dataclasses/tree/_ScriptsTree.py +0 -118
  45. scitex/writer/_dataclasses/tree/_SharedTree.py +0 -100
  46. scitex/writer/_dataclasses/tree/_SupplementaryTree.py +0 -101
  47. scitex/writer/_dataclasses/tree/__init__.py +0 -23
  48. scitex/writer/_mcp/__init__.py +0 -4
  49. scitex/writer/_mcp/handlers.py +0 -32
  50. scitex/writer/_mcp/tool_schemas.py +0 -33
  51. scitex/writer/_project/__init__.py +0 -29
  52. scitex/writer/_project/_create.py +0 -89
  53. scitex/writer/_project/_trees.py +0 -63
  54. scitex/writer/_project/_validate.py +0 -61
  55. scitex/writer/utils/.legacy_git_retry.py +0 -164
  56. scitex/writer/utils/__init__.py +0 -24
  57. scitex/writer/utils/_converters.py +0 -635
  58. scitex/writer/utils/_parse_latex_logs.py +0 -138
  59. scitex/writer/utils/_parse_script_args.py +0 -156
  60. scitex/writer/utils/_verify_tree_structure.py +0 -205
  61. scitex/writer/utils/_watch.py +0 -96
  62. {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/WHEEL +0 -0
  63. {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/entry_points.txt +0 -0
  64. {scitex-2.16.0.dist-info → scitex-2.16.1.dist-info}/licenses/LICENSE +0 -0
@@ -16,7 +16,7 @@ scitex/_mcp_resources/_modules.py,sha256=17LZpOPSmr9XwgGJg2vRgEK596S5FoSYb320vgm
16
16
  scitex/_mcp_resources/_scholar.py,sha256=RSYt7j6bcbKtR-tOtvCtdE6J3IS8C925_c34t0Z1Es8,4689
17
17
  scitex/_mcp_resources/_session.py,sha256=lbe9W3cfPOyoq6bPOeN-jB8MwI4DnRWMpxHmpfn97SM,4590
18
18
  scitex/_mcp_tools/__init__.py,sha256=zFHC9td0__88O41gBlL1Fh07R2m48AYSpUVd_1dZ6Zc,1305
19
- scitex/_mcp_tools/audio.py,sha256=LBX9YQZkNGAXfoIEFljnHRk39gTyJfdaVPCRrS6F8qE,6245
19
+ scitex/_mcp_tools/audio.py,sha256=EZ7lwz_VvrjSl1bhAUXzFgXCD141A6VfrW0_NOYtxvU,4750
20
20
  scitex/_mcp_tools/canvas.py,sha256=KG6JfguRYfatnQyj2rD8NC_ettjvq5IAL9ggBrrXoLM,4877
21
21
  scitex/_mcp_tools/capture.py,sha256=k7pwuB1vdP-VCYjutajEZEsvVAKY-8_mEYrYGWXgOo8,5658
22
22
  scitex/_mcp_tools/dataset.py,sha256=m53HCktI33m_MOXkCiN-s8xV3F8vsC7KWh75o0ZC1Qo,812
@@ -171,17 +171,19 @@ scitex/ai/utils/_sliding_window_data_augmentation.py,sha256=80uSbUnt8LDMmxzRmjPo
171
171
  scitex/ai/utils/_under_sample.py,sha256=8BfDaou3MR890wNCV_spdrxerAjSHpBZVxxsF0t-t-0,1197
172
172
  scitex/ai/utils/_verify_n_gpus.py,sha256=FEmnwsSNzNIdTPbftbFP68yqKtwpiPtwDlxIivhLICg,438
173
173
  scitex/ai/utils/grid_search.py,sha256=XJ-cEsswH4B5BtmwQKQVZXc9kwFnK0Uo7FmzsEFvTMc,4646
174
- scitex/audio/README.md,sha256=F6C8wKnHCvyf8q4skmfJnm3-8u7fZ0z1x2nsIIdzSqo,4107
175
- scitex/audio/__init__.py,sha256=OuTC9l3HzfvYXhLZZMY98KNa29cIz-Vj6RFJfYv6RLU,13783
174
+ scitex/audio/README.md,sha256=BirKKK30uX-5_-p3NaJTsbbosQEthwzvD7d3mRvWEMo,5065
175
+ scitex/audio/__init__.py,sha256=QR9A2g9Lf8MHubyPfT0JsexY_GQDdv8tiOQXwHVf3EE,7111
176
176
  scitex/audio/__main__.py,sha256=IjdxdB5C_4GdxqLGUwDu-Qz_eNCUjhGgKvVTY2_Hsio,3822
177
+ scitex/audio/_audio_check.py,sha256=tZDHjuFX6F9IVi2hdeHuuWcbd_Izy5IlDWk0WPfhKqM,2802
177
178
  scitex/audio/_branding.py,sha256=WbPMGUdCNfvT71JziSSS4bZGK9J7aQLXRWBoRgvLMzQ,5010
178
179
  scitex/audio/_cross_process_lock.py,sha256=ujQnCmVOCJxii-N6wtyWo5eflO3HW65PCmvVHgw0Ayc,3864
179
180
  scitex/audio/_relay.py,sha256=3XhLxbrbOBMSNVi6lSurbrYA9c4wEOjkDnPkBRTUuqs,6189
181
+ scitex/audio/_speak.py,sha256=L8PSZHUFd8_f_N0PDbV7e6a8C1SrZ33qN6Vc0jstMls,9683
180
182
  scitex/audio/_tts.py,sha256=rqpMbek_G_0VGpiH4yZYWu53XC9EnL9CH9eUUZn3lAQ,10034
181
- scitex/audio/mcp_server.py,sha256=v8R4TeZMp1INFXtGKU9_57L5pboZwgeQTsauTaosn6M,14500
183
+ scitex/audio/mcp_server.py,sha256=O-ZUKnI7-HY4NzX6-r1MokhuPDBasSw24trjG7WSAPg,15805
182
184
  scitex/audio/_mcp/__init__.py,sha256=Y9H7ws266TNmKAXN7J4u4_heF6LNdiDGPLursC2wdV4,829
183
185
  scitex/audio/_mcp/handlers.py,sha256=9rXEDOFbAarp0Hqj2qiQxTXxg_o8AZxLmx7WakRc7Qo,11534
184
- scitex/audio/_mcp/speak_handlers.py,sha256=HlONGygUZCffnf7Fsl-xjBkveTS58FCCBfZ97wydqDg,7031
186
+ scitex/audio/_mcp/speak_handlers.py,sha256=vl-LwB9BUivgh210gET5G_EwYsv9uumE-MtQ12gA2aM,9065
185
187
  scitex/audio/_mcp/tool_schemas.py,sha256=SaQs3HGzAgqJl4B0-p3BNobgcaUV69AQb7facbGfLGU,7484
186
188
  scitex/audio/engines/__init__.py,sha256=PrWJtphKxiA2xswOJK19SMJVd1BYDmNuVqlK3v9DU-E,903
187
189
  scitex/audio/engines/_base.py,sha256=YIhUvLFph53AqO53oTqYHNo97UIGNPU58tK4UozREPU,8025
@@ -2412,7 +2414,7 @@ scitex/sh/_shell_legacy.py,sha256=OfRNwKihPpM2LfezmQoBCYYfy-9CJl2seuAz3HSYo4w,13
2412
2414
  scitex/sh/_types.py,sha256=ydWw3i82K3XmSow3ldAgG40Og-vZ75fPy7NzR2cwBx4,605
2413
2415
  scitex/sh/test_sh.py,sha256=qHJdUXvTSY5FXrgNXz1gzdhzDK6TH-oTbgjZRkW7D6w,1968
2414
2416
  scitex/sh/test_sh_simple.py,sha256=G-EukceD5gbxCY_K0x2LBJL8FT2Gkzd5XPrZrGoIyck,1661
2415
- scitex/social/__init__.py,sha256=fUNoTJ2Q6YZ_9u7IBbFgXDgdxbOAW79M459n4WU2Eyk,4051
2417
+ scitex/social/__init__.py,sha256=0X1j2bvhwpxZZQqWTf3Z5CPFteosrAf1xdvbQAoL3rE,3464
2416
2418
  scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md,sha256=k61TlK7joYnKlKaprQ54c2qayTNBPG01NtAMDes3pX4,4214
2417
2419
  scitex/stats/README.md,sha256=v6PMJRE-NI9bnHXfEnzES4dYHLOyTWpSSDLAzsp161I,33416
2418
2420
  scitex/stats/__init__.py,sha256=Pnq-9HC5oLwUUUhQ3aRrBRSWNkPDRZMkjgvnzX5DWPE,10010
@@ -2572,59 +2574,10 @@ scitex/web/_scraping.py,sha256=6jfguvscysZySpuRIQOaq_R8mSOMUloekdbYxKJNY-g,4336
2572
2574
  scitex/web/_search_pubmed.py,sha256=tiRAeV8V5L-0G8pkIheIaY5_46KCYtbSwj4FHFU0RB0,15285
2573
2575
  scitex/web/_summarize_url.py,sha256=PpWBk727pjC_yivI_RVNU_RMxjV_jrqlMNaD6kXQAPk,4489
2574
2576
  scitex/web/download_images.py,sha256=g4sxWzg0ip5Wig7ElPo6fDz5DdXKyJnAsBFwIYoQI6g,9473
2575
- scitex/writer/README.md,sha256=1026ZBezSHDSy5fMri5KhOEc00co2ieCOnyIOq5lTmo,14293
2576
- scitex/writer/Writer.py,sha256=NNxT3hubEv5Sj4yHQeFH3_J7NY772rL-Kvvtchmq1qU,15439
2577
- scitex/writer/__init__.py,sha256=5y17XvbSPfNlPxDRfyiN4QOJkMlupZj3_599rV15xMo,1135
2578
- scitex/writer/_clone_writer_project.py,sha256=SdTtUkJLBx8-zTuBCO5YFP89GRzsrKFoTHSeElJDuBM,4480
2579
- scitex/writer/_compile/__init__.py,sha256=Jsfxsnqvmv95-KprrdsTMX5K-kBiGFpSNxc-LYwhm2E,1157
2580
- scitex/writer/_compile/_compile_async.py,sha256=T6Jisx-VgSl1hcPd8HlsGyMqyGPhl_BvtpXleHr9iJA,3926
2581
- scitex/writer/_compile/_compile_unified.py,sha256=ZhdYQ42A7GYGjrTxy5huXkkmFmX74GnkmCm9ptNCorU,4664
2582
- scitex/writer/_compile/_parser.py,sha256=yRM2eI_Y3jRGwjQXwoMnu6EPRX2B413WGdze0AD-3nk,1543
2583
- scitex/writer/_compile/_runner.py,sha256=Ga_WIMgl40XcV3Oca1WDpp1fH7Gdkb4HJLhZkF_gq3g,13731
2584
- scitex/writer/_compile/_validator.py,sha256=ZKYkk85WlQdIkvIQ7fBFPkZxqP3_UixepoCgYvNfiQ4,1019
2585
- scitex/writer/_compile/manuscript.py,sha256=H4CqzMdPrr7jjcbDGZJaWQt7JLbK5UM5sgtXTlhh0Hs,2954
2586
- scitex/writer/_compile/revision.py,sha256=P3oPfEXcH55IN9ua3VdsnxN5MjAEk_9b7Nluq8m5vRM,2192
2587
- scitex/writer/_compile/supplementary.py,sha256=CpVJMBXa1zF7rlroaCtb8v7SC8E5Qy6eoc3RXprsNIA,2692
2588
- scitex/writer/_dataclasses/__init__.py,sha256=4iCoQlmGrFb830CYna-B1i5XiOq_6FLOlVCRq8upfmc,1087
2589
- scitex/writer/_dataclasses/config/_CONSTANTS.py,sha256=sBPFguqc3eNXAzsllkx0gX1XHwet0mwrl-dYHvr4CZA,1080
2590
- scitex/writer/_dataclasses/config/_WriterConfig.py,sha256=LsiJbOKpA1R6WUJkG4-wW3ea5ElKTS92wqw7wRBeI5k,4474
2591
- scitex/writer/_dataclasses/config/__init__.py,sha256=0XUYxxOZjVe1M-_fM4ibZ6YXWP9o1w8Rq44PRLM6AVw,208
2592
- scitex/writer/_dataclasses/contents/_ManuscriptContents.py,sha256=hoZ0myT1Ybg2qPB1gBCq_hbpYTBniirgVqYXrmWbFK4,7340
2593
- scitex/writer/_dataclasses/contents/_RevisionContents.py,sha256=647iZTCVORb4Hsxkc7L4PBdIesp8WMVYwbpisNI1M4E,4569
2594
- scitex/writer/_dataclasses/contents/_SupplementaryContents.py,sha256=DGzjSfj--Gs5WYFGqIC31NIgvTFM-kzVmVwBf1g6bME,3870
2595
- scitex/writer/_dataclasses/contents/__init__.py,sha256=6DkwQb1-K_d3rHnNfwhW2w2B2wQCMXV-mTTfnbDnvhQ,252
2596
- scitex/writer/_dataclasses/core/_Document.py,sha256=bxLUA01W6IQt2Sa6pyqt_p1StzY2YKYUu-015ED82u0,3755
2597
- scitex/writer/_dataclasses/core/_DocumentSection.py,sha256=0mqGhovAVwQ0dUKL8sOTgbkO0SejPUNg6Rp9ENFLAtA,17072
2598
- scitex/writer/_dataclasses/core/__init__.py,sha256=8zk7o3UOQxvVjmY3OcOTOp5pcJc7u9leVVoCCUV4j04,132
2599
- scitex/writer/_dataclasses/results/_CompilationResult.py,sha256=dtEQFY4Ut_sbtNGKFnqN9a37sBQGoWF9f6-WT6q78hc,4106
2600
- scitex/writer/_dataclasses/results/_LaTeXIssue.py,sha256=WIU6_iHKwg7HUczbBmnHUX6Uu7TvdvTTX2YI8lwiiO0,2267
2601
- scitex/writer/_dataclasses/results/_SaveSectionsResponse.py,sha256=6DTF7eJDcj9UnrbPDFTHSDzDxrN_rPpWWHOoZAZ09qA,3755
2602
- scitex/writer/_dataclasses/results/_SectionReadResponse.py,sha256=LJI5BNdnrt5pG3mJBDCbottOe15UHtb_Z-CzSw-6FTY,3970
2603
- scitex/writer/_dataclasses/results/__init__.py,sha256=-grYV-nD7gjbuCpP56fG4qpeSeWXi9giec2JYlZe3U8,309
2604
- scitex/writer/_dataclasses/tree/MINIMUM_FILES.md,sha256=4ABZUCzhgfvo1yO3Wo0SC12fKMnVXtn45dXU9vuhUeQ,4160
2605
- scitex/writer/_dataclasses/tree/_ConfigTree.py,sha256=wKPBnBOcM9zTaWh2Xw4L2mX7fvbSuk7-bcymckqtT8U,2695
2606
- scitex/writer/_dataclasses/tree/_ManuscriptTree.py,sha256=BjZGQqqsHkJhOa58WMTVShC_vtNRUADCiVq3d6pX4pQ,2476
2607
- scitex/writer/_dataclasses/tree/_RevisionTree.py,sha256=RmqxrVOfMUpo_RAgxlK7ZNCKHpEz_ioxXeJ2prsjka0,2999
2608
- scitex/writer/_dataclasses/tree/_ScriptsTree.py,sha256=pXEQEYP32SAZWSMJ5SNZcfB-Yy4WLf8xKve__9eTlKE,3861
2609
- scitex/writer/_dataclasses/tree/_SharedTree.py,sha256=g2A2aZauG_z-ZCWBsS3vP_ZpC2ID8zd9WzmdSNVu6Jk,3106
2610
- scitex/writer/_dataclasses/tree/_SupplementaryTree.py,sha256=TJCGdNiphzYnklntFDk1ijbRSIh08QDJ4vN2hzRj67g,3267
2611
- scitex/writer/_dataclasses/tree/__init__.py,sha256=HZjCSa7djOyrz8CfZOoox2dioloPJmRoGMX52171lF0,678
2612
- scitex/writer/_mcp/__init__.py,sha256=FJRAr90vUCg4PJ8Sv-WzsKuM7aY93m6UR87fhk843MU,73
2613
- scitex/writer/_mcp/handlers.py,sha256=oyPBC1G6RDQbrQmhLb7lTjfda_YIOxaV7M1f7Eontlg,701
2614
- scitex/writer/_mcp/tool_schemas.py,sha256=9-VBeRQv1IuTxdOmh6HmKBnoGcQTV--1UyUrn3bAIUc,761
2615
- scitex/writer/_project/__init__.py,sha256=fdtDxN795DEKeg3yriYwgDE9j-dJ2tr_Sz2FI8RCm3U,735
2616
- scitex/writer/_project/_create.py,sha256=lfnoSqjVybEeovwqlIHBjQpl75sZw_NzWJjcUf-P0OE,2594
2617
- scitex/writer/_project/_trees.py,sha256=sr9JkIWaxdGMAlRXz_4M6rHOd__0PGMt8Y2nEI3gCxI,1778
2618
- scitex/writer/_project/_validate.py,sha256=oy8LwEP9UwOGrhMOxdPwfLuTT2w4lG_0yKzCi1O4jP4,1537
2619
- scitex/writer/utils/.legacy_git_retry.py,sha256=IKEmx-aZLW_--sJ5PRgBKLTatQj5afVoewyABTcvZb4,3999
2620
- scitex/writer/utils/__init__.py,sha256=2fffroMZTtdVFYrL8xIsfcSKJatHmMWacLSu1ETpUWM,505
2621
- scitex/writer/utils/_converters.py,sha256=aixd7AtDhtG5Ve_213wAaiX4Ea3jnR5wSsSYEiYp6qk,18075
2622
- scitex/writer/utils/_parse_latex_logs.py,sha256=K05kCJClG86-RovXG9I5e3wHP0mEGiZlk9RBPS1P9q0,3140
2623
- scitex/writer/utils/_parse_script_args.py,sha256=Fkx1ze_jlKYIpviLuT7z0hpqE4cdtXXA_7sK3sKpVs4,4593
2624
- scitex/writer/utils/_verify_tree_structure.py,sha256=Uk9NUSleR9aMHpAgUGsPZMk4a75l35EkZhQYKIfolVY,5724
2625
- scitex/writer/utils/_watch.py,sha256=nYzPQ-iPAOzbwzAPBtSrrVBLLPMl08e0qxw0mtv0Y8I,2577
2626
- scitex-2.16.0.dist-info/METADATA,sha256=MuQ0blt2wCEXgqb06hBNN7L31bNG9MhQdQLmIa8fYX0,26297
2627
- scitex-2.16.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
2628
- scitex-2.16.0.dist-info/entry_points.txt,sha256=ZtDrHnPNMnsSmAnQoCHNmk0xKotNyR2X_YFDDteupW8,497
2629
- scitex-2.16.0.dist-info/licenses/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
2630
- scitex-2.16.0.dist-info/RECORD,,
2577
+ scitex/writer/README.md,sha256=RqUMOJD7wUiQjWoiLSf_hl_Y0IAE3_xPxhlp941zYe4,1299
2578
+ scitex/writer/__init__.py,sha256=jQqdIyvQhknySoUAMKreBhAa1KwZ0ieW8SYCppBukts,3301
2579
+ scitex-2.16.1.dist-info/METADATA,sha256=Kq0j5a18i7V8Xbe6rlRChbMkU_NC_WgnCfzI4hXx-wQ,26534
2580
+ scitex-2.16.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
2581
+ scitex-2.16.1.dist-info/entry_points.txt,sha256=ZtDrHnPNMnsSmAnQoCHNmk0xKotNyR2X_YFDDteupW8,497
2582
+ scitex-2.16.1.dist-info/licenses/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
2583
+ scitex-2.16.1.dist-info/RECORD,,
scitex/writer/Writer.py DELETED
@@ -1,487 +0,0 @@
1
- #!/usr/bin/env python3
2
- # Timestamp: "2025-10-29 06:13:07 (ywatanabe)"
3
- # File: /home/ywatanabe/proj/scitex-code/src/scitex/writer/_Writer.py
4
- # ----------------------------------------
5
- from __future__ import annotations
6
-
7
- import os
8
-
9
- __FILE__ = "./src/scitex/writer/_Writer.py"
10
- __DIR__ = os.path.dirname(__FILE__)
11
- # ----------------------------------------
12
-
13
- """
14
- Writer class for manuscript LaTeX compilation.
15
-
16
- Provides object-oriented interface to scitex-writer functionality.
17
- """
18
-
19
-
20
- from pathlib import Path
21
- from typing import Callable, Optional
22
-
23
- from scitex import logging
24
- from scitex.git import init_git_repo
25
-
26
- from ._clone_writer_project import (
27
- clone_writer_project as _clone_writer_project,
28
- )
29
- from ._compile import (
30
- CompilationResult,
31
- compile_manuscript,
32
- compile_revision,
33
- compile_supplementary,
34
- )
35
- from ._dataclasses import ManuscriptTree, RevisionTree, SupplementaryTree
36
- from ._dataclasses.config import DOC_TYPE_DIRS
37
- from ._dataclasses.tree import ScriptsTree, SharedTree
38
- from .utils._watch import watch_manuscript
39
-
40
- logger = logging.getLogger(__name__)
41
-
42
-
43
- class Writer:
44
- """LaTeX manuscript compiler."""
45
-
46
- def __init__(
47
- self,
48
- project_dir: Path,
49
- name: Optional[str] = None,
50
- git_strategy: Optional[str] = "child",
51
- branch: Optional[str] = None,
52
- tag: Optional[str] = None,
53
- ):
54
- """
55
- Initialize for project directory.
56
-
57
- If directory doesn't exist, creates new project.
58
-
59
- Parameters
60
- ----------
61
- project_dir : Path
62
- Path to project directory.
63
- name : str, optional
64
- Project name (used if creating new project).
65
- git_strategy : str, optional
66
- Git initialization strategy:
67
- - 'child': Create isolated git in project directory (default)
68
- - 'parent': Use parent git repository
69
- - 'origin': Preserve template's original git history
70
- - None: Disable git initialization
71
- branch : str, optional
72
- Specific branch of template repository to clone.
73
- If None, clones the default branch. Mutually exclusive with tag.
74
- tag : str, optional
75
- Specific tag/release of template repository to clone.
76
- If None, clones the default branch. Mutually exclusive with branch.
77
- """
78
- self.project_name = name or Path(project_dir).name
79
- self.project_dir = Path(project_dir)
80
- self.git_strategy = git_strategy
81
- self.branch = branch
82
- self.tag = tag
83
-
84
- ref_info = ""
85
- if branch:
86
- ref_info = f" (branch: {branch})"
87
- elif tag:
88
- ref_info = f" (tag: {tag})"
89
- logger.info(
90
- f"Writer: Initializing with:\n"
91
- f" Project Name: {self.project_name}\n"
92
- f" Project Directory: {self.project_dir.absolute()}\n"
93
- f" Git Strategy: {self.git_strategy}{ref_info}..."
94
- )
95
-
96
- # Create or attach to project
97
- self.project_dir = self._attach_or_create_project(name)
98
-
99
- # Initialize git repository based on strategy (delegates to template module)
100
- self.git_root = init_git_repo(self.project_dir, self.git_strategy)
101
-
102
- # Document accessors (pass git_root for efficiency)
103
- self.shared = SharedTree(self.project_dir / "00_shared", git_root=self.git_root)
104
- self.manuscript = ManuscriptTree(
105
- self.project_dir / "01_manuscript", git_root=self.git_root
106
- )
107
- self.supplementary = SupplementaryTree(
108
- self.project_dir / "02_supplementary", git_root=self.git_root
109
- )
110
- self.revision = RevisionTree(
111
- self.project_dir / "03_revision", git_root=self.git_root
112
- )
113
- self.scripts = ScriptsTree(self.project_dir / "scripts", git_root=self.git_root)
114
-
115
- logger.success(f"Writer: Initialization complete for {self.project_name}")
116
-
117
- def _attach_or_create_project(self, name: Optional[str] = None) -> Path:
118
- """
119
- Create new project or attach to existing one.
120
-
121
- If project directory doesn't exist, creates it based on git_strategy:
122
- - 'child': Full template with git initialization
123
- - 'parent'/'None': Minimal directory structure
124
-
125
- Parameters
126
- ----------
127
- name : str, optional
128
- Project name (used if creating new project).
129
-
130
- Returns
131
- -------
132
- Path
133
- Path to the project directory.
134
- """
135
- if self.project_dir.exists():
136
- logger.info(
137
- f"Writer: Attached to existing project at {self.project_dir.absolute()}"
138
- )
139
- # Verify existing project structure
140
- self._verify_project_structure()
141
- return self.project_dir
142
-
143
- project_name = name or self.project_dir.name
144
-
145
- logger.info(
146
- f"Writer: Creating new project '{project_name}' at {self.project_dir.absolute()}"
147
- )
148
-
149
- # Initialize project directory structure
150
- success = _clone_writer_project(
151
- str(self.project_dir), self.git_strategy, self.branch, self.tag
152
- )
153
-
154
- if not success:
155
- logger.error(
156
- f"Writer: Failed to initialize project directory for {project_name}"
157
- )
158
- raise RuntimeError(
159
- f"Could not create project directory at {self.project_dir}"
160
- )
161
-
162
- # Verify project directory was created
163
- if not self.project_dir.exists():
164
- logger.error(
165
- f"Writer: Project directory {self.project_dir} was not created"
166
- )
167
- raise RuntimeError(f"Project directory {self.project_dir} was not created")
168
-
169
- logger.success(
170
- f"Writer: Successfully created project at {self.project_dir.absolute()}"
171
- )
172
- return self.project_dir
173
-
174
- def _verify_project_structure(self) -> None:
175
- """
176
- Verify attached project has expected structure.
177
-
178
- Checks:
179
- - Required directories exist (01_manuscript, 02_supplementary, 03_revision)
180
- - .git exists (for git-enabled strategies)
181
-
182
- Raises
183
- ------
184
- RuntimeError
185
- If structure is invalid.
186
- """
187
- required_dirs = [
188
- self.project_dir / "01_manuscript",
189
- self.project_dir / "02_supplementary",
190
- self.project_dir / "03_revision",
191
- ]
192
-
193
- for dir_path in required_dirs:
194
- if not dir_path.exists():
195
- logger.error(f"Writer: Expected directory missing: {dir_path}")
196
- raise RuntimeError(
197
- f"Project structure invalid: missing {dir_path.name} directory"
198
- )
199
-
200
- logger.success(
201
- f"Writer: Project structure verified at {self.project_dir.absolute()}"
202
- )
203
-
204
- def compile_manuscript(
205
- self,
206
- timeout: int = 300,
207
- log_callback: Optional[Callable[[str], None]] = None,
208
- progress_callback: Optional[Callable[[int, str], None]] = None,
209
- ) -> CompilationResult:
210
- """
211
- Compile manuscript to PDF with optional live callbacks.
212
-
213
- Runs scripts/shell/compile_manuscript.sh with configured settings.
214
-
215
- Parameters
216
- ----------
217
- timeout : int, optional
218
- Maximum compilation time in seconds (default: 300).
219
- log_callback : callable, optional
220
- Called with each log line: log_callback("Running pdflatex...").
221
- progress_callback : callable, optional
222
- Called with progress: progress_callback(50, "Pass 2/3").
223
-
224
- Returns
225
- -------
226
- CompilationResult
227
- With success status, PDF path, and errors/warnings.
228
-
229
- Examples
230
- --------
231
- >>> writer = Writer(Path("my_paper"))
232
- >>> result = writer.compile_manuscript()
233
- >>> if result.success:
234
- ... print(f"PDF created: {result.output_pdf}")
235
- """
236
- return compile_manuscript(
237
- self.project_dir,
238
- timeout=timeout,
239
- log_callback=log_callback,
240
- progress_callback=progress_callback,
241
- )
242
-
243
- def compile_supplementary(
244
- self,
245
- timeout: int = 300,
246
- log_callback: Optional[Callable[[str], None]] = None,
247
- progress_callback: Optional[Callable[[int, str], None]] = None,
248
- ) -> CompilationResult:
249
- """
250
- Compile supplementary materials to PDF with optional live callbacks.
251
-
252
- Runs scripts/shell/compile_supplementary.sh with configured settings.
253
-
254
- Parameters
255
- ----------
256
- timeout : int, optional
257
- Maximum compilation time in seconds (default: 300).
258
- log_callback : callable, optional
259
- Called with each log line.
260
- progress_callback : callable, optional
261
- Called with progress updates.
262
-
263
- Returns
264
- -------
265
- CompilationResult
266
- With success status, PDF path, and errors/warnings.
267
-
268
- Examples
269
- --------
270
- >>> writer = Writer(Path("my_paper"))
271
- >>> result = writer.compile_supplementary()
272
- >>> if result.success:
273
- ... print(f"PDF created: {result.output_pdf}")
274
- """
275
- return compile_supplementary(
276
- self.project_dir,
277
- timeout=timeout,
278
- log_callback=log_callback,
279
- progress_callback=progress_callback,
280
- )
281
-
282
- def compile_revision(
283
- self,
284
- track_changes: bool = False,
285
- timeout: int = 300,
286
- log_callback: Optional[Callable[[str], None]] = None,
287
- progress_callback: Optional[Callable[[int, str], None]] = None,
288
- ) -> CompilationResult:
289
- """
290
- Compile revision document with optional change tracking and live callbacks.
291
-
292
- Runs scripts/shell/compile_revision.sh with configured settings.
293
-
294
- Parameters
295
- ----------
296
- track_changes : bool, optional
297
- Enable change tracking in compiled PDF (default: False).
298
- timeout : int, optional
299
- Maximum compilation time in seconds (default: 300).
300
- log_callback : callable, optional
301
- Called with each log line.
302
- progress_callback : callable, optional
303
- Called with progress updates.
304
-
305
- Returns
306
- -------
307
- CompilationResult
308
- With success status, PDF path, and errors/warnings.
309
-
310
- Examples
311
- --------
312
- >>> writer = Writer(Path("my_paper"))
313
- >>> result = writer.compile_revision(track_changes=True)
314
- >>> if result.success:
315
- ... print(f"Revision PDF: {result.output_pdf}")
316
- """
317
- return compile_revision(
318
- self.project_dir,
319
- track_changes=track_changes,
320
- timeout=timeout,
321
- log_callback=log_callback,
322
- progress_callback=progress_callback,
323
- )
324
-
325
- def watch(self, on_compile: Optional[Callable] = None) -> None:
326
- """Auto-recompile on file changes."""
327
- watch_manuscript(self.project_dir, on_compile=on_compile)
328
-
329
- def get_pdf(self, doc_type: str = "manuscript") -> Optional[Path]:
330
- """Get output PDF path (Read)."""
331
- pdf = self.project_dir / DOC_TYPE_DIRS[doc_type] / f"{doc_type}.pdf"
332
- return pdf if pdf.exists() else None
333
-
334
- def delete(self) -> bool:
335
- """Delete project directory (Delete)."""
336
- import shutil
337
-
338
- try:
339
- logger.warning(
340
- f"Writer: Deleting project directory at {self.project_dir.absolute()}"
341
- )
342
- shutil.rmtree(self.project_dir)
343
- logger.success(
344
- f"Writer: Successfully deleted project at {self.project_dir.absolute()}"
345
- )
346
- return True
347
- except Exception as e:
348
- logger.error(
349
- f"Writer: Failed to delete project directory at {self.project_dir.absolute()}: {e}"
350
- )
351
- return False
352
-
353
-
354
- def run_session() -> None:
355
- """Initialize scitex framework, run main function, and cleanup."""
356
- global CONFIG, CC, sys, plt, rng
357
- import sys
358
-
359
- import matplotlib.pyplot as plt
360
-
361
- import scitex as stx
362
-
363
- args = parse_args()
364
-
365
- CONFIG, sys.stdout, sys.stderr, plt, CC, rng = stx.session.start(
366
- sys,
367
- plt,
368
- args=args,
369
- file=__FILE__,
370
- sdir_suffix=None,
371
- verbose=False,
372
- agg=True,
373
- )
374
-
375
- exit_status = main(args)
376
-
377
- stx.session.close(
378
- CONFIG,
379
- verbose=False,
380
- notify=False,
381
- message="",
382
- exit_status=exit_status,
383
- )
384
-
385
-
386
- def main(args):
387
- if args.action == "create":
388
- writer = Writer.create(
389
- args.project_name,
390
- git_strategy=args.git_strategy,
391
- )
392
- if writer:
393
- print(f"Created writer project: {writer.project_dir}")
394
- return 0
395
- else:
396
- print("Failed to create writer project")
397
- return 1
398
-
399
- elif args.action == "compile":
400
- writer = Writer(Path(args.dir) if args.dir else Path.cwd())
401
-
402
- if args.document == "manuscript":
403
- result = writer.compile_manuscript()
404
- elif args.document == "supplementary":
405
- result = writer.compile_supplementary()
406
- elif args.document == "revision":
407
- result = writer.compile_revision(track_changes=args.track_changes)
408
-
409
- if result.success:
410
- print(f"Compilation successful: {result.output_pdf}")
411
- return 0
412
- else:
413
- print(f"Compilation failed (exit code {result.exit_code})")
414
- return result.exit_code
415
-
416
- elif args.action == "info":
417
- writer = Writer(Path(args.dir) if args.dir else Path.cwd())
418
- print(f"Project: {writer.project_dir}")
419
- print("\nDocuments:")
420
- print(f" - Manuscript: {writer.manuscript}")
421
- print(f" - Supplementary: {writer.supplementary}")
422
- print(f" - Revision: {writer.revision}")
423
- return 0
424
-
425
-
426
- def parse_args():
427
- import argparse
428
-
429
- parser = argparse.ArgumentParser(
430
- description="Writer project management and compilation"
431
- )
432
- parser.add_argument(
433
- "--action",
434
- "-a",
435
- type=str,
436
- choices=["create", "compile", "info"],
437
- default="info",
438
- help="Action to perform (default: info)",
439
- )
440
- parser.add_argument(
441
- "--project-name",
442
- "-n",
443
- type=str,
444
- help="Project name (for create action)",
445
- )
446
- parser.add_argument(
447
- "--dir",
448
- "-d",
449
- type=str,
450
- help="Project directory (for compile/info)",
451
- )
452
- parser.add_argument(
453
- "--document",
454
- "-t",
455
- type=str,
456
- choices=["manuscript", "supplementary", "revision"],
457
- default="manuscript",
458
- help="Document to compile (default: manuscript)",
459
- )
460
- parser.add_argument(
461
- "--git-strategy",
462
- "-g",
463
- type=str,
464
- choices=["child", "parent", "origin", "none"],
465
- default="child",
466
- help="Git strategy (for create action, default: child)",
467
- )
468
- parser.add_argument(
469
- "--track-changes",
470
- action="store_true",
471
- help="Enable change tracking (revision only)",
472
- )
473
-
474
- return parser.parse_args()
475
-
476
-
477
- if __name__ == "__main__":
478
- run_session()
479
-
480
-
481
- __all__ = ["Writer"]
482
-
483
- # python -m scitex.writer.Writer --action create --project-name my_paper
484
- # python -m scitex.writer.Writer --action compile --dir ./my_paper --document manuscript
485
- # python -m scitex.writer.Writer --action info --dir ./my_paper
486
-
487
- # EOF