scitex 2.7.3__py3-none-any.whl → 2.10.0__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.
- scitex/__init__.py +15 -7
- scitex/__version__.py +1 -2
- scitex/_install_guide.py +250 -0
- scitex/_optional_deps.py +206 -39
- scitex/ai/_gen_ai/_Groq.py +2 -4
- scitex/ai/_gen_ai/_OpenAI.py +5 -2
- scitex/ai/_gen_ai/_Perplexity.py +20 -6
- scitex/audio/__init__.py +24 -15
- scitex/audio/_cross_process_lock.py +139 -0
- scitex/audio/_mcp_handlers.py +256 -0
- scitex/audio/_mcp_tool_schemas.py +203 -0
- scitex/audio/engines/elevenlabs_engine.py +5 -2
- scitex/audio/mcp_server.py +98 -457
- scitex/bridge/__init__.py +30 -19
- scitex/bridge/_figrecipe.py +245 -0
- scitex/bridge/_helpers.py +2 -1
- scitex/bridge/_plt_vis.py +23 -10
- scitex/bridge/_stats_plt.py +18 -5
- scitex/bridge/_stats_vis.py +16 -2
- scitex/browser/__init__.py +84 -44
- scitex/browser/automation/__init__.py +5 -1
- scitex/browser/core/BrowserMixin.py +17 -4
- scitex/browser/core/__init__.py +11 -2
- scitex/browser/remote/CaptchaHandler.py +1 -1
- scitex/browser/remote/ZenRowsAPIClient.py +1 -1
- scitex/capture/grid.py +487 -0
- scitex/capture/mcp_handlers.py +401 -0
- scitex/capture/mcp_tool_defs.py +192 -0
- scitex/capture/mcp_tools.py +241 -0
- scitex/capture/mcp_utils.py +30 -0
- scitex/cli/convert.py +421 -0
- scitex/cli/main.py +6 -4
- scitex/datetime/__init__.py +46 -0
- scitex/datetime/_linspace.py +100 -0
- scitex/datetime/_normalize_timestamp.py +306 -0
- scitex/db/_delete_duplicates.py +4 -4
- scitex/db/_sqlite3/_delete_duplicates.py +11 -2
- scitex/dev/plt/__init__.py +61 -62
- scitex/dev/plt/demo_plotters/__init__.py +0 -0
- scitex/dev/plt/demo_plotters/plot_mpl_axhline.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_axhspan.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_axvline.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_axvspan.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_bar.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_barh.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_boxplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_contour.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_contourf.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_errorbar.py +30 -0
- scitex/dev/plt/demo_plotters/plot_mpl_eventplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_fill.py +30 -0
- scitex/dev/plt/demo_plotters/plot_mpl_fill_between.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_hexbin.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_hist.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_hist2d.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_imshow.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_pcolormesh.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_pie.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_plot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_quiver.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_scatter.py +28 -0
- scitex/dev/plt/demo_plotters/plot_mpl_stackplot.py +31 -0
- scitex/dev/plt/demo_plotters/plot_mpl_stem.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_step.py +29 -0
- scitex/dev/plt/demo_plotters/plot_mpl_violinplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_sns_barplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_boxplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_heatmap.py +28 -0
- scitex/dev/plt/demo_plotters/plot_sns_histplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_kdeplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_lineplot.py +31 -0
- scitex/dev/plt/demo_plotters/plot_sns_scatterplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_stripplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_swarmplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_sns_violinplot.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_bar.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_barh.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_box.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_boxplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_conf_mat.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_contour.py +31 -0
- scitex/dev/plt/demo_plotters/plot_stx_ecdf.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_errorbar.py +30 -0
- scitex/dev/plt/demo_plotters/plot_stx_fill_between.py +31 -0
- scitex/dev/plt/demo_plotters/plot_stx_fillv.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_heatmap.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_image.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_imshow.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_joyplot.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_kde.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_line.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_mean_ci.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_mean_std.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_median_iqr.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_raster.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_rectangle.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_scatter.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_shaded_line.py +29 -0
- scitex/dev/plt/demo_plotters/plot_stx_violin.py +28 -0
- scitex/dev/plt/demo_plotters/plot_stx_violinplot.py +28 -0
- scitex/dev/plt/mpl/get_dir_ax.py +46 -0
- scitex/dev/plt/mpl/get_signatures.py +176 -0
- scitex/dev/plt/mpl/get_signatures_details.py +522 -0
- scitex/dev/plt/plot_mpl_axhline.py +0 -0
- scitex/dev/plt/plot_mpl_axhspan.py +0 -0
- scitex/dev/plt/plot_mpl_axvline.py +0 -0
- scitex/dev/plt/plot_mpl_axvspan.py +0 -0
- scitex/dev/plt/plot_mpl_bar.py +0 -0
- scitex/dev/plt/plot_mpl_barh.py +0 -0
- scitex/dev/plt/plot_mpl_boxplot.py +0 -0
- scitex/dev/plt/plot_mpl_contour.py +0 -0
- scitex/dev/plt/plot_mpl_contourf.py +0 -0
- scitex/dev/plt/plot_mpl_errorbar.py +0 -0
- scitex/dev/plt/plot_mpl_eventplot.py +0 -0
- scitex/dev/plt/plot_mpl_fill.py +0 -0
- scitex/dev/plt/plot_mpl_fill_between.py +0 -0
- scitex/dev/plt/plot_mpl_hexbin.py +0 -0
- scitex/dev/plt/plot_mpl_hist.py +0 -0
- scitex/dev/plt/plot_mpl_hist2d.py +0 -0
- scitex/dev/plt/plot_mpl_imshow.py +0 -0
- scitex/dev/plt/plot_mpl_pcolormesh.py +0 -0
- scitex/dev/plt/plot_mpl_pie.py +0 -0
- scitex/dev/plt/plot_mpl_plot.py +0 -0
- scitex/dev/plt/plot_mpl_quiver.py +0 -0
- scitex/dev/plt/plot_mpl_scatter.py +0 -0
- scitex/dev/plt/plot_mpl_stackplot.py +0 -0
- scitex/dev/plt/plot_mpl_stem.py +0 -0
- scitex/dev/plt/plot_mpl_step.py +0 -0
- scitex/dev/plt/plot_mpl_violinplot.py +0 -0
- scitex/dev/plt/plot_sns_barplot.py +0 -0
- scitex/dev/plt/plot_sns_boxplot.py +0 -0
- scitex/dev/plt/plot_sns_heatmap.py +0 -0
- scitex/dev/plt/plot_sns_histplot.py +0 -0
- scitex/dev/plt/plot_sns_kdeplot.py +0 -0
- scitex/dev/plt/plot_sns_lineplot.py +0 -0
- scitex/dev/plt/plot_sns_scatterplot.py +0 -0
- scitex/dev/plt/plot_sns_stripplot.py +0 -0
- scitex/dev/plt/plot_sns_swarmplot.py +0 -0
- scitex/dev/plt/plot_sns_violinplot.py +0 -0
- scitex/dev/plt/plot_stx_bar.py +0 -0
- scitex/dev/plt/plot_stx_barh.py +0 -0
- scitex/dev/plt/plot_stx_box.py +0 -0
- scitex/dev/plt/plot_stx_boxplot.py +0 -0
- scitex/dev/plt/plot_stx_conf_mat.py +0 -0
- scitex/dev/plt/plot_stx_contour.py +0 -0
- scitex/dev/plt/plot_stx_ecdf.py +0 -0
- scitex/dev/plt/plot_stx_errorbar.py +0 -0
- scitex/dev/plt/plot_stx_fill_between.py +0 -0
- scitex/dev/plt/plot_stx_fillv.py +0 -0
- scitex/dev/plt/plot_stx_heatmap.py +0 -0
- scitex/dev/plt/plot_stx_image.py +0 -0
- scitex/dev/plt/plot_stx_imshow.py +0 -0
- scitex/dev/plt/plot_stx_joyplot.py +0 -0
- scitex/dev/plt/plot_stx_kde.py +0 -0
- scitex/dev/plt/plot_stx_line.py +0 -0
- scitex/dev/plt/plot_stx_mean_ci.py +0 -0
- scitex/dev/plt/plot_stx_mean_std.py +0 -0
- scitex/dev/plt/plot_stx_median_iqr.py +0 -0
- scitex/dev/plt/plot_stx_raster.py +0 -0
- scitex/dev/plt/plot_stx_rectangle.py +0 -0
- scitex/dev/plt/plot_stx_scatter.py +0 -0
- scitex/dev/plt/plot_stx_shaded_line.py +0 -0
- scitex/dev/plt/plot_stx_violin.py +0 -0
- scitex/dev/plt/plot_stx_violinplot.py +0 -0
- scitex/diagram/README.md +197 -0
- scitex/diagram/__init__.py +48 -0
- scitex/diagram/_compile.py +312 -0
- scitex/diagram/_diagram.py +355 -0
- scitex/diagram/_presets.py +173 -0
- scitex/diagram/_schema.py +182 -0
- scitex/diagram/_split.py +278 -0
- scitex/dict/_pop_keys.py +1 -7
- scitex/dsp/__init__.py +15 -10
- scitex/dsp/add_noise.py +5 -2
- scitex/dsp/example.py +35 -22
- scitex/dsp/filt.py +8 -3
- scitex/dsp/reference.py +3 -2
- scitex/dsp/utils/__init__.py +2 -1
- scitex/dsp/utils/_differential_bandpass_filters.py +14 -4
- scitex/dt/__init__.py +39 -2
- scitex/errors.py +82 -521
- scitex/fig/__init__.py +4 -4
- scitex/fig/editor/__init__.py +5 -2
- scitex/fig/editor/_dearpygui_editor.py +1 -1
- scitex/fig/editor/_mpl_editor.py +1 -1
- scitex/fig/editor/_qt_editor.py +1 -1
- scitex/fig/editor/_tkinter_editor.py +1 -1
- scitex/fig/editor/edit/__init__.py +50 -0
- scitex/fig/editor/edit/backend_detector.py +109 -0
- scitex/fig/editor/edit/bundle_resolver.py +240 -0
- scitex/fig/editor/edit/editor_launcher.py +239 -0
- scitex/fig/editor/edit/manual_handler.py +53 -0
- scitex/fig/editor/edit/panel_loader.py +232 -0
- scitex/fig/editor/edit/path_resolver.py +67 -0
- scitex/fig/editor/flask_editor/_bbox.py +23 -0
- scitex/fig/editor/flask_editor/_core.py +908 -103
- scitex/fig/editor/flask_editor/_renderer.py +74 -0
- scitex/fig/editor/flask_editor/static/css/base/reset.css +41 -0
- scitex/fig/editor/flask_editor/static/css/base/typography.css +16 -0
- scitex/fig/editor/flask_editor/static/css/base/variables.css +85 -0
- scitex/fig/editor/flask_editor/static/css/components/buttons.css +217 -0
- scitex/fig/editor/flask_editor/static/css/components/context-menu.css +93 -0
- scitex/fig/editor/flask_editor/static/css/components/dropdown.css +57 -0
- scitex/fig/editor/flask_editor/static/css/components/forms.css +112 -0
- scitex/fig/editor/flask_editor/static/css/components/modal.css +59 -0
- scitex/fig/editor/flask_editor/static/css/components/sections.css +212 -0
- scitex/fig/editor/flask_editor/static/css/features/canvas.css +176 -0
- scitex/fig/editor/flask_editor/static/css/features/element-inspector.css +190 -0
- scitex/fig/editor/flask_editor/static/css/features/loading.css +59 -0
- scitex/fig/editor/flask_editor/static/css/features/overlay.css +45 -0
- scitex/fig/editor/flask_editor/static/css/features/panel-grid.css +95 -0
- scitex/fig/editor/flask_editor/static/css/features/selection.css +101 -0
- scitex/fig/editor/flask_editor/static/css/features/statistics.css +138 -0
- scitex/fig/editor/flask_editor/static/css/index.css +31 -0
- scitex/fig/editor/flask_editor/static/css/layout/container.css +7 -0
- scitex/fig/editor/flask_editor/static/css/layout/controls.css +56 -0
- scitex/fig/editor/flask_editor/static/css/layout/preview.css +78 -0
- scitex/fig/editor/flask_editor/static/js/alignment/axis.js +314 -0
- scitex/fig/editor/flask_editor/static/js/alignment/basic.js +107 -0
- scitex/fig/editor/flask_editor/static/js/alignment/distribute.js +54 -0
- scitex/fig/editor/flask_editor/static/js/canvas/canvas.js +172 -0
- scitex/fig/editor/flask_editor/static/js/canvas/dragging.js +258 -0
- scitex/fig/editor/flask_editor/static/js/canvas/resize.js +48 -0
- scitex/fig/editor/flask_editor/static/js/canvas/selection.js +71 -0
- scitex/fig/editor/flask_editor/static/js/core/api.js +288 -0
- scitex/fig/editor/flask_editor/static/js/core/state.js +143 -0
- scitex/fig/editor/flask_editor/static/js/core/utils.js +245 -0
- scitex/fig/editor/flask_editor/static/js/dev/element-inspector.js +992 -0
- scitex/fig/editor/flask_editor/static/js/editor/bbox.js +339 -0
- scitex/fig/editor/flask_editor/static/js/editor/element-drag.js +286 -0
- scitex/fig/editor/flask_editor/static/js/editor/overlay.js +371 -0
- scitex/fig/editor/flask_editor/static/js/editor/preview.js +293 -0
- scitex/fig/editor/flask_editor/static/js/main.js +426 -0
- scitex/fig/editor/flask_editor/static/js/shortcuts/context-menu.js +152 -0
- scitex/fig/editor/flask_editor/static/js/shortcuts/keyboard.js +265 -0
- scitex/fig/editor/flask_editor/static/js/ui/controls.js +184 -0
- scitex/fig/editor/flask_editor/static/js/ui/download.js +57 -0
- scitex/fig/editor/flask_editor/static/js/ui/help.js +100 -0
- scitex/fig/editor/flask_editor/static/js/ui/theme.js +34 -0
- scitex/fig/editor/flask_editor/templates/__init__.py +95 -5
- scitex/fig/editor/flask_editor/templates/_html.py +27 -9
- scitex/fig/editor/flask_editor/templates/_scripts.py +1928 -131
- scitex/fig/editor/flask_editor/templates/_styles.py +363 -51
- scitex/fig/io/_bundle.py +104 -19
- scitex/fts/README.md +262 -0
- scitex/fts/TODO.md +66 -0
- scitex/fts/__init__.py +90 -0
- scitex/fts/_bundle/README_IN_BUNDLE.md +102 -0
- scitex/fts/_bundle/_FTS.py +657 -0
- scitex/fts/_bundle/__init__.py +38 -0
- scitex/fts/_bundle/_children.py +216 -0
- scitex/fts/_bundle/_conversion/__init__.py +15 -0
- scitex/fts/_bundle/_conversion/_bundle2dict.py +44 -0
- scitex/fts/_bundle/_conversion/_dict2bundle.py +50 -0
- scitex/fts/_bundle/_dataclasses/_Axes.py +57 -0
- scitex/fts/_bundle/_dataclasses/_BBox.py +54 -0
- scitex/fts/_bundle/_dataclasses/_ColumnDef.py +72 -0
- scitex/fts/_bundle/_dataclasses/_DataFormat.py +40 -0
- scitex/fts/_bundle/_dataclasses/_DataInfo.py +135 -0
- scitex/fts/_bundle/_dataclasses/_DataSource.py +44 -0
- scitex/fts/_bundle/_dataclasses/_Node.py +319 -0
- scitex/fts/_bundle/_dataclasses/_NodeRefs.py +45 -0
- scitex/fts/_bundle/_dataclasses/_SizeMM.py +38 -0
- scitex/fts/_bundle/_dataclasses/__init__.py +35 -0
- scitex/fts/_bundle/_extractors/__init__.py +32 -0
- scitex/fts/_bundle/_extractors/_extract_bar.py +131 -0
- scitex/fts/_bundle/_extractors/_extract_line.py +71 -0
- scitex/fts/_bundle/_extractors/_extract_scatter.py +79 -0
- scitex/fts/_bundle/_loader.py +134 -0
- scitex/fts/_bundle/_mpl_helpers.py +389 -0
- scitex/fts/_bundle/_saver.py +269 -0
- scitex/fts/_bundle/_storage.py +200 -0
- scitex/fts/_bundle/_utils/__init__.py +55 -0
- scitex/fts/_bundle/_utils/_const.py +26 -0
- scitex/fts/_bundle/_utils/_errors.py +73 -0
- scitex/fts/_bundle/_utils/_generate.py +21 -0
- scitex/fts/_bundle/_utils/_types.py +76 -0
- scitex/fts/_bundle/_validation.py +434 -0
- scitex/fts/_bundle/_zipbundle.py +165 -0
- scitex/fts/_fig/__init__.py +22 -0
- scitex/fts/_fig/_backend/__init__.py +53 -0
- scitex/fts/_fig/_backend/_export.py +165 -0
- scitex/fts/_fig/_backend/_parser.py +188 -0
- scitex/fts/_fig/_backend/_render.py +538 -0
- scitex/fts/_fig/_composite.py +345 -0
- scitex/fts/_fig/_dataclasses/_ChannelEncoding.py +46 -0
- scitex/fts/_fig/_dataclasses/_Encoding.py +82 -0
- scitex/fts/_fig/_dataclasses/_Theme.py +441 -0
- scitex/fts/_fig/_dataclasses/_TraceEncoding.py +52 -0
- scitex/fts/_fig/_dataclasses/__init__.py +47 -0
- scitex/fts/_fig/_editor/__init__.py +14 -0
- scitex/fts/_fig/_editor/_cui/__init__.py +33 -0
- scitex/fts/_fig/_editor/_cui/_backend_detector.py +39 -0
- scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +366 -0
- scitex/fts/_fig/_editor/_cui/_editor_launcher.py +175 -0
- scitex/fts/_fig/_editor/_cui/_manual_handler.py +52 -0
- scitex/fts/_fig/_editor/_cui/_panel_loader.py +246 -0
- scitex/fts/_fig/_editor/_cui/_path_resolver.py +66 -0
- scitex/fts/_fig/_editor/_defaults.py +300 -0
- scitex/fts/_fig/_editor/_gui/__init__.py +11 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +20 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_bbox.py +1339 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_core.py +1688 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +664 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_renderer.py +853 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +79 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +41 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +16 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +85 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +217 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +93 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +57 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +112 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +59 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +212 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/canvas.css +176 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +190 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +59 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +45 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +95 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +101 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +138 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +31 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +7 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +56 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +78 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +314 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +107 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +54 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +172 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +258 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +48 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +71 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +288 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +143 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +245 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +992 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +339 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +286 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +371 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +293 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +426 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +152 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +265 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +184 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +57 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +100 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +34 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +124 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +851 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +4932 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +1657 -0
- scitex/fts/_fig/_editor/_gui/_flask_editor.py +36 -0
- scitex/fts/_fig/_models/_Annotations.py +115 -0
- scitex/fts/_fig/_models/_Axes.py +152 -0
- scitex/fts/_fig/_models/_Figure.py +138 -0
- scitex/fts/_fig/_models/_Guides.py +104 -0
- scitex/fts/_fig/_models/_Plot.py +123 -0
- scitex/fts/_fig/_models/_Styles.py +245 -0
- scitex/fts/_fig/_models/__init__.py +80 -0
- scitex/fts/_fig/_models/_plot_types/__init__.py +156 -0
- scitex/fts/_fig/_models/_plot_types/_bar.py +43 -0
- scitex/fts/_fig/_models/_plot_types/_box.py +38 -0
- scitex/fts/_fig/_models/_plot_types/_distribution.py +36 -0
- scitex/fts/_fig/_models/_plot_types/_errorbar.py +60 -0
- scitex/fts/_fig/_models/_plot_types/_histogram.py +30 -0
- scitex/fts/_fig/_models/_plot_types/_image.py +61 -0
- scitex/fts/_fig/_models/_plot_types/_line.py +57 -0
- scitex/fts/_fig/_models/_plot_types/_scatter.py +30 -0
- scitex/fts/_fig/_models/_plot_types/_seaborn.py +121 -0
- scitex/fts/_fig/_models/_plot_types/_violin.py +36 -0
- scitex/fts/_fig/_utils/__init__.py +129 -0
- scitex/fts/_fig/_utils/_auto_layout.py +127 -0
- scitex/fts/_fig/_utils/_calc_bounds.py +111 -0
- scitex/fts/_fig/_utils/_const_sizes.py +48 -0
- scitex/fts/_fig/_utils/_convert_coords.py +77 -0
- scitex/fts/_fig/_utils/_get_template.py +178 -0
- scitex/fts/_fig/_utils/_normalize.py +73 -0
- scitex/fts/_fig/_utils/_plot_layout.py +397 -0
- scitex/fts/_fig/_utils/_validate.py +197 -0
- scitex/fts/_kinds/__init__.py +45 -0
- scitex/fts/_kinds/_figure/__init__.py +19 -0
- scitex/fts/_kinds/_figure/_composite.py +345 -0
- scitex/fts/_kinds/_plot/__init__.py +25 -0
- scitex/fts/_kinds/_plot/_backend/__init__.py +53 -0
- scitex/fts/_kinds/_plot/_backend/_export.py +165 -0
- scitex/fts/_kinds/_plot/_backend/_parser.py +188 -0
- scitex/fts/_kinds/_plot/_backend/_render.py +538 -0
- scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +46 -0
- scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +82 -0
- scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +441 -0
- scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +52 -0
- scitex/fts/_kinds/_plot/_dataclasses/__init__.py +47 -0
- scitex/fts/_kinds/_plot/_models/_Annotations.py +115 -0
- scitex/fts/_kinds/_plot/_models/_Axes.py +152 -0
- scitex/fts/_kinds/_plot/_models/_Figure.py +138 -0
- scitex/fts/_kinds/_plot/_models/_Guides.py +104 -0
- scitex/fts/_kinds/_plot/_models/_Plot.py +123 -0
- scitex/fts/_kinds/_plot/_models/_Styles.py +245 -0
- scitex/fts/_kinds/_plot/_models/__init__.py +80 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +156 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +43 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +38 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +36 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +60 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +30 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +61 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +57 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +30 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +121 -0
- scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +36 -0
- scitex/fts/_kinds/_plot/_utils/__init__.py +129 -0
- scitex/fts/_kinds/_plot/_utils/_auto_layout.py +127 -0
- scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +111 -0
- scitex/fts/_kinds/_plot/_utils/_const_sizes.py +48 -0
- scitex/fts/_kinds/_plot/_utils/_convert_coords.py +77 -0
- scitex/fts/_kinds/_plot/_utils/_get_template.py +178 -0
- scitex/fts/_kinds/_plot/_utils/_normalize.py +73 -0
- scitex/fts/_kinds/_plot/_utils/_plot_layout.py +397 -0
- scitex/fts/_kinds/_plot/_utils/_validate.py +197 -0
- scitex/fts/_kinds/_shape/__init__.py +141 -0
- scitex/fts/_kinds/_stats/__init__.py +56 -0
- scitex/fts/_kinds/_stats/_dataclasses/_Stats.py +423 -0
- scitex/fts/_kinds/_stats/_dataclasses/__init__.py +48 -0
- scitex/fts/_kinds/_table/__init__.py +72 -0
- scitex/fts/_kinds/_table/_latex/__init__.py +93 -0
- scitex/fts/_kinds/_table/_latex/_editor/__init__.py +11 -0
- scitex/fts/_kinds/_table/_latex/_editor/_app.py +725 -0
- scitex/fts/_kinds/_table/_latex/_export.py +279 -0
- scitex/fts/_kinds/_table/_latex/_figure_exporter.py +153 -0
- scitex/fts/_kinds/_table/_latex/_stats_formatter.py +274 -0
- scitex/fts/_kinds/_table/_latex/_table_exporter.py +362 -0
- scitex/fts/_kinds/_table/_latex/_utils.py +369 -0
- scitex/fts/_kinds/_table/_latex/_validator.py +445 -0
- scitex/fts/_kinds/_text/__init__.py +77 -0
- scitex/fts/_schemas/data_info.schema.json +75 -0
- scitex/fts/_schemas/encoding.schema.json +90 -0
- scitex/fts/_schemas/node.schema.json +145 -0
- scitex/fts/_schemas/render_manifest.schema.json +62 -0
- scitex/fts/_schemas/stats.schema.json +132 -0
- scitex/fts/_schemas/theme.schema.json +141 -0
- scitex/fts/_stats/__init__.py +48 -0
- scitex/fts/_stats/_dataclasses/_Stats.py +423 -0
- scitex/fts/_stats/_dataclasses/__init__.py +48 -0
- scitex/fts/_tables/__init__.py +65 -0
- scitex/fts/_tables/_latex/__init__.py +93 -0
- scitex/fts/_tables/_latex/_editor/__init__.py +11 -0
- scitex/fts/_tables/_latex/_editor/_app.py +725 -0
- scitex/fts/_tables/_latex/_export.py +279 -0
- scitex/fts/_tables/_latex/_figure_exporter.py +153 -0
- scitex/fts/_tables/_latex/_stats_formatter.py +274 -0
- scitex/fts/_tables/_latex/_table_exporter.py +362 -0
- scitex/fts/_tables/_latex/_utils.py +369 -0
- scitex/fts/_tables/_latex/_validator.py +445 -0
- scitex/gen/__init__.py +66 -25
- scitex/gen/misc.py +28 -0
- scitex/io/__init__.py +47 -20
- scitex/io/_load.py +87 -36
- scitex/io/_load_modules/__init__.py +10 -7
- scitex/io/_load_modules/_pandas.py +6 -1
- scitex/io/_save.py +299 -1556
- scitex/io/_save_modules/__init__.py +76 -19
- scitex/io/_save_modules/_figure_utils.py +90 -0
- scitex/io/_save_modules/_image_csv.py +497 -0
- scitex/io/_save_modules/_legends.py +91 -0
- scitex/io/_save_modules/_pltz_bundle.py +356 -0
- scitex/io/_save_modules/_pltz_stx.py +536 -0
- scitex/io/_save_modules/_stx_bundle.py +104 -0
- scitex/io/_save_modules/_symlink.py +96 -0
- scitex/io/_save_modules/_yaml.py +1 -1
- scitex/io/_save_modules/_zarr.py +64 -18
- scitex/io/bundle/README.md +212 -0
- scitex/io/bundle/__init__.py +110 -0
- scitex/io/{_bundle.py → bundle/_core.py} +219 -89
- scitex/io/bundle/_nested.py +713 -0
- scitex/io/bundle/_types.py +74 -0
- scitex/io/bundle/_zip.py +487 -0
- scitex/io/utils/h5_to_zarr.py +1 -1
- scitex/logging/__init__.py +108 -13
- scitex/logging/_errors.py +508 -0
- scitex/logging/_formatters.py +30 -6
- scitex/logging/_warnings.py +261 -0
- scitex/plt/__init__.py +4 -1
- scitex/plt/_figrecipe.py +236 -0
- scitex/plt/_subplots/_AxisWrapper.py +6 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/__init__.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_labels.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_metadata.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_visual.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_base.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_scientific.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_statistical.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_stx_aliases.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_RawMatplotlibMixin.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/__init__.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_base.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +0 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +112 -1
- scitex/plt/_subplots/_FigWrapper.py +15 -0
- scitex/plt/_subplots/_SubplotsWrapper.py +125 -489
- scitex/plt/_subplots/_export_as_csv.py +11 -0
- scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +2 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_pcolormesh.py +66 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stackplot.py +62 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_bar.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_barh.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_errorbar.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +208 -0
- scitex/plt/_subplots/_fonts.py +71 -0
- scitex/plt/_subplots/_mm_layout.py +282 -0
- scitex/plt/gallery/__init__.py +99 -2
- scitex/plt/io/_layered_bundle.py +0 -0
- scitex/plt/styles/_plot_postprocess.py +3 -1
- scitex/plt/utils/_configure_mpl.py +16 -19
- scitex/repro/_RandomStateManager.py +13 -8
- scitex/resource/__init__.py +19 -1
- scitex/resource/_utils/_get_env_info.py +13 -25
- scitex/schema/__init__.py +149 -160
- scitex/schema/_encoding.py +273 -0
- scitex/schema/_figure_elements.py +406 -0
- scitex/schema/_plot.py +0 -0
- scitex/schema/_theme.py +360 -0
- scitex/schema/_validation.py +0 -98
- scitex/scholar/__init__.py +56 -14
- scitex/scholar/auth/ScholarAuthManager.py +1 -1
- scitex/scholar/auth/__init__.py +11 -2
- scitex/scholar/auth/providers/BaseAuthenticator.py +1 -1
- scitex/scholar/auth/providers/EZProxyAuthenticator.py +1 -1
- scitex/scholar/auth/providers/OpenAthensAuthenticator.py +1 -1
- scitex/scholar/auth/providers/ShibbolethAuthenticator.py +1 -1
- scitex/scholar/config/ScholarConfig.py +1 -1
- scitex/scholar/core/Scholar.py +1 -1
- scitex/session/_decorator.py +18 -16
- scitex/session/_lifecycle.py +9 -11
- scitex/session/template.py +9 -8
- scitex/sh/test_sh.py +72 -0
- scitex/sh/test_sh_simple.py +61 -0
- scitex/stats/__init__.py +221 -97
- scitex/stats/_schema.py +21 -22
- scitex/stats/descriptive/_circular.py +212 -351
- scitex/stats/descriptive/_describe.py +81 -132
- scitex/stats/descriptive/_nan.py +205 -433
- scitex/stats/descriptive/_real.py +127 -141
- scitex/str/_format_plot_text.py +5 -5
- scitex/str/_latex.py +26 -84
- scitex/str/_latex_fallback.py +53 -47
- scitex/web/_search_pubmed.py +5 -4
- scitex/writer/tests/test_diff_between.py +451 -0
- scitex/writer/tests/test_document_section.py +311 -0
- scitex/writer/tests/test_document_workflow.py +393 -0
- scitex/writer/tests/test_writer.py +361 -0
- scitex/writer/tests/test_writer_integration.py +303 -0
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/METADATA +364 -181
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/RECORD +479 -108
- scitex/fig/editor/_edit.py +0 -751
- scitex/scholar/docs/to_claude/guidelines/examples/mgmt/ARCHITECTURE_EXAMPLE.md +0 -905
- scitex/scholar/docs/to_claude/guidelines/examples/mgmt/BULLETIN_BOARD_EXAMPLE.md +0 -99
- scitex/scholar/docs/to_claude/guidelines/examples/mgmt/PROJECT_DESCRIPTION_EXAMPLE.md +0 -96
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/WHEEL +0 -0
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/entry_points.txt +0 -0
- {scitex-2.7.3.dist-info → scitex-2.10.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Comprehensive tests for DocumentSection class.
|
|
5
|
+
|
|
6
|
+
Tests cover:
|
|
7
|
+
- File read/write operations
|
|
8
|
+
- Git operations (commit, history, diff, checkout)
|
|
9
|
+
- Error handling and edge cases
|
|
10
|
+
- Integration with git repository
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import tempfile
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from unittest.mock import MagicMock, patch
|
|
18
|
+
|
|
19
|
+
import pytest
|
|
20
|
+
|
|
21
|
+
from scitex.writer.dataclasses.core._DocumentSection import DocumentSection
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestDocumentSectionReadWrite:
|
|
25
|
+
"""Test file read/write operations."""
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def temp_file(self):
|
|
29
|
+
"""Create temporary file."""
|
|
30
|
+
temp_dir = tempfile.mkdtemp(prefix="scitex_doc_")
|
|
31
|
+
temp_file = Path(temp_dir) / "test.tex"
|
|
32
|
+
temp_file.write_text("Initial content\n")
|
|
33
|
+
|
|
34
|
+
yield temp_file
|
|
35
|
+
|
|
36
|
+
# Cleanup
|
|
37
|
+
if Path(temp_dir).exists():
|
|
38
|
+
shutil.rmtree(temp_dir)
|
|
39
|
+
|
|
40
|
+
def test_read_existing_file(self, temp_file):
|
|
41
|
+
"""Test reading existing file."""
|
|
42
|
+
section = DocumentSection(temp_file)
|
|
43
|
+
content = section.read()
|
|
44
|
+
|
|
45
|
+
assert content is not None
|
|
46
|
+
assert "Initial content" in str(content)
|
|
47
|
+
|
|
48
|
+
def test_read_nonexistent_file(self):
|
|
49
|
+
"""Test reading non-existent file returns None."""
|
|
50
|
+
section = DocumentSection(Path("/nonexistent/file.tex"))
|
|
51
|
+
content = section.read()
|
|
52
|
+
|
|
53
|
+
assert content is None
|
|
54
|
+
|
|
55
|
+
def test_write_file(self, temp_file):
|
|
56
|
+
"""Test writing to file."""
|
|
57
|
+
section = DocumentSection(temp_file)
|
|
58
|
+
result = section.write("New content\n")
|
|
59
|
+
|
|
60
|
+
assert result is True
|
|
61
|
+
assert temp_file.read_text() == "New content\n"
|
|
62
|
+
|
|
63
|
+
def test_write_with_list(self, temp_file):
|
|
64
|
+
"""Test writing list of lines."""
|
|
65
|
+
section = DocumentSection(temp_file)
|
|
66
|
+
result = section.write(["Line 1", "Line 2", "Line 3"])
|
|
67
|
+
|
|
68
|
+
assert result is True
|
|
69
|
+
content = temp_file.read_text()
|
|
70
|
+
assert "Line 1\nLine 2\nLine 3" in content
|
|
71
|
+
|
|
72
|
+
def test_write_nonexistent_directory(self):
|
|
73
|
+
"""Test writing to non-existent directory fails gracefully."""
|
|
74
|
+
section = DocumentSection(Path("/nonexistent/dir/file.tex"))
|
|
75
|
+
result = section.write("content")
|
|
76
|
+
|
|
77
|
+
assert result is False
|
|
78
|
+
|
|
79
|
+
def test_read_write_roundtrip(self, temp_file):
|
|
80
|
+
"""Test reading and writing back same content."""
|
|
81
|
+
section = DocumentSection(temp_file)
|
|
82
|
+
original = section.read()
|
|
83
|
+
|
|
84
|
+
section.write(original)
|
|
85
|
+
readback = section.read()
|
|
86
|
+
|
|
87
|
+
assert original == readback
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class TestDocumentSectionGitOperations:
|
|
91
|
+
"""Test git-based operations."""
|
|
92
|
+
|
|
93
|
+
@pytest.fixture
|
|
94
|
+
def git_repo_with_file(self):
|
|
95
|
+
"""Create git repository with test file."""
|
|
96
|
+
temp_dir = tempfile.mkdtemp(prefix="scitex_git_")
|
|
97
|
+
repo_path = Path(temp_dir)
|
|
98
|
+
|
|
99
|
+
# Initialize git repo
|
|
100
|
+
subprocess.run(
|
|
101
|
+
["git", "init"],
|
|
102
|
+
cwd=repo_path,
|
|
103
|
+
capture_output=True,
|
|
104
|
+
check=True,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Configure git
|
|
108
|
+
subprocess.run(
|
|
109
|
+
["git", "config", "user.email", "test@example.com"],
|
|
110
|
+
cwd=repo_path,
|
|
111
|
+
capture_output=True,
|
|
112
|
+
check=True,
|
|
113
|
+
)
|
|
114
|
+
subprocess.run(
|
|
115
|
+
["git", "config", "user.name", "Test User"],
|
|
116
|
+
cwd=repo_path,
|
|
117
|
+
capture_output=True,
|
|
118
|
+
check=True,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Create test file
|
|
122
|
+
test_file = repo_path / "test.tex"
|
|
123
|
+
test_file.write_text("Initial content\n")
|
|
124
|
+
|
|
125
|
+
# Initial commit
|
|
126
|
+
subprocess.run(
|
|
127
|
+
["git", "add", "test.tex"],
|
|
128
|
+
cwd=repo_path,
|
|
129
|
+
capture_output=True,
|
|
130
|
+
check=True,
|
|
131
|
+
)
|
|
132
|
+
subprocess.run(
|
|
133
|
+
["git", "commit", "-m", "Initial commit"],
|
|
134
|
+
cwd=repo_path,
|
|
135
|
+
capture_output=True,
|
|
136
|
+
check=True,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
yield test_file, repo_path
|
|
140
|
+
|
|
141
|
+
# Cleanup
|
|
142
|
+
if repo_path.exists():
|
|
143
|
+
shutil.rmtree(repo_path)
|
|
144
|
+
|
|
145
|
+
def test_commit_file(self, git_repo_with_file):
|
|
146
|
+
"""Test committing file to git."""
|
|
147
|
+
test_file, repo_path = git_repo_with_file
|
|
148
|
+
|
|
149
|
+
section = DocumentSection(test_file, git_root=repo_path)
|
|
150
|
+
section.write("Updated content\n")
|
|
151
|
+
result = section.commit("Update test file")
|
|
152
|
+
|
|
153
|
+
assert result is True
|
|
154
|
+
|
|
155
|
+
# Verify commit was made
|
|
156
|
+
log_result = subprocess.run(
|
|
157
|
+
["git", "log", "--oneline"],
|
|
158
|
+
cwd=repo_path,
|
|
159
|
+
capture_output=True,
|
|
160
|
+
text=True,
|
|
161
|
+
check=True,
|
|
162
|
+
)
|
|
163
|
+
assert "Update test file" in log_result.stdout
|
|
164
|
+
|
|
165
|
+
def test_history_shows_commits(self, git_repo_with_file):
|
|
166
|
+
"""Test getting file history."""
|
|
167
|
+
test_file, repo_path = git_repo_with_file
|
|
168
|
+
|
|
169
|
+
section = DocumentSection(test_file, git_root=repo_path)
|
|
170
|
+
section.write("Update 1\n")
|
|
171
|
+
section.commit("Commit 1")
|
|
172
|
+
section.write("Update 2\n")
|
|
173
|
+
section.commit("Commit 2")
|
|
174
|
+
|
|
175
|
+
history = section.history()
|
|
176
|
+
|
|
177
|
+
assert len(history) >= 2
|
|
178
|
+
assert any("Commit 1" in h for h in history)
|
|
179
|
+
assert any("Commit 2" in h for h in history)
|
|
180
|
+
|
|
181
|
+
def test_diff_shows_changes(self, git_repo_with_file):
|
|
182
|
+
"""Test getting diff of changes."""
|
|
183
|
+
test_file, repo_path = git_repo_with_file
|
|
184
|
+
|
|
185
|
+
section = DocumentSection(test_file, git_root=repo_path)
|
|
186
|
+
section.write("Changed content\n")
|
|
187
|
+
|
|
188
|
+
diff = section.diff()
|
|
189
|
+
|
|
190
|
+
assert len(diff) > 0
|
|
191
|
+
assert "Changed content" in diff or "-" in diff
|
|
192
|
+
|
|
193
|
+
def test_checkout_restores_file(self, git_repo_with_file):
|
|
194
|
+
"""Test checking out file from git."""
|
|
195
|
+
test_file, repo_path = git_repo_with_file
|
|
196
|
+
|
|
197
|
+
section = DocumentSection(test_file, git_root=repo_path)
|
|
198
|
+
|
|
199
|
+
# Modify file
|
|
200
|
+
section.write("Modified content\n")
|
|
201
|
+
modified = section.read()
|
|
202
|
+
|
|
203
|
+
# Restore from HEAD
|
|
204
|
+
result = section.checkout("HEAD")
|
|
205
|
+
|
|
206
|
+
assert result is True
|
|
207
|
+
restored = section.read()
|
|
208
|
+
assert restored != modified
|
|
209
|
+
assert "Initial content" in str(restored)
|
|
210
|
+
|
|
211
|
+
def test_history_empty_without_git(self):
|
|
212
|
+
"""Test history returns empty list without git repo."""
|
|
213
|
+
temp_file = Path(tempfile.mktemp(suffix=".tex"))
|
|
214
|
+
temp_file.write_text("content\n")
|
|
215
|
+
|
|
216
|
+
section = DocumentSection(temp_file)
|
|
217
|
+
history = section.history()
|
|
218
|
+
|
|
219
|
+
assert history == []
|
|
220
|
+
|
|
221
|
+
# Cleanup
|
|
222
|
+
temp_file.unlink()
|
|
223
|
+
|
|
224
|
+
def test_diff_empty_without_git(self):
|
|
225
|
+
"""Test diff returns empty string without git repo."""
|
|
226
|
+
temp_file = Path(tempfile.mktemp(suffix=".tex"))
|
|
227
|
+
temp_file.write_text("content\n")
|
|
228
|
+
|
|
229
|
+
section = DocumentSection(temp_file)
|
|
230
|
+
diff = section.diff()
|
|
231
|
+
|
|
232
|
+
assert diff == ""
|
|
233
|
+
|
|
234
|
+
# Cleanup
|
|
235
|
+
temp_file.unlink()
|
|
236
|
+
|
|
237
|
+
def test_commit_fails_without_git(self):
|
|
238
|
+
"""Test commit returns False without git repo."""
|
|
239
|
+
temp_file = Path(tempfile.mktemp(suffix=".tex"))
|
|
240
|
+
temp_file.write_text("content\n")
|
|
241
|
+
|
|
242
|
+
section = DocumentSection(temp_file)
|
|
243
|
+
result = section.commit("test message")
|
|
244
|
+
|
|
245
|
+
assert result is False
|
|
246
|
+
|
|
247
|
+
# Cleanup
|
|
248
|
+
temp_file.unlink()
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class TestDocumentSectionRepresentation:
|
|
252
|
+
"""Test string representation."""
|
|
253
|
+
|
|
254
|
+
def test_repr(self):
|
|
255
|
+
"""Test __repr__ shows filename."""
|
|
256
|
+
section = DocumentSection(Path("/path/to/introduction.tex"))
|
|
257
|
+
repr_str = repr(section)
|
|
258
|
+
|
|
259
|
+
assert "DocumentSection" in repr_str
|
|
260
|
+
assert "introduction.tex" in repr_str
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class TestDocumentSectionPathHandling:
|
|
264
|
+
"""Test path handling."""
|
|
265
|
+
|
|
266
|
+
def test_path_attribute(self):
|
|
267
|
+
"""Test path attribute is stored."""
|
|
268
|
+
path = Path("/path/to/file.tex")
|
|
269
|
+
section = DocumentSection(path)
|
|
270
|
+
|
|
271
|
+
assert section.path == path
|
|
272
|
+
|
|
273
|
+
def test_git_root_passed_explicitly(self):
|
|
274
|
+
"""Test git_root is stored when passed."""
|
|
275
|
+
git_root = Path("/path/to/git")
|
|
276
|
+
section = DocumentSection(Path("/path/to/file.tex"), git_root=git_root)
|
|
277
|
+
|
|
278
|
+
assert section.git_root == git_root
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class TestDocumentSectionErrorHandling:
|
|
282
|
+
"""Test error handling."""
|
|
283
|
+
|
|
284
|
+
def test_read_unicode_fallback(self):
|
|
285
|
+
"""Test read handles encoding errors gracefully."""
|
|
286
|
+
temp_dir = tempfile.mkdtemp(prefix="scitex_enc_")
|
|
287
|
+
temp_file = Path(temp_dir) / "test.tex"
|
|
288
|
+
|
|
289
|
+
# Write with UTF-8
|
|
290
|
+
temp_file.write_text("Valid UTF-8 content\n", encoding="utf-8")
|
|
291
|
+
|
|
292
|
+
section = DocumentSection(temp_file)
|
|
293
|
+
content = section.read()
|
|
294
|
+
|
|
295
|
+
assert content is not None
|
|
296
|
+
assert "Valid UTF-8 content" in str(content)
|
|
297
|
+
|
|
298
|
+
# Cleanup
|
|
299
|
+
shutil.rmtree(temp_dir)
|
|
300
|
+
|
|
301
|
+
def test_write_handles_exceptions(self):
|
|
302
|
+
"""Test write handles exceptions gracefully."""
|
|
303
|
+
# Use a path that will fail to write
|
|
304
|
+
section = DocumentSection(Path("/root/impossible/path/file.tex"))
|
|
305
|
+
result = section.write("content")
|
|
306
|
+
|
|
307
|
+
assert result is False
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
if __name__ == "__main__":
|
|
311
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
End-to-end workflow tests for Writer document operations.
|
|
5
|
+
|
|
6
|
+
Tests complete workflows:
|
|
7
|
+
- Create project → access section → read/write/commit
|
|
8
|
+
- Multi-section editing
|
|
9
|
+
- Document tree navigation
|
|
10
|
+
- Git history tracking
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import tempfile
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from unittest.mock import patch
|
|
18
|
+
|
|
19
|
+
import pytest
|
|
20
|
+
|
|
21
|
+
from scitex.writer.Writer import Writer
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestWriterDocumentWorkflow:
|
|
25
|
+
"""Test complete document editing workflows."""
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def valid_project_dir(self):
|
|
29
|
+
"""Create a valid project structure."""
|
|
30
|
+
temp_dir = tempfile.mkdtemp(prefix="scitex_workflow_")
|
|
31
|
+
project_dir = Path(temp_dir)
|
|
32
|
+
|
|
33
|
+
# Create required structure with contents subdirectory
|
|
34
|
+
(project_dir / "01_manuscript" / "contents").mkdir(parents=True, exist_ok=True)
|
|
35
|
+
(project_dir / "02_supplementary").mkdir(parents=True, exist_ok=True)
|
|
36
|
+
(project_dir / "03_revision").mkdir(parents=True, exist_ok=True)
|
|
37
|
+
|
|
38
|
+
# Create manuscript files
|
|
39
|
+
(project_dir / "01_manuscript" / "base.tex").write_text("\\documentclass{article}\n")
|
|
40
|
+
(project_dir / "01_manuscript" / "README.md").write_text("# Manuscript\n")
|
|
41
|
+
|
|
42
|
+
# Create manuscript content files
|
|
43
|
+
(project_dir / "01_manuscript" / "contents" / "abstract.tex").write_text("Abstract content\n")
|
|
44
|
+
(project_dir / "01_manuscript" / "contents" / "introduction.tex").write_text("Introduction content\n")
|
|
45
|
+
(project_dir / "01_manuscript" / "contents" / "methods.tex").write_text("Methods content\n")
|
|
46
|
+
(project_dir / "01_manuscript" / "contents" / "results.tex").write_text("Results content\n")
|
|
47
|
+
(project_dir / "01_manuscript" / "contents" / "discussion.tex").write_text("Discussion content\n")
|
|
48
|
+
|
|
49
|
+
# Create directories for figures and tables
|
|
50
|
+
(project_dir / "01_manuscript" / "contents" / "figures").mkdir(exist_ok=True)
|
|
51
|
+
(project_dir / "01_manuscript" / "contents" / "tables").mkdir(exist_ok=True)
|
|
52
|
+
|
|
53
|
+
# Initialize git repo
|
|
54
|
+
subprocess.run(
|
|
55
|
+
["git", "init"],
|
|
56
|
+
cwd=project_dir,
|
|
57
|
+
capture_output=True,
|
|
58
|
+
check=True,
|
|
59
|
+
)
|
|
60
|
+
subprocess.run(
|
|
61
|
+
["git", "config", "user.email", "test@example.com"],
|
|
62
|
+
cwd=project_dir,
|
|
63
|
+
capture_output=True,
|
|
64
|
+
check=True,
|
|
65
|
+
)
|
|
66
|
+
subprocess.run(
|
|
67
|
+
["git", "config", "user.name", "Test User"],
|
|
68
|
+
cwd=project_dir,
|
|
69
|
+
capture_output=True,
|
|
70
|
+
check=True,
|
|
71
|
+
)
|
|
72
|
+
subprocess.run(
|
|
73
|
+
["git", "add", "."],
|
|
74
|
+
cwd=project_dir,
|
|
75
|
+
capture_output=True,
|
|
76
|
+
check=True,
|
|
77
|
+
)
|
|
78
|
+
subprocess.run(
|
|
79
|
+
["git", "commit", "-m", "Initial commit"],
|
|
80
|
+
cwd=project_dir,
|
|
81
|
+
capture_output=True,
|
|
82
|
+
check=True,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
yield project_dir
|
|
86
|
+
|
|
87
|
+
# Cleanup
|
|
88
|
+
if project_dir.exists():
|
|
89
|
+
shutil.rmtree(project_dir)
|
|
90
|
+
|
|
91
|
+
def test_access_manuscript_introduction(self, valid_project_dir):
|
|
92
|
+
"""Test accessing manuscript introduction section."""
|
|
93
|
+
from scitex.writer.dataclasses.tree._ManuscriptTree import ManuscriptTree
|
|
94
|
+
|
|
95
|
+
# Create actual tree without mocking
|
|
96
|
+
tree = ManuscriptTree(
|
|
97
|
+
valid_project_dir / "01_manuscript",
|
|
98
|
+
git_root=valid_project_dir,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Access introduction through contents
|
|
102
|
+
intro = tree.contents.introduction
|
|
103
|
+
assert intro is not None
|
|
104
|
+
assert intro.path.name == "introduction.tex"
|
|
105
|
+
|
|
106
|
+
def test_read_section_content(self, valid_project_dir):
|
|
107
|
+
"""Test reading section content."""
|
|
108
|
+
from scitex.writer.dataclasses.core._DocumentSection import DocumentSection
|
|
109
|
+
|
|
110
|
+
intro_path = valid_project_dir / "01_manuscript" / "contents" / "introduction.tex"
|
|
111
|
+
section = DocumentSection(intro_path, git_root=valid_project_dir)
|
|
112
|
+
|
|
113
|
+
content = section.read()
|
|
114
|
+
assert content is not None
|
|
115
|
+
assert "Introduction content" in str(content)
|
|
116
|
+
|
|
117
|
+
def test_write_section_content(self, valid_project_dir):
|
|
118
|
+
"""Test writing to section."""
|
|
119
|
+
from scitex.writer.dataclasses.core._DocumentSection import DocumentSection
|
|
120
|
+
|
|
121
|
+
intro_path = valid_project_dir / "01_manuscript" / "contents" / "introduction.tex"
|
|
122
|
+
section = DocumentSection(intro_path, git_root=valid_project_dir)
|
|
123
|
+
|
|
124
|
+
new_content = "Updated introduction with new content\n"
|
|
125
|
+
result = section.write(new_content)
|
|
126
|
+
|
|
127
|
+
assert result is True
|
|
128
|
+
assert intro_path.read_text() == new_content
|
|
129
|
+
|
|
130
|
+
def test_commit_section_changes(self, valid_project_dir):
|
|
131
|
+
"""Test committing changes to section."""
|
|
132
|
+
from scitex.writer.dataclasses.core._DocumentSection import DocumentSection
|
|
133
|
+
|
|
134
|
+
intro_path = valid_project_dir / "01_manuscript" / "contents" / "introduction.tex"
|
|
135
|
+
section = DocumentSection(intro_path, git_root=valid_project_dir)
|
|
136
|
+
|
|
137
|
+
# Modify and commit
|
|
138
|
+
section.write("Updated introduction\n")
|
|
139
|
+
result = section.commit("Update introduction section")
|
|
140
|
+
|
|
141
|
+
assert result is True
|
|
142
|
+
|
|
143
|
+
# Verify commit exists
|
|
144
|
+
log = subprocess.run(
|
|
145
|
+
["git", "log", "--oneline"],
|
|
146
|
+
cwd=valid_project_dir,
|
|
147
|
+
capture_output=True,
|
|
148
|
+
text=True,
|
|
149
|
+
check=True,
|
|
150
|
+
)
|
|
151
|
+
assert "Update introduction section" in log.stdout
|
|
152
|
+
|
|
153
|
+
def test_access_multiple_sections(self, valid_project_dir):
|
|
154
|
+
"""Test accessing multiple sections."""
|
|
155
|
+
from scitex.writer.dataclasses.contents._ManuscriptContents import (
|
|
156
|
+
ManuscriptContents,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
contents = ManuscriptContents(
|
|
160
|
+
valid_project_dir / "01_manuscript" / "contents",
|
|
161
|
+
git_root=valid_project_dir,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Access different sections
|
|
165
|
+
assert contents.abstract is not None
|
|
166
|
+
assert contents.introduction is not None
|
|
167
|
+
assert contents.methods is not None
|
|
168
|
+
assert contents.results is not None
|
|
169
|
+
assert contents.discussion is not None
|
|
170
|
+
|
|
171
|
+
# All should be DocumentSection instances
|
|
172
|
+
assert hasattr(contents.abstract, "read")
|
|
173
|
+
assert hasattr(contents.introduction, "commit")
|
|
174
|
+
|
|
175
|
+
def test_read_write_commit_workflow(self, valid_project_dir):
|
|
176
|
+
"""Test complete read-write-commit workflow."""
|
|
177
|
+
from scitex.writer.dataclasses.core._DocumentSection import DocumentSection
|
|
178
|
+
|
|
179
|
+
intro_path = valid_project_dir / "01_manuscript" / "contents" / "introduction.tex"
|
|
180
|
+
section = DocumentSection(intro_path, git_root=valid_project_dir)
|
|
181
|
+
|
|
182
|
+
# Read initial
|
|
183
|
+
original = section.read()
|
|
184
|
+
assert original is not None
|
|
185
|
+
|
|
186
|
+
# Modify
|
|
187
|
+
modified = "Completely new introduction\n"
|
|
188
|
+
section.write(modified)
|
|
189
|
+
|
|
190
|
+
# Verify modification (read returns what scitex.io gives us - could be list or string)
|
|
191
|
+
readback = section.read()
|
|
192
|
+
if isinstance(readback, list):
|
|
193
|
+
assert any("Completely new introduction" in line for line in readback)
|
|
194
|
+
else:
|
|
195
|
+
assert "Completely new introduction" in str(readback)
|
|
196
|
+
|
|
197
|
+
# Commit
|
|
198
|
+
commit_result = section.commit("Rewrite introduction")
|
|
199
|
+
assert commit_result is True
|
|
200
|
+
|
|
201
|
+
# Check history shows both commits
|
|
202
|
+
history = section.history()
|
|
203
|
+
assert len(history) >= 1
|
|
204
|
+
assert any("Rewrite introduction" in h for h in history)
|
|
205
|
+
|
|
206
|
+
def test_diff_shows_changes(self, valid_project_dir):
|
|
207
|
+
"""Test diff operation shows changes."""
|
|
208
|
+
from scitex.writer.dataclasses.core._DocumentSection import DocumentSection
|
|
209
|
+
|
|
210
|
+
intro_path = valid_project_dir / "01_manuscript" / "contents" / "introduction.tex"
|
|
211
|
+
section = DocumentSection(intro_path, git_root=valid_project_dir)
|
|
212
|
+
|
|
213
|
+
# Modify file
|
|
214
|
+
section.write("Modified introduction\n")
|
|
215
|
+
|
|
216
|
+
# Get diff
|
|
217
|
+
diff = section.diff()
|
|
218
|
+
|
|
219
|
+
assert len(diff) > 0
|
|
220
|
+
|
|
221
|
+
def test_checkout_reverts_changes(self, valid_project_dir):
|
|
222
|
+
"""Test checking out file reverts to previous version."""
|
|
223
|
+
from scitex.writer.dataclasses.core._DocumentSection import DocumentSection
|
|
224
|
+
|
|
225
|
+
intro_path = valid_project_dir / "01_manuscript" / "contents" / "introduction.tex"
|
|
226
|
+
section = DocumentSection(intro_path, git_root=valid_project_dir)
|
|
227
|
+
|
|
228
|
+
original = section.read()
|
|
229
|
+
|
|
230
|
+
# Modify
|
|
231
|
+
section.write("New content\n")
|
|
232
|
+
modified = section.read()
|
|
233
|
+
assert modified != original
|
|
234
|
+
|
|
235
|
+
# Checkout HEAD (revert)
|
|
236
|
+
result = section.checkout("HEAD")
|
|
237
|
+
assert result is True
|
|
238
|
+
|
|
239
|
+
# Verify reverted
|
|
240
|
+
reverted = section.read()
|
|
241
|
+
assert reverted == original
|
|
242
|
+
|
|
243
|
+
def test_history_tracks_commits(self, valid_project_dir):
|
|
244
|
+
"""Test history tracks multiple commits."""
|
|
245
|
+
from scitex.writer.dataclasses.core._DocumentSection import DocumentSection
|
|
246
|
+
|
|
247
|
+
intro_path = valid_project_dir / "01_manuscript" / "contents" / "introduction.tex"
|
|
248
|
+
section = DocumentSection(intro_path, git_root=valid_project_dir)
|
|
249
|
+
|
|
250
|
+
# Make multiple commits
|
|
251
|
+
section.write("Version 1\n")
|
|
252
|
+
section.commit("Version 1")
|
|
253
|
+
|
|
254
|
+
section.write("Version 2\n")
|
|
255
|
+
section.commit("Version 2")
|
|
256
|
+
|
|
257
|
+
section.write("Version 3\n")
|
|
258
|
+
section.commit("Version 3")
|
|
259
|
+
|
|
260
|
+
# Check history
|
|
261
|
+
history = section.history()
|
|
262
|
+
assert len(history) >= 3
|
|
263
|
+
assert any("Version 1" in h for h in history)
|
|
264
|
+
assert any("Version 2" in h for h in history)
|
|
265
|
+
assert any("Version 3" in h for h in history)
|
|
266
|
+
|
|
267
|
+
def test_tree_structure_verification(self, valid_project_dir):
|
|
268
|
+
"""Test verifying manuscript tree structure."""
|
|
269
|
+
from scitex.writer.dataclasses.tree._ManuscriptTree import ManuscriptTree
|
|
270
|
+
|
|
271
|
+
tree = ManuscriptTree(
|
|
272
|
+
valid_project_dir / "01_manuscript",
|
|
273
|
+
git_root=valid_project_dir,
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
is_valid, missing = tree.verify_structure()
|
|
277
|
+
assert is_valid is True
|
|
278
|
+
assert len(missing) == 0
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class TestManuscriptContentsAccess:
|
|
282
|
+
"""Test accessing all manuscript content sections."""
|
|
283
|
+
|
|
284
|
+
@pytest.fixture
|
|
285
|
+
def manuscript_contents_dir(self):
|
|
286
|
+
"""Create manuscript contents directory with all files."""
|
|
287
|
+
temp_dir = tempfile.mkdtemp(prefix="scitex_contents_")
|
|
288
|
+
contents_dir = Path(temp_dir)
|
|
289
|
+
|
|
290
|
+
# Create all section files
|
|
291
|
+
sections = [
|
|
292
|
+
"abstract.tex",
|
|
293
|
+
"introduction.tex",
|
|
294
|
+
"methods.tex",
|
|
295
|
+
"results.tex",
|
|
296
|
+
"discussion.tex",
|
|
297
|
+
"title.tex",
|
|
298
|
+
"authors.tex",
|
|
299
|
+
"keywords.tex",
|
|
300
|
+
"journal_name.tex",
|
|
301
|
+
"graphical_abstract.tex",
|
|
302
|
+
"highlights.tex",
|
|
303
|
+
"data_availability.tex",
|
|
304
|
+
"additional_info.tex",
|
|
305
|
+
"wordcount.tex",
|
|
306
|
+
"bibliography.bib",
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
for section in sections:
|
|
310
|
+
(contents_dir / section).write_text(f"{section} content\n")
|
|
311
|
+
|
|
312
|
+
# Create directories
|
|
313
|
+
(contents_dir / "figures").mkdir(exist_ok=True)
|
|
314
|
+
(contents_dir / "tables").mkdir(exist_ok=True)
|
|
315
|
+
(contents_dir / "latex_styles").mkdir(exist_ok=True)
|
|
316
|
+
|
|
317
|
+
yield contents_dir
|
|
318
|
+
|
|
319
|
+
# Cleanup
|
|
320
|
+
if contents_dir.exists():
|
|
321
|
+
shutil.rmtree(contents_dir)
|
|
322
|
+
|
|
323
|
+
def test_access_all_core_sections(self, manuscript_contents_dir):
|
|
324
|
+
"""Test accessing all core manuscript sections."""
|
|
325
|
+
from scitex.writer.dataclasses.contents._ManuscriptContents import (
|
|
326
|
+
ManuscriptContents,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
contents = ManuscriptContents(manuscript_contents_dir)
|
|
330
|
+
|
|
331
|
+
# Core sections
|
|
332
|
+
assert contents.abstract is not None
|
|
333
|
+
assert contents.introduction is not None
|
|
334
|
+
assert contents.methods is not None
|
|
335
|
+
assert contents.results is not None
|
|
336
|
+
assert contents.discussion is not None
|
|
337
|
+
|
|
338
|
+
# Read from each
|
|
339
|
+
assert "abstract.tex content" in str(contents.abstract.read())
|
|
340
|
+
assert "introduction.tex content" in str(contents.introduction.read())
|
|
341
|
+
|
|
342
|
+
def test_access_all_metadata_sections(self, manuscript_contents_dir):
|
|
343
|
+
"""Test accessing metadata sections."""
|
|
344
|
+
from scitex.writer.dataclasses.contents._ManuscriptContents import (
|
|
345
|
+
ManuscriptContents,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
contents = ManuscriptContents(manuscript_contents_dir)
|
|
349
|
+
|
|
350
|
+
assert contents.title is not None
|
|
351
|
+
assert contents.authors is not None
|
|
352
|
+
assert contents.keywords is not None
|
|
353
|
+
assert contents.journal_name is not None
|
|
354
|
+
|
|
355
|
+
def test_access_optional_sections(self, manuscript_contents_dir):
|
|
356
|
+
"""Test accessing optional sections."""
|
|
357
|
+
from scitex.writer.dataclasses.contents._ManuscriptContents import (
|
|
358
|
+
ManuscriptContents,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
contents = ManuscriptContents(manuscript_contents_dir)
|
|
362
|
+
|
|
363
|
+
assert contents.graphical_abstract is not None
|
|
364
|
+
assert contents.highlights is not None
|
|
365
|
+
assert contents.data_availability is not None
|
|
366
|
+
|
|
367
|
+
def test_access_bibliography(self, manuscript_contents_dir):
|
|
368
|
+
"""Test accessing bibliography file."""
|
|
369
|
+
from scitex.writer.dataclasses.contents._ManuscriptContents import (
|
|
370
|
+
ManuscriptContents,
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
contents = ManuscriptContents(manuscript_contents_dir)
|
|
374
|
+
|
|
375
|
+
assert contents.bibliography is not None
|
|
376
|
+
assert contents.bibliography.path.name == "bibliography.bib"
|
|
377
|
+
|
|
378
|
+
def test_access_directories(self, manuscript_contents_dir):
|
|
379
|
+
"""Test accessing figure and table directories."""
|
|
380
|
+
from scitex.writer.dataclasses.contents._ManuscriptContents import (
|
|
381
|
+
ManuscriptContents,
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
contents = ManuscriptContents(manuscript_contents_dir)
|
|
385
|
+
|
|
386
|
+
assert contents.figures is not None
|
|
387
|
+
assert contents.figures.exists()
|
|
388
|
+
assert contents.tables is not None
|
|
389
|
+
assert contents.tables.exists()
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
if __name__ == "__main__":
|
|
393
|
+
pytest.main([__file__, "-v"])
|