scitex 2.8.1__py3-none-any.whl → 2.10.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 (415) hide show
  1. scitex/__init__.py +15 -7
  2. scitex/__version__.py +1 -2
  3. scitex/_install_guide.py +250 -0
  4. scitex/_optional_deps.py +206 -39
  5. scitex/ai/_gen_ai/_Groq.py +2 -4
  6. scitex/ai/_gen_ai/_OpenAI.py +5 -2
  7. scitex/ai/_gen_ai/_Perplexity.py +20 -6
  8. scitex/audio/__init__.py +24 -15
  9. scitex/audio/_cross_process_lock.py +139 -0
  10. scitex/audio/_mcp_handlers.py +256 -0
  11. scitex/audio/_mcp_tool_schemas.py +203 -0
  12. scitex/audio/engines/elevenlabs_engine.py +5 -2
  13. scitex/audio/mcp_server.py +98 -457
  14. scitex/bridge/__init__.py +30 -19
  15. scitex/bridge/_figrecipe.py +245 -0
  16. scitex/bridge/_helpers.py +2 -1
  17. scitex/bridge/_plt_vis.py +23 -10
  18. scitex/bridge/_stats_plt.py +18 -5
  19. scitex/bridge/_stats_vis.py +16 -2
  20. scitex/browser/__init__.py +84 -44
  21. scitex/browser/automation/__init__.py +5 -1
  22. scitex/browser/core/BrowserMixin.py +17 -4
  23. scitex/browser/core/__init__.py +11 -2
  24. scitex/browser/remote/CaptchaHandler.py +1 -1
  25. scitex/browser/remote/ZenRowsAPIClient.py +1 -1
  26. scitex/capture/grid.py +487 -0
  27. scitex/capture/mcp_handlers.py +401 -0
  28. scitex/capture/mcp_tool_defs.py +192 -0
  29. scitex/capture/mcp_tools.py +241 -0
  30. scitex/capture/mcp_utils.py +30 -0
  31. scitex/cli/convert.py +421 -0
  32. scitex/cli/main.py +6 -4
  33. scitex/datetime/__init__.py +46 -0
  34. scitex/datetime/_linspace.py +100 -0
  35. scitex/datetime/_normalize_timestamp.py +306 -0
  36. scitex/db/_delete_duplicates.py +4 -4
  37. scitex/db/_sqlite3/_delete_duplicates.py +11 -2
  38. scitex/dev/plt/__init__.py +61 -62
  39. scitex/dev/plt/demo_plotters/__init__.py +0 -0
  40. scitex/dev/plt/demo_plotters/plot_mpl_axhline.py +28 -0
  41. scitex/dev/plt/demo_plotters/plot_mpl_axhspan.py +28 -0
  42. scitex/dev/plt/demo_plotters/plot_mpl_axvline.py +28 -0
  43. scitex/dev/plt/demo_plotters/plot_mpl_axvspan.py +28 -0
  44. scitex/dev/plt/demo_plotters/plot_mpl_bar.py +29 -0
  45. scitex/dev/plt/demo_plotters/plot_mpl_barh.py +29 -0
  46. scitex/dev/plt/demo_plotters/plot_mpl_boxplot.py +28 -0
  47. scitex/dev/plt/demo_plotters/plot_mpl_contour.py +31 -0
  48. scitex/dev/plt/demo_plotters/plot_mpl_contourf.py +31 -0
  49. scitex/dev/plt/demo_plotters/plot_mpl_errorbar.py +30 -0
  50. scitex/dev/plt/demo_plotters/plot_mpl_eventplot.py +28 -0
  51. scitex/dev/plt/demo_plotters/plot_mpl_fill.py +30 -0
  52. scitex/dev/plt/demo_plotters/plot_mpl_fill_between.py +31 -0
  53. scitex/dev/plt/demo_plotters/plot_mpl_hexbin.py +28 -0
  54. scitex/dev/plt/demo_plotters/plot_mpl_hist.py +28 -0
  55. scitex/dev/plt/demo_plotters/plot_mpl_hist2d.py +28 -0
  56. scitex/dev/plt/demo_plotters/plot_mpl_imshow.py +29 -0
  57. scitex/dev/plt/demo_plotters/plot_mpl_pcolormesh.py +31 -0
  58. scitex/dev/plt/demo_plotters/plot_mpl_pie.py +29 -0
  59. scitex/dev/plt/demo_plotters/plot_mpl_plot.py +29 -0
  60. scitex/dev/plt/demo_plotters/plot_mpl_quiver.py +31 -0
  61. scitex/dev/plt/demo_plotters/plot_mpl_scatter.py +28 -0
  62. scitex/dev/plt/demo_plotters/plot_mpl_stackplot.py +31 -0
  63. scitex/dev/plt/demo_plotters/plot_mpl_stem.py +29 -0
  64. scitex/dev/plt/demo_plotters/plot_mpl_step.py +29 -0
  65. scitex/dev/plt/demo_plotters/plot_mpl_violinplot.py +28 -0
  66. scitex/dev/plt/demo_plotters/plot_sns_barplot.py +29 -0
  67. scitex/dev/plt/demo_plotters/plot_sns_boxplot.py +29 -0
  68. scitex/dev/plt/demo_plotters/plot_sns_heatmap.py +28 -0
  69. scitex/dev/plt/demo_plotters/plot_sns_histplot.py +29 -0
  70. scitex/dev/plt/demo_plotters/plot_sns_kdeplot.py +29 -0
  71. scitex/dev/plt/demo_plotters/plot_sns_lineplot.py +31 -0
  72. scitex/dev/plt/demo_plotters/plot_sns_scatterplot.py +29 -0
  73. scitex/dev/plt/demo_plotters/plot_sns_stripplot.py +29 -0
  74. scitex/dev/plt/demo_plotters/plot_sns_swarmplot.py +29 -0
  75. scitex/dev/plt/demo_plotters/plot_sns_violinplot.py +29 -0
  76. scitex/dev/plt/demo_plotters/plot_stx_bar.py +29 -0
  77. scitex/dev/plt/demo_plotters/plot_stx_barh.py +29 -0
  78. scitex/dev/plt/demo_plotters/plot_stx_box.py +28 -0
  79. scitex/dev/plt/demo_plotters/plot_stx_boxplot.py +28 -0
  80. scitex/dev/plt/demo_plotters/plot_stx_conf_mat.py +28 -0
  81. scitex/dev/plt/demo_plotters/plot_stx_contour.py +31 -0
  82. scitex/dev/plt/demo_plotters/plot_stx_ecdf.py +28 -0
  83. scitex/dev/plt/demo_plotters/plot_stx_errorbar.py +30 -0
  84. scitex/dev/plt/demo_plotters/plot_stx_fill_between.py +31 -0
  85. scitex/dev/plt/demo_plotters/plot_stx_fillv.py +28 -0
  86. scitex/dev/plt/demo_plotters/plot_stx_heatmap.py +28 -0
  87. scitex/dev/plt/demo_plotters/plot_stx_image.py +28 -0
  88. scitex/dev/plt/demo_plotters/plot_stx_imshow.py +28 -0
  89. scitex/dev/plt/demo_plotters/plot_stx_joyplot.py +28 -0
  90. scitex/dev/plt/demo_plotters/plot_stx_kde.py +28 -0
  91. scitex/dev/plt/demo_plotters/plot_stx_line.py +28 -0
  92. scitex/dev/plt/demo_plotters/plot_stx_mean_ci.py +28 -0
  93. scitex/dev/plt/demo_plotters/plot_stx_mean_std.py +28 -0
  94. scitex/dev/plt/demo_plotters/plot_stx_median_iqr.py +28 -0
  95. scitex/dev/plt/demo_plotters/plot_stx_raster.py +28 -0
  96. scitex/dev/plt/demo_plotters/plot_stx_rectangle.py +28 -0
  97. scitex/dev/plt/demo_plotters/plot_stx_scatter.py +29 -0
  98. scitex/dev/plt/demo_plotters/plot_stx_shaded_line.py +29 -0
  99. scitex/dev/plt/demo_plotters/plot_stx_violin.py +28 -0
  100. scitex/dev/plt/demo_plotters/plot_stx_violinplot.py +28 -0
  101. scitex/dev/plt/mpl/get_dir_ax.py +46 -0
  102. scitex/dev/plt/mpl/get_signatures.py +176 -0
  103. scitex/dev/plt/mpl/get_signatures_details.py +522 -0
  104. scitex/dict/_pop_keys.py +1 -7
  105. scitex/dsp/__init__.py +15 -10
  106. scitex/dsp/add_noise.py +5 -2
  107. scitex/dsp/example.py +35 -22
  108. scitex/dsp/filt.py +8 -3
  109. scitex/dsp/reference.py +3 -2
  110. scitex/dsp/utils/__init__.py +2 -1
  111. scitex/dsp/utils/_differential_bandpass_filters.py +14 -4
  112. scitex/dt/__init__.py +39 -2
  113. scitex/errors.py +82 -521
  114. scitex/fig/__init__.py +4 -4
  115. scitex/fig/editor/edit/panel_loader.py +1 -1
  116. scitex/fig/io/_bundle.py +7 -7
  117. scitex/fts/README.md +262 -0
  118. scitex/fts/TODO.md +66 -0
  119. scitex/fts/__init__.py +90 -0
  120. scitex/fts/_bundle/README_IN_BUNDLE.md +102 -0
  121. scitex/fts/_bundle/_FTS.py +657 -0
  122. scitex/fts/_bundle/__init__.py +38 -0
  123. scitex/fts/_bundle/_children.py +216 -0
  124. scitex/fts/_bundle/_conversion/__init__.py +15 -0
  125. scitex/fts/_bundle/_conversion/_bundle2dict.py +44 -0
  126. scitex/fts/_bundle/_conversion/_dict2bundle.py +50 -0
  127. scitex/fts/_bundle/_dataclasses/_Axes.py +57 -0
  128. scitex/fts/_bundle/_dataclasses/_BBox.py +54 -0
  129. scitex/fts/_bundle/_dataclasses/_ColumnDef.py +72 -0
  130. scitex/fts/_bundle/_dataclasses/_DataFormat.py +40 -0
  131. scitex/fts/_bundle/_dataclasses/_DataInfo.py +135 -0
  132. scitex/fts/_bundle/_dataclasses/_DataSource.py +44 -0
  133. scitex/fts/_bundle/_dataclasses/_Node.py +319 -0
  134. scitex/fts/_bundle/_dataclasses/_NodeRefs.py +45 -0
  135. scitex/fts/_bundle/_dataclasses/_SizeMM.py +38 -0
  136. scitex/fts/_bundle/_dataclasses/__init__.py +35 -0
  137. scitex/fts/_bundle/_extractors/__init__.py +32 -0
  138. scitex/fts/_bundle/_extractors/_extract_bar.py +131 -0
  139. scitex/fts/_bundle/_extractors/_extract_line.py +71 -0
  140. scitex/fts/_bundle/_extractors/_extract_scatter.py +79 -0
  141. scitex/fts/_bundle/_loader.py +134 -0
  142. scitex/fts/_bundle/_mpl_helpers.py +389 -0
  143. scitex/fts/_bundle/_saver.py +269 -0
  144. scitex/fts/_bundle/_storage.py +200 -0
  145. scitex/fts/_bundle/_utils/__init__.py +55 -0
  146. scitex/fts/_bundle/_utils/_const.py +26 -0
  147. scitex/fts/_bundle/_utils/_errors.py +73 -0
  148. scitex/fts/_bundle/_utils/_generate.py +21 -0
  149. scitex/fts/_bundle/_utils/_types.py +76 -0
  150. scitex/fts/_bundle/_validation.py +434 -0
  151. scitex/fts/_bundle/_zipbundle.py +165 -0
  152. scitex/fts/_fig/__init__.py +22 -0
  153. scitex/fts/_fig/_backend/__init__.py +53 -0
  154. scitex/fts/_fig/_backend/_export.py +165 -0
  155. scitex/fts/_fig/_backend/_parser.py +188 -0
  156. scitex/fts/_fig/_backend/_render.py +538 -0
  157. scitex/fts/_fig/_composite.py +345 -0
  158. scitex/fts/_fig/_dataclasses/_ChannelEncoding.py +46 -0
  159. scitex/fts/_fig/_dataclasses/_Encoding.py +82 -0
  160. scitex/fts/_fig/_dataclasses/_Theme.py +441 -0
  161. scitex/fts/_fig/_dataclasses/_TraceEncoding.py +52 -0
  162. scitex/fts/_fig/_dataclasses/__init__.py +47 -0
  163. scitex/fts/_fig/_editor/__init__.py +14 -0
  164. scitex/fts/_fig/_editor/_cui/__init__.py +33 -0
  165. scitex/fts/_fig/_editor/_cui/_backend_detector.py +39 -0
  166. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +366 -0
  167. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +175 -0
  168. scitex/fts/_fig/_editor/_cui/_manual_handler.py +52 -0
  169. scitex/fts/_fig/_editor/_cui/_panel_loader.py +246 -0
  170. scitex/fts/_fig/_editor/_cui/_path_resolver.py +66 -0
  171. scitex/fts/_fig/_editor/_defaults.py +300 -0
  172. scitex/fts/_fig/_editor/_gui/__init__.py +11 -0
  173. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +20 -0
  174. scitex/fts/_fig/_editor/_gui/_flask_editor/_bbox.py +1339 -0
  175. scitex/fts/_fig/_editor/_gui/_flask_editor/_core.py +1688 -0
  176. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +664 -0
  177. scitex/fts/_fig/_editor/_gui/_flask_editor/_renderer.py +853 -0
  178. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +79 -0
  179. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +41 -0
  180. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +16 -0
  181. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +85 -0
  182. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +217 -0
  183. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +93 -0
  184. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +57 -0
  185. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +112 -0
  186. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +59 -0
  187. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +212 -0
  188. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/canvas.css +176 -0
  189. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +190 -0
  190. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +59 -0
  191. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +45 -0
  192. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +95 -0
  193. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +101 -0
  194. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +138 -0
  195. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +31 -0
  196. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +7 -0
  197. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +56 -0
  198. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +78 -0
  199. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +314 -0
  200. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +107 -0
  201. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +54 -0
  202. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +172 -0
  203. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +258 -0
  204. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +48 -0
  205. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +71 -0
  206. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +288 -0
  207. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +143 -0
  208. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +245 -0
  209. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +992 -0
  210. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +339 -0
  211. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +286 -0
  212. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +371 -0
  213. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +293 -0
  214. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +426 -0
  215. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +152 -0
  216. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +265 -0
  217. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +184 -0
  218. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +57 -0
  219. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +100 -0
  220. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +34 -0
  221. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +124 -0
  222. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +851 -0
  223. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +4932 -0
  224. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +1657 -0
  225. scitex/fts/_fig/_editor/_gui/_flask_editor.py +36 -0
  226. scitex/fts/_fig/_models/_Annotations.py +115 -0
  227. scitex/fts/_fig/_models/_Axes.py +152 -0
  228. scitex/fts/_fig/_models/_Figure.py +138 -0
  229. scitex/fts/_fig/_models/_Guides.py +104 -0
  230. scitex/fts/_fig/_models/_Plot.py +123 -0
  231. scitex/fts/_fig/_models/_Styles.py +245 -0
  232. scitex/fts/_fig/_models/__init__.py +80 -0
  233. scitex/fts/_fig/_models/_plot_types/__init__.py +156 -0
  234. scitex/fts/_fig/_models/_plot_types/_bar.py +43 -0
  235. scitex/fts/_fig/_models/_plot_types/_box.py +38 -0
  236. scitex/fts/_fig/_models/_plot_types/_distribution.py +36 -0
  237. scitex/fts/_fig/_models/_plot_types/_errorbar.py +60 -0
  238. scitex/fts/_fig/_models/_plot_types/_histogram.py +30 -0
  239. scitex/fts/_fig/_models/_plot_types/_image.py +61 -0
  240. scitex/fts/_fig/_models/_plot_types/_line.py +57 -0
  241. scitex/fts/_fig/_models/_plot_types/_scatter.py +30 -0
  242. scitex/fts/_fig/_models/_plot_types/_seaborn.py +121 -0
  243. scitex/fts/_fig/_models/_plot_types/_violin.py +36 -0
  244. scitex/fts/_fig/_utils/__init__.py +129 -0
  245. scitex/fts/_fig/_utils/_auto_layout.py +127 -0
  246. scitex/fts/_fig/_utils/_calc_bounds.py +111 -0
  247. scitex/fts/_fig/_utils/_const_sizes.py +48 -0
  248. scitex/fts/_fig/_utils/_convert_coords.py +77 -0
  249. scitex/fts/_fig/_utils/_get_template.py +178 -0
  250. scitex/fts/_fig/_utils/_normalize.py +73 -0
  251. scitex/fts/_fig/_utils/_plot_layout.py +397 -0
  252. scitex/fts/_fig/_utils/_validate.py +197 -0
  253. scitex/fts/_kinds/__init__.py +45 -0
  254. scitex/fts/_kinds/_figure/__init__.py +19 -0
  255. scitex/fts/_kinds/_figure/_composite.py +345 -0
  256. scitex/fts/_kinds/_plot/__init__.py +25 -0
  257. scitex/fts/_kinds/_plot/_backend/__init__.py +53 -0
  258. scitex/fts/_kinds/_plot/_backend/_export.py +165 -0
  259. scitex/fts/_kinds/_plot/_backend/_parser.py +188 -0
  260. scitex/fts/_kinds/_plot/_backend/_render.py +538 -0
  261. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +46 -0
  262. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +82 -0
  263. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +441 -0
  264. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +52 -0
  265. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +47 -0
  266. scitex/fts/_kinds/_plot/_models/_Annotations.py +115 -0
  267. scitex/fts/_kinds/_plot/_models/_Axes.py +152 -0
  268. scitex/fts/_kinds/_plot/_models/_Figure.py +138 -0
  269. scitex/fts/_kinds/_plot/_models/_Guides.py +104 -0
  270. scitex/fts/_kinds/_plot/_models/_Plot.py +123 -0
  271. scitex/fts/_kinds/_plot/_models/_Styles.py +245 -0
  272. scitex/fts/_kinds/_plot/_models/__init__.py +80 -0
  273. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +156 -0
  274. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +43 -0
  275. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +38 -0
  276. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +36 -0
  277. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +60 -0
  278. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +30 -0
  279. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +61 -0
  280. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +57 -0
  281. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +30 -0
  282. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +121 -0
  283. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +36 -0
  284. scitex/fts/_kinds/_plot/_utils/__init__.py +129 -0
  285. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +127 -0
  286. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +111 -0
  287. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +48 -0
  288. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +77 -0
  289. scitex/fts/_kinds/_plot/_utils/_get_template.py +178 -0
  290. scitex/fts/_kinds/_plot/_utils/_normalize.py +73 -0
  291. scitex/fts/_kinds/_plot/_utils/_plot_layout.py +397 -0
  292. scitex/fts/_kinds/_plot/_utils/_validate.py +197 -0
  293. scitex/fts/_kinds/_shape/__init__.py +141 -0
  294. scitex/fts/_kinds/_stats/__init__.py +56 -0
  295. scitex/fts/_kinds/_stats/_dataclasses/_Stats.py +423 -0
  296. scitex/fts/_kinds/_stats/_dataclasses/__init__.py +48 -0
  297. scitex/fts/_kinds/_table/__init__.py +72 -0
  298. scitex/fts/_kinds/_table/_latex/__init__.py +93 -0
  299. scitex/fts/_kinds/_table/_latex/_editor/__init__.py +11 -0
  300. scitex/fts/_kinds/_table/_latex/_editor/_app.py +725 -0
  301. scitex/fts/_kinds/_table/_latex/_export.py +279 -0
  302. scitex/fts/_kinds/_table/_latex/_figure_exporter.py +153 -0
  303. scitex/fts/_kinds/_table/_latex/_stats_formatter.py +274 -0
  304. scitex/fts/_kinds/_table/_latex/_table_exporter.py +362 -0
  305. scitex/fts/_kinds/_table/_latex/_utils.py +369 -0
  306. scitex/fts/_kinds/_table/_latex/_validator.py +445 -0
  307. scitex/fts/_kinds/_text/__init__.py +77 -0
  308. scitex/fts/_schemas/data_info.schema.json +75 -0
  309. scitex/fts/_schemas/encoding.schema.json +90 -0
  310. scitex/fts/_schemas/node.schema.json +145 -0
  311. scitex/fts/_schemas/render_manifest.schema.json +62 -0
  312. scitex/fts/_schemas/stats.schema.json +132 -0
  313. scitex/fts/_schemas/theme.schema.json +141 -0
  314. scitex/fts/_stats/__init__.py +48 -0
  315. scitex/fts/_stats/_dataclasses/_Stats.py +423 -0
  316. scitex/fts/_stats/_dataclasses/__init__.py +48 -0
  317. scitex/fts/_tables/__init__.py +65 -0
  318. scitex/fts/_tables/_latex/__init__.py +93 -0
  319. scitex/fts/_tables/_latex/_editor/__init__.py +11 -0
  320. scitex/fts/_tables/_latex/_editor/_app.py +725 -0
  321. scitex/fts/_tables/_latex/_export.py +279 -0
  322. scitex/fts/_tables/_latex/_figure_exporter.py +153 -0
  323. scitex/fts/_tables/_latex/_stats_formatter.py +274 -0
  324. scitex/fts/_tables/_latex/_table_exporter.py +362 -0
  325. scitex/fts/_tables/_latex/_utils.py +369 -0
  326. scitex/fts/_tables/_latex/_validator.py +445 -0
  327. scitex/gen/__init__.py +66 -25
  328. scitex/gen/misc.py +28 -0
  329. scitex/io/__init__.py +47 -32
  330. scitex/io/_load.py +87 -36
  331. scitex/io/_load_modules/__init__.py +10 -7
  332. scitex/io/_load_modules/_pandas.py +6 -1
  333. scitex/io/_save.py +299 -1556
  334. scitex/io/_save_modules/__init__.py +76 -19
  335. scitex/io/_save_modules/_figure_utils.py +90 -0
  336. scitex/io/_save_modules/_image_csv.py +497 -0
  337. scitex/io/_save_modules/_legends.py +91 -0
  338. scitex/io/_save_modules/_pltz_bundle.py +356 -0
  339. scitex/io/_save_modules/_pltz_stx.py +536 -0
  340. scitex/io/_save_modules/_stx_bundle.py +104 -0
  341. scitex/io/_save_modules/_symlink.py +96 -0
  342. scitex/io/_save_modules/_yaml.py +1 -1
  343. scitex/io/_save_modules/_zarr.py +64 -18
  344. scitex/io/bundle/README.md +212 -0
  345. scitex/io/bundle/__init__.py +110 -0
  346. scitex/io/{_bundle.py → bundle/_core.py} +168 -97
  347. scitex/io/bundle/_nested.py +713 -0
  348. scitex/io/bundle/_types.py +74 -0
  349. scitex/io/{_zip_bundle.py → bundle/_zip.py} +93 -45
  350. scitex/io/utils/h5_to_zarr.py +1 -1
  351. scitex/logging/__init__.py +108 -13
  352. scitex/logging/_errors.py +508 -0
  353. scitex/logging/_formatters.py +30 -6
  354. scitex/logging/_warnings.py +261 -0
  355. scitex/plt/__init__.py +4 -1
  356. scitex/plt/_figrecipe.py +236 -0
  357. scitex/plt/_subplots/_AxisWrapper.py +6 -0
  358. scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +112 -1
  359. scitex/plt/_subplots/_FigWrapper.py +15 -0
  360. scitex/plt/_subplots/_SubplotsWrapper.py +125 -489
  361. scitex/plt/_subplots/_export_as_csv.py +11 -0
  362. scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +2 -0
  363. scitex/plt/_subplots/_export_as_csv_formatters/_format_pcolormesh.py +66 -0
  364. scitex/plt/_subplots/_export_as_csv_formatters/_format_stackplot.py +62 -0
  365. scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +208 -0
  366. scitex/plt/_subplots/_fonts.py +71 -0
  367. scitex/plt/_subplots/_mm_layout.py +282 -0
  368. scitex/plt/gallery/__init__.py +99 -2
  369. scitex/plt/styles/_plot_postprocess.py +3 -1
  370. scitex/plt/utils/_configure_mpl.py +16 -19
  371. scitex/repro/_RandomStateManager.py +13 -8
  372. scitex/resource/__init__.py +19 -1
  373. scitex/resource/_utils/_get_env_info.py +13 -25
  374. scitex/schema/__init__.py +149 -160
  375. scitex/schema/_encoding.py +273 -0
  376. scitex/schema/_figure_elements.py +406 -0
  377. scitex/schema/_theme.py +360 -0
  378. scitex/schema/_validation.py +0 -98
  379. scitex/scholar/__init__.py +56 -14
  380. scitex/scholar/auth/ScholarAuthManager.py +1 -1
  381. scitex/scholar/auth/__init__.py +11 -2
  382. scitex/scholar/auth/providers/BaseAuthenticator.py +1 -1
  383. scitex/scholar/auth/providers/EZProxyAuthenticator.py +1 -1
  384. scitex/scholar/auth/providers/OpenAthensAuthenticator.py +1 -1
  385. scitex/scholar/auth/providers/ShibbolethAuthenticator.py +1 -1
  386. scitex/scholar/config/ScholarConfig.py +1 -1
  387. scitex/scholar/core/Scholar.py +1 -1
  388. scitex/session/_decorator.py +18 -16
  389. scitex/session/_lifecycle.py +9 -11
  390. scitex/session/template.py +9 -8
  391. scitex/sh/test_sh.py +72 -0
  392. scitex/sh/test_sh_simple.py +61 -0
  393. scitex/stats/__init__.py +221 -97
  394. scitex/stats/_schema.py +21 -22
  395. scitex/stats/descriptive/_circular.py +212 -351
  396. scitex/stats/descriptive/_describe.py +81 -132
  397. scitex/stats/descriptive/_nan.py +205 -433
  398. scitex/stats/descriptive/_real.py +127 -141
  399. scitex/str/_format_plot_text.py +5 -5
  400. scitex/str/_latex.py +26 -84
  401. scitex/str/_latex_fallback.py +53 -47
  402. scitex/web/_search_pubmed.py +5 -4
  403. scitex/writer/tests/test_diff_between.py +451 -0
  404. scitex/writer/tests/test_document_section.py +311 -0
  405. scitex/writer/tests/test_document_workflow.py +393 -0
  406. scitex/writer/tests/test_writer.py +361 -0
  407. scitex/writer/tests/test_writer_integration.py +303 -0
  408. {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/METADATA +368 -183
  409. {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/RECORD +412 -97
  410. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/ARCHITECTURE_EXAMPLE.md +0 -905
  411. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/BULLETIN_BOARD_EXAMPLE.md +0 -99
  412. scitex/scholar/docs/to_claude/guidelines/examples/mgmt/PROJECT_DESCRIPTION_EXAMPLE.md +0 -96
  413. {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/WHEEL +0 -0
  414. {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/entry_points.txt +0 -0
  415. {scitex-2.8.1.dist-info → scitex-2.10.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,360 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: 2025-12-19
3
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/schema/_theme.py
4
+
5
+ """
6
+ Theme Schema - Pure Aesthetics for Visual Presentation.
7
+
8
+ This module defines the theme layer that controls visual appearance
9
+ without affecting scientific meaning. Theme can be changed without
10
+ affecting reproducibility of the data representation.
11
+
12
+ Theme (theme.json) - Aesthetics Only:
13
+ - Colors and color palettes
14
+ - Fonts and typography
15
+ - Line styles and widths
16
+ - Marker styles and sizes
17
+ - Layout and spacing
18
+ """
19
+
20
+ import json
21
+ from dataclasses import asdict, dataclass, field
22
+ from typing import Any, Dict, List, Optional
23
+
24
+ THEME_VERSION = "1.0.0"
25
+
26
+
27
+ @dataclass
28
+ class ColorScheme:
29
+ """
30
+ Color scheme specification.
31
+
32
+ Parameters
33
+ ----------
34
+ mode : str
35
+ Color mode (light, dark, auto)
36
+ background : str
37
+ Figure background color
38
+ axes_bg : str
39
+ Axes background color
40
+ text : str
41
+ Text color
42
+ spine : str
43
+ Axes spine color
44
+ tick : str
45
+ Tick mark color
46
+ grid : str
47
+ Grid line color
48
+ palette : str, optional
49
+ Named color palette for traces
50
+ """
51
+
52
+ mode: str = "light"
53
+ background: str = "transparent"
54
+ axes_bg: str = "white"
55
+ text: str = "black"
56
+ spine: str = "black"
57
+ tick: str = "black"
58
+ grid: str = "#cccccc"
59
+ palette: Optional[str] = None
60
+
61
+ def to_dict(self) -> Dict[str, Any]:
62
+ result = {
63
+ "mode": self.mode,
64
+ "background": self.background,
65
+ "axes_bg": self.axes_bg,
66
+ "text": self.text,
67
+ "spine": self.spine,
68
+ "tick": self.tick,
69
+ "grid": self.grid,
70
+ }
71
+ if self.palette:
72
+ result["palette"] = self.palette
73
+ return result
74
+
75
+ @classmethod
76
+ def from_dict(cls, data: Dict[str, Any]) -> "ColorScheme":
77
+ return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
78
+
79
+
80
+ @dataclass
81
+ class Typography:
82
+ """
83
+ Typography specification.
84
+
85
+ Parameters
86
+ ----------
87
+ family : str
88
+ Font family
89
+ size_pt : float
90
+ Base font size in points
91
+ title_size_pt : float
92
+ Title font size in points
93
+ label_size_pt : float
94
+ Axis label font size in points
95
+ tick_size_pt : float
96
+ Tick label font size in points
97
+ legend_size_pt : float
98
+ Legend font size in points
99
+ weight : str
100
+ Font weight (normal, bold, etc.)
101
+ """
102
+
103
+ family: str = "sans-serif"
104
+ size_pt: float = 7.0
105
+ title_size_pt: float = 8.0
106
+ label_size_pt: float = 7.0
107
+ tick_size_pt: float = 6.0
108
+ legend_size_pt: float = 6.0
109
+ weight: str = "normal"
110
+
111
+ def to_dict(self) -> Dict[str, Any]:
112
+ return asdict(self)
113
+
114
+ @classmethod
115
+ def from_dict(cls, data: Dict[str, Any]) -> "Typography":
116
+ return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
117
+
118
+
119
+ @dataclass
120
+ class LineDefaults:
121
+ """Default line style settings."""
122
+
123
+ width: float = 1.0
124
+ style: str = "-" # solid
125
+ alpha: float = 1.0
126
+
127
+ def to_dict(self) -> Dict[str, Any]:
128
+ return asdict(self)
129
+
130
+ @classmethod
131
+ def from_dict(cls, data: Dict[str, Any]) -> "LineDefaults":
132
+ return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
133
+
134
+
135
+ @dataclass
136
+ class MarkerDefaults:
137
+ """Default marker style settings."""
138
+
139
+ size: float = 6.0
140
+ style: str = "o"
141
+ edge_width: float = 0.5
142
+ edge_color: str = "auto" # auto means same as fill or black
143
+
144
+ def to_dict(self) -> Dict[str, Any]:
145
+ return asdict(self)
146
+
147
+ @classmethod
148
+ def from_dict(cls, data: Dict[str, Any]) -> "MarkerDefaults":
149
+ return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
150
+
151
+
152
+ @dataclass
153
+ class TraceStyle:
154
+ """
155
+ Per-trace style overrides.
156
+
157
+ Parameters
158
+ ----------
159
+ trace_id : str
160
+ ID of the trace this style applies to
161
+ color : str, optional
162
+ Trace color
163
+ linewidth : float, optional
164
+ Line width
165
+ linestyle : str, optional
166
+ Line style
167
+ marker : str, optional
168
+ Marker style
169
+ markersize : float, optional
170
+ Marker size
171
+ alpha : float, optional
172
+ Opacity
173
+ """
174
+
175
+ trace_id: str
176
+ color: Optional[str] = None
177
+ linewidth: Optional[float] = None
178
+ linestyle: Optional[str] = None
179
+ marker: Optional[str] = None
180
+ markersize: Optional[float] = None
181
+ alpha: Optional[float] = None
182
+
183
+ def to_dict(self) -> Dict[str, Any]:
184
+ result = {"trace_id": self.trace_id}
185
+ for name in [
186
+ "color",
187
+ "linewidth",
188
+ "linestyle",
189
+ "marker",
190
+ "markersize",
191
+ "alpha",
192
+ ]:
193
+ val = getattr(self, name)
194
+ if val is not None:
195
+ result[name] = val
196
+ return result
197
+
198
+ @classmethod
199
+ def from_dict(cls, data: Dict[str, Any]) -> "TraceStyle":
200
+ return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
201
+
202
+
203
+ @dataclass
204
+ class LegendStyle:
205
+ """Legend styling options."""
206
+
207
+ visible: bool = True
208
+ location: str = "best"
209
+ frameon: bool = True
210
+ ncols: int = 1
211
+ title: Optional[str] = None
212
+
213
+ def to_dict(self) -> Dict[str, Any]:
214
+ result = {
215
+ "visible": self.visible,
216
+ "location": self.location,
217
+ "frameon": self.frameon,
218
+ "ncols": self.ncols,
219
+ }
220
+ if self.title:
221
+ result["title"] = self.title
222
+ return result
223
+
224
+ @classmethod
225
+ def from_dict(cls, data: Dict[str, Any]) -> "LegendStyle":
226
+ if isinstance(data, bool):
227
+ return cls(visible=data)
228
+ return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
229
+
230
+
231
+ @dataclass
232
+ class PlotTheme:
233
+ """
234
+ Complete theme specification for a plot.
235
+
236
+ Stored in theme.json. Contains pure aesthetics that can be
237
+ changed without affecting scientific interpretation.
238
+
239
+ Parameters
240
+ ----------
241
+ colors : ColorScheme
242
+ Color scheme settings
243
+ typography : Typography
244
+ Font settings
245
+ line : LineDefaults
246
+ Default line style
247
+ marker : MarkerDefaults
248
+ Default marker style
249
+ traces : list of TraceStyle
250
+ Per-trace style overrides
251
+ legend : LegendStyle
252
+ Legend styling
253
+ grid : bool
254
+ Whether to show grid
255
+ """
256
+
257
+ colors: ColorScheme = field(default_factory=ColorScheme)
258
+ typography: Typography = field(default_factory=Typography)
259
+ line: LineDefaults = field(default_factory=LineDefaults)
260
+ marker: MarkerDefaults = field(default_factory=MarkerDefaults)
261
+ traces: List[TraceStyle] = field(default_factory=list)
262
+ legend: LegendStyle = field(default_factory=LegendStyle)
263
+ grid: bool = False
264
+
265
+ # Schema metadata
266
+ scitex_schema: str = "scitex.plt.theme"
267
+ scitex_schema_version: str = THEME_VERSION
268
+
269
+ def to_dict(self) -> Dict[str, Any]:
270
+ return {
271
+ "schema": {
272
+ "name": self.scitex_schema,
273
+ "version": self.scitex_schema_version,
274
+ },
275
+ "colors": self.colors.to_dict(),
276
+ "typography": self.typography.to_dict(),
277
+ "line": self.line.to_dict(),
278
+ "marker": self.marker.to_dict(),
279
+ "traces": [t.to_dict() for t in self.traces],
280
+ "legend": self.legend.to_dict(),
281
+ "grid": self.grid,
282
+ }
283
+
284
+ def to_json(self, indent: int = 2) -> str:
285
+ return json.dumps(self.to_dict(), indent=indent)
286
+
287
+ @classmethod
288
+ def from_dict(cls, data: Dict[str, Any]) -> "PlotTheme":
289
+ return cls(
290
+ colors=ColorScheme.from_dict(data.get("colors", {})),
291
+ typography=Typography.from_dict(data.get("typography", {})),
292
+ line=LineDefaults.from_dict(data.get("line", {})),
293
+ marker=MarkerDefaults.from_dict(data.get("marker", {})),
294
+ traces=[TraceStyle.from_dict(t) for t in data.get("traces", [])],
295
+ legend=LegendStyle.from_dict(data.get("legend", {})),
296
+ grid=data.get("grid", False),
297
+ )
298
+
299
+ @classmethod
300
+ def from_json(cls, json_str: str) -> "PlotTheme":
301
+ return cls.from_dict(json.loads(json_str))
302
+
303
+ @classmethod
304
+ def from_style(cls, style: dict) -> "PlotTheme":
305
+ """
306
+ Create theme from PlotStyle dict for backward compatibility.
307
+ """
308
+ theme_data = style.get("theme", {})
309
+ font_data = style.get("font", {})
310
+ size_data = style.get("size", {})
311
+
312
+ return cls(
313
+ colors=ColorScheme(
314
+ mode=theme_data.get("mode", "light"),
315
+ background=theme_data.get("colors", {}).get(
316
+ "background", "transparent"
317
+ ),
318
+ axes_bg=theme_data.get("colors", {}).get("axes_bg", "white"),
319
+ text=theme_data.get("colors", {}).get("text", "black"),
320
+ spine=theme_data.get("colors", {}).get("spine", "black"),
321
+ tick=theme_data.get("colors", {}).get("tick", "black"),
322
+ palette=theme_data.get("palette"),
323
+ ),
324
+ typography=Typography(
325
+ family=font_data.get("family", "sans-serif"),
326
+ size_pt=font_data.get("size_pt", 7.0),
327
+ title_size_pt=font_data.get("title_size_pt", 8.0),
328
+ label_size_pt=font_data.get("label_size_pt", 7.0),
329
+ tick_size_pt=font_data.get("tick_size_pt", 6.0),
330
+ ),
331
+ traces=[
332
+ TraceStyle(
333
+ trace_id=t.get("trace_id", ""),
334
+ color=t.get("color"),
335
+ linewidth=t.get("linewidth"),
336
+ linestyle=t.get("linestyle"),
337
+ marker=t.get("marker"),
338
+ markersize=t.get("markersize"),
339
+ alpha=t.get("alpha"),
340
+ )
341
+ for t in style.get("traces", [])
342
+ ],
343
+ legend=LegendStyle.from_dict(style.get("legend", {})),
344
+ grid=style.get("grid", False),
345
+ )
346
+
347
+
348
+ __all__ = [
349
+ "THEME_VERSION",
350
+ "ColorScheme",
351
+ "Typography",
352
+ "LineDefaults",
353
+ "MarkerDefaults",
354
+ "TraceStyle",
355
+ "LegendStyle",
356
+ "PlotTheme",
357
+ ]
358
+
359
+
360
+ # EOF
@@ -439,103 +439,6 @@ def validate_stat_result(stat_data: Dict[str, Any]) -> bool:
439
439
  return True
440
440
 
441
441
 
442
- # =============================================================================
443
- # Canvas Validation
444
- # =============================================================================
445
-
446
-
447
- def validate_canvas(canvas_data: Dict[str, Any]) -> bool:
448
- """
449
- Validate a canvas specification.
450
-
451
- Parameters
452
- ----------
453
- canvas_data : Dict[str, Any]
454
- Canvas specification dictionary
455
-
456
- Returns
457
- -------
458
- bool
459
- True if valid
460
-
461
- Raises
462
- ------
463
- ValidationError
464
- If validation fails
465
- """
466
- # canvas_name is required
467
- if "canvas_name" not in canvas_data:
468
- raise ValidationError(
469
- "Missing required field: canvas_name",
470
- field="canvas_name",
471
- )
472
-
473
- # Validate size
474
- if "size" in canvas_data:
475
- size = canvas_data["size"]
476
- if not isinstance(size, dict):
477
- raise ValidationError(
478
- "size must be a dictionary",
479
- field="size",
480
- value=type(size).__name__,
481
- )
482
-
483
- width = size.get("width_mm", 0)
484
- height = size.get("height_mm", 0)
485
-
486
- if width <= 0:
487
- raise ValidationError(
488
- "width_mm must be positive",
489
- field="size.width_mm",
490
- value=width,
491
- )
492
-
493
- if height <= 0:
494
- raise ValidationError(
495
- "height_mm must be positive",
496
- field="size.height_mm",
497
- value=height,
498
- )
499
-
500
- # Validate panels
501
- if "panels" in canvas_data:
502
- if not isinstance(canvas_data["panels"], list):
503
- raise ValidationError(
504
- "panels must be a list",
505
- field="panels",
506
- value=type(canvas_data["panels"]).__name__,
507
- )
508
-
509
- # Check for duplicate panel names
510
- panel_names = set()
511
- for i, panel in enumerate(canvas_data["panels"]):
512
- name = panel.get("name")
513
- if not name:
514
- raise ValidationError(
515
- f"Panel at index {i} is missing 'name'",
516
- field=f"panels[{i}].name",
517
- )
518
-
519
- if name in panel_names:
520
- raise ValidationError(
521
- f"Duplicate panel name: {name}",
522
- field=f"panels[{i}].name",
523
- value=name,
524
- )
525
- panel_names.add(name)
526
-
527
- # Validate panel type
528
- panel_type = panel.get("type", "image")
529
- if panel_type not in {"scitex", "image"}:
530
- raise ValidationError(
531
- f"Invalid panel type: {panel_type}",
532
- field=f"panels[{i}].type",
533
- value=panel_type,
534
- )
535
-
536
- return True
537
-
538
-
539
442
  # =============================================================================
540
443
  # Color Validation
541
444
  # =============================================================================
@@ -582,7 +485,6 @@ __all__ = [
582
485
  "validate_axes",
583
486
  "validate_plot",
584
487
  "validate_stat_result",
585
- "validate_canvas",
586
488
  "validate_color",
587
489
  ]
588
490
 
@@ -13,21 +13,63 @@ Quick Start:
13
13
  scholar = Scholar()
14
14
  papers = scholar.search("deep learning")
15
15
  papers.save("pac.bib")
16
- """
17
16
 
18
- # # Import main class
19
- # from .core._Scholar import Scholar, search, search_quick, enrich_bibtex
17
+ Installation:
18
+ pip install scitex[scholar]
19
+ """
20
20
 
21
- # Import configuration
22
- from scitex.scholar.config import ScholarConfig
23
- from scitex.scholar.auth import ScholarAuthManager
24
- from scitex.scholar.browser import ScholarBrowserManager
25
- from scitex.scholar.metadata_engines import ScholarEngine
26
- from scitex.scholar.url_finder import ScholarURLFinder
27
- from scitex.scholar.pdf_download import ScholarPDFDownloader
28
- from scitex.scholar.storage import ScholarLibrary
29
- from scitex.scholar.core import Paper, Papers, Scholar
30
- from . import utils
21
+ # Check for missing dependencies and warn user
22
+ from scitex._install_guide import warn_module_deps
23
+
24
+ _missing = warn_module_deps("scholar")
25
+
26
+ # Import configuration - wrap all in try/except for graceful degradation
27
+ try:
28
+ from scitex.scholar.auth import ScholarAuthManager
29
+ except ImportError:
30
+ ScholarAuthManager = None
31
+
32
+ try:
33
+ from scitex.scholar.browser import ScholarBrowserManager
34
+ except ImportError:
35
+ ScholarBrowserManager = None
36
+
37
+ try:
38
+ from scitex.scholar.config import ScholarConfig
39
+ except ImportError:
40
+ ScholarConfig = None
41
+
42
+ try:
43
+ from scitex.scholar.core import Paper, Papers, Scholar
44
+ except ImportError:
45
+ Paper = None
46
+ Papers = None
47
+ Scholar = None
48
+
49
+ try:
50
+ from scitex.scholar.metadata_engines import ScholarEngine
51
+ except ImportError:
52
+ ScholarEngine = None
53
+
54
+ try:
55
+ from scitex.scholar.pdf_download import ScholarPDFDownloader
56
+ except ImportError:
57
+ ScholarPDFDownloader = None
58
+
59
+ try:
60
+ from scitex.scholar.storage import ScholarLibrary
61
+ except ImportError:
62
+ ScholarLibrary = None
63
+
64
+ try:
65
+ from scitex.scholar.url_finder import ScholarURLFinder
66
+ except ImportError:
67
+ ScholarURLFinder = None
68
+
69
+ try:
70
+ from . import utils
71
+ except ImportError:
72
+ utils = None
31
73
 
32
74
  __all__ = [
33
75
  "ScholarConfig",
@@ -240,7 +282,7 @@ __all__ = [
240
282
  # # else:
241
283
  # # return Scholar
242
284
 
243
- # # from scitex.errors import ScholarError
285
+ # # from scitex.logging import ScholarError
244
286
  # # raise ScholarError(
245
287
  # # f"Module attribute not found: '{name}'",
246
288
  # # context={"module": __name__, "attribute": name},
@@ -23,7 +23,7 @@ interface for authentication operations.
23
23
  from typing import Any, Dict, List, Optional
24
24
 
25
25
  from scitex import logging
26
- from scitex.errors import AuthenticationError
26
+ from scitex.logging import AuthenticationError
27
27
  from scitex.scholar.config import ScholarConfig
28
28
 
29
29
  from .providers.BaseAuthenticator import BaseAuthenticator
@@ -1,7 +1,16 @@
1
1
  """Authentication module for Scholar."""
2
2
 
3
- from .ScholarAuthManager import ScholarAuthManager
4
- from .core.AuthenticationGateway import AuthenticationGateway, URLContext
3
+ # Optional: requires browser dependencies (playwright, aiohttp)
4
+ try:
5
+ from .ScholarAuthManager import ScholarAuthManager
6
+ except ImportError:
7
+ ScholarAuthManager = None
8
+
9
+ try:
10
+ from .core.AuthenticationGateway import AuthenticationGateway, URLContext
11
+ except ImportError:
12
+ AuthenticationGateway = None
13
+ URLContext = None
5
14
 
6
15
  __all__ = [
7
16
  "ScholarAuthManager",
@@ -23,7 +23,7 @@ from typing import Any, Dict, List, Optional
23
23
 
24
24
  from scitex import logging
25
25
 
26
- from scitex.errors import AuthenticationError
26
+ from scitex.logging import AuthenticationError
27
27
 
28
28
  """Logger"""
29
29
  logger = logging.getLogger(__name__)
@@ -35,7 +35,7 @@ except ImportError:
35
35
  Page = None
36
36
  Browser = None
37
37
 
38
- from scitex.errors import ScholarError
38
+ from scitex.logging import ScholarError
39
39
 
40
40
  from .BaseAuthenticator import BaseAuthenticator
41
41
 
@@ -29,7 +29,7 @@ from typing import Any, Dict, List, Optional
29
29
  from playwright.async_api import async_playwright
30
30
 
31
31
  from scitex import logging
32
- from scitex.errors import ScholarError
32
+ from scitex.logging import ScholarError
33
33
  from scitex.scholar.config import ScholarConfig
34
34
 
35
35
  from ..core.BrowserAuthenticator import BrowserAuthenticator
@@ -28,7 +28,7 @@ except ImportError:
28
28
  Page = None
29
29
  Browser = None
30
30
 
31
- from scitex.errors import ScholarError
31
+ from scitex.logging import ScholarError
32
32
  from .BaseAuthenticator import BaseAuthenticator
33
33
 
34
34
  logger = logging.getLogger(__name__)
@@ -18,7 +18,7 @@ from typing import Optional, Union
18
18
 
19
19
  import yaml
20
20
 
21
- from scitex.errors import ScholarError
21
+ from scitex.logging import ScholarError
22
22
  from scitex.logging import getLogger
23
23
 
24
24
  from .core._CascadeConfig import CascadeConfig
@@ -35,7 +35,7 @@ from scitex import logging
35
35
  import shutil
36
36
 
37
37
  # PDF extraction is now handled by scitex.io
38
- from scitex.errors import ScholarError
38
+ from scitex.logging import ScholarError
39
39
  from scitex.scholar.config import ScholarConfig
40
40
 
41
41
  # Updated imports for current architecture