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
scitex/bridge/__init__.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
2
|
# File: ./src/scitex/bridge/__init__.py
|
|
4
3
|
# Time-stamp: "2024-12-09 09:30:00 (ywatanabe)"
|
|
5
4
|
"""
|
|
@@ -45,40 +44,47 @@ Usage:
|
|
|
45
44
|
"""
|
|
46
45
|
|
|
47
46
|
# Stats ↔ Plt bridges
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
# FigRecipe integration (optional)
|
|
48
|
+
from scitex.bridge._figrecipe import (
|
|
49
|
+
FIGRECIPE_AVAILABLE,
|
|
50
|
+
has_figrecipe,
|
|
51
|
+
load_recipe,
|
|
52
|
+
save_with_recipe,
|
|
52
53
|
)
|
|
53
54
|
|
|
54
|
-
#
|
|
55
|
-
from scitex.bridge.
|
|
56
|
-
|
|
57
|
-
add_stats_to_figure_model,
|
|
58
|
-
position_stat_annotation,
|
|
55
|
+
# High-level helpers
|
|
56
|
+
from scitex.bridge._helpers import (
|
|
57
|
+
add_stats_from_results,
|
|
59
58
|
)
|
|
60
59
|
|
|
61
60
|
# Plt ↔ Vis bridges
|
|
62
61
|
from scitex.bridge._plt_vis import (
|
|
63
|
-
figure_to_vis_model,
|
|
64
62
|
axes_to_vis_axes,
|
|
65
|
-
tracking_to_plot_configs,
|
|
66
63
|
collect_figure_data,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
# High-level helpers
|
|
70
|
-
from scitex.bridge._helpers import (
|
|
71
|
-
add_stats_from_results,
|
|
64
|
+
figure_to_vis_model,
|
|
65
|
+
tracking_to_plot_configs,
|
|
72
66
|
)
|
|
73
67
|
|
|
74
68
|
# Protocol versioning
|
|
75
69
|
from scitex.bridge._protocol import (
|
|
76
70
|
BRIDGE_PROTOCOL_VERSION,
|
|
71
|
+
COORDINATE_SYSTEMS,
|
|
77
72
|
ProtocolInfo,
|
|
78
|
-
check_protocol_compatibility,
|
|
79
73
|
add_protocol_metadata,
|
|
74
|
+
check_protocol_compatibility,
|
|
80
75
|
extract_protocol_metadata,
|
|
81
|
-
|
|
76
|
+
)
|
|
77
|
+
from scitex.bridge._stats_plt import (
|
|
78
|
+
add_stat_to_axes,
|
|
79
|
+
extract_stats_from_axes,
|
|
80
|
+
format_stat_for_plot,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Stats ↔ Vis bridges
|
|
84
|
+
from scitex.bridge._stats_vis import (
|
|
85
|
+
add_stats_to_figure_model,
|
|
86
|
+
position_stat_annotation,
|
|
87
|
+
stat_result_to_annotation,
|
|
82
88
|
)
|
|
83
89
|
|
|
84
90
|
__all__ = [
|
|
@@ -104,6 +110,11 @@ __all__ = [
|
|
|
104
110
|
"collect_figure_data",
|
|
105
111
|
# High-level helpers
|
|
106
112
|
"add_stats_from_results",
|
|
113
|
+
# FigRecipe integration
|
|
114
|
+
"save_with_recipe",
|
|
115
|
+
"load_recipe",
|
|
116
|
+
"has_figrecipe",
|
|
117
|
+
"FIGRECIPE_AVAILABLE",
|
|
107
118
|
]
|
|
108
119
|
|
|
109
120
|
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Bridge adapter for figrecipe integration.
|
|
3
|
+
|
|
4
|
+
This module provides functions to save figures with both:
|
|
5
|
+
- SigmaPlot-compatible CSV (scitex format)
|
|
6
|
+
- figrecipe YAML recipe (reproducible figures)
|
|
7
|
+
|
|
8
|
+
The FTS bundle structure:
|
|
9
|
+
figure/
|
|
10
|
+
├── recipe.yaml # Source of truth (figrecipe format)
|
|
11
|
+
├── recipe_data/ # Large arrays (if needed)
|
|
12
|
+
├── plot.csv # SigmaPlot combined CSV (derived)
|
|
13
|
+
├── plot.png # Primary image (derived)
|
|
14
|
+
└── meta.yaml # FTS metadata (optional)
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any, Dict, Optional, Union
|
|
19
|
+
|
|
20
|
+
# Check figrecipe availability
|
|
21
|
+
try:
|
|
22
|
+
import figrecipe as fr
|
|
23
|
+
from figrecipe._serializer import save_recipe as _fr_save_recipe
|
|
24
|
+
|
|
25
|
+
FIGRECIPE_AVAILABLE = True
|
|
26
|
+
except ImportError:
|
|
27
|
+
FIGRECIPE_AVAILABLE = False
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def save_with_recipe(
|
|
31
|
+
fig,
|
|
32
|
+
path: Union[str, Path],
|
|
33
|
+
include_csv: bool = True,
|
|
34
|
+
include_recipe: bool = True,
|
|
35
|
+
data_format: str = "csv",
|
|
36
|
+
dpi: int = 300,
|
|
37
|
+
**kwargs,
|
|
38
|
+
) -> Dict[str, Path]:
|
|
39
|
+
"""Save figure with both CSV and figrecipe recipe.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
fig : FigWrapper or matplotlib Figure
|
|
44
|
+
The figure to save.
|
|
45
|
+
path : str or Path
|
|
46
|
+
Output path. Can be:
|
|
47
|
+
- Directory path (creates bundle)
|
|
48
|
+
- File path with .zip extension (creates zip bundle)
|
|
49
|
+
- File path with image extension (saves image + sidecar files)
|
|
50
|
+
include_csv : bool
|
|
51
|
+
If True, save SigmaPlot-compatible CSV.
|
|
52
|
+
include_recipe : bool
|
|
53
|
+
If True, save figrecipe YAML recipe (requires figrecipe).
|
|
54
|
+
data_format : str
|
|
55
|
+
Format for recipe data: 'csv', 'npz', or 'inline'.
|
|
56
|
+
dpi : int
|
|
57
|
+
Resolution for image output.
|
|
58
|
+
**kwargs
|
|
59
|
+
Additional arguments passed to savefig.
|
|
60
|
+
|
|
61
|
+
Returns
|
|
62
|
+
-------
|
|
63
|
+
dict
|
|
64
|
+
Paths to saved files: {'image': Path, 'csv': Path, 'recipe': Path}
|
|
65
|
+
"""
|
|
66
|
+
from scitex.fts._bundle._storage import get_storage
|
|
67
|
+
|
|
68
|
+
path = Path(path)
|
|
69
|
+
result = {}
|
|
70
|
+
|
|
71
|
+
# Determine if this is a bundle (directory or zip)
|
|
72
|
+
is_bundle = path.suffix == ".zip" or path.suffix == "" or path.is_dir()
|
|
73
|
+
|
|
74
|
+
if is_bundle:
|
|
75
|
+
# Create bundle storage
|
|
76
|
+
storage = get_storage(path)
|
|
77
|
+
storage.ensure_exists()
|
|
78
|
+
|
|
79
|
+
# Get underlying matplotlib figure
|
|
80
|
+
mpl_fig = fig._fig_mpl if hasattr(fig, "_fig_mpl") else fig
|
|
81
|
+
|
|
82
|
+
# 1. Save image
|
|
83
|
+
image_path = storage.path / "plot.png"
|
|
84
|
+
mpl_fig.savefig(image_path, dpi=dpi, **kwargs)
|
|
85
|
+
result["image"] = image_path
|
|
86
|
+
|
|
87
|
+
# 2. Save SigmaPlot CSV
|
|
88
|
+
if include_csv and hasattr(fig, "export_as_csv"):
|
|
89
|
+
try:
|
|
90
|
+
csv_df = fig.export_as_csv()
|
|
91
|
+
if not csv_df.empty:
|
|
92
|
+
csv_path = storage.path / "plot.csv"
|
|
93
|
+
csv_df.to_csv(csv_path, index=False)
|
|
94
|
+
result["csv"] = csv_path
|
|
95
|
+
except Exception:
|
|
96
|
+
pass # CSV export is optional
|
|
97
|
+
|
|
98
|
+
# 3. Save figrecipe recipe
|
|
99
|
+
if include_recipe:
|
|
100
|
+
recipe_path = _save_recipe_to_path(
|
|
101
|
+
fig, storage.path / "recipe.yaml", data_format
|
|
102
|
+
)
|
|
103
|
+
if recipe_path:
|
|
104
|
+
result["recipe"] = recipe_path
|
|
105
|
+
|
|
106
|
+
else:
|
|
107
|
+
# Single file save (image + sidecars)
|
|
108
|
+
mpl_fig = fig._fig_mpl if hasattr(fig, "_fig_mpl") else fig
|
|
109
|
+
mpl_fig.savefig(path, dpi=dpi, **kwargs)
|
|
110
|
+
result["image"] = path
|
|
111
|
+
|
|
112
|
+
# Save CSV sidecar
|
|
113
|
+
if include_csv and hasattr(fig, "export_as_csv"):
|
|
114
|
+
try:
|
|
115
|
+
csv_df = fig.export_as_csv()
|
|
116
|
+
if not csv_df.empty:
|
|
117
|
+
csv_path = path.with_suffix(".csv")
|
|
118
|
+
csv_df.to_csv(csv_path, index=False)
|
|
119
|
+
result["csv"] = csv_path
|
|
120
|
+
except Exception:
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
# Save recipe sidecar
|
|
124
|
+
if include_recipe:
|
|
125
|
+
recipe_path = _save_recipe_to_path(
|
|
126
|
+
fig, path.with_suffix(".yaml"), data_format
|
|
127
|
+
)
|
|
128
|
+
if recipe_path:
|
|
129
|
+
result["recipe"] = recipe_path
|
|
130
|
+
|
|
131
|
+
return result
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _save_recipe_to_path(
|
|
135
|
+
fig,
|
|
136
|
+
path: Path,
|
|
137
|
+
data_format: str = "csv",
|
|
138
|
+
) -> Optional[Path]:
|
|
139
|
+
"""Save figrecipe recipe if available.
|
|
140
|
+
|
|
141
|
+
Parameters
|
|
142
|
+
----------
|
|
143
|
+
fig : FigWrapper
|
|
144
|
+
Figure with optional _figrecipe_recorder attribute.
|
|
145
|
+
path : Path
|
|
146
|
+
Output path for recipe.yaml.
|
|
147
|
+
data_format : str
|
|
148
|
+
Format for data: 'csv', 'npz', or 'inline'.
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
Path or None
|
|
153
|
+
Path to saved recipe, or None if not available.
|
|
154
|
+
"""
|
|
155
|
+
if not FIGRECIPE_AVAILABLE:
|
|
156
|
+
return None
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
# Check if figure has figrecipe recorder
|
|
160
|
+
if hasattr(fig, "_figrecipe_recorder") and fig._figrecipe_enabled:
|
|
161
|
+
recorder = fig._figrecipe_recorder
|
|
162
|
+
figure_record = recorder.figure_record
|
|
163
|
+
|
|
164
|
+
# Capture current figure state into record
|
|
165
|
+
_capture_figure_state(fig, figure_record)
|
|
166
|
+
|
|
167
|
+
# Save using figrecipe's serializer
|
|
168
|
+
_fr_save_recipe(
|
|
169
|
+
figure_record, path, include_data=True, data_format=data_format
|
|
170
|
+
)
|
|
171
|
+
return path
|
|
172
|
+
|
|
173
|
+
# Alternative: if figure was created with fr.subplots() directly
|
|
174
|
+
if hasattr(fig, "save_recipe"):
|
|
175
|
+
fig.save_recipe(path, include_data=True, data_format=data_format)
|
|
176
|
+
return path
|
|
177
|
+
|
|
178
|
+
except Exception:
|
|
179
|
+
pass # Recipe saving is optional
|
|
180
|
+
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _capture_figure_state(fig, figure_record):
|
|
185
|
+
"""Capture current figure state into the record.
|
|
186
|
+
|
|
187
|
+
This syncs the matplotlib figure state with the figrecipe record,
|
|
188
|
+
ensuring the recipe reflects the final figure appearance.
|
|
189
|
+
"""
|
|
190
|
+
try:
|
|
191
|
+
mpl_fig = fig._fig_mpl if hasattr(fig, "_fig_mpl") else fig
|
|
192
|
+
|
|
193
|
+
# Update figure dimensions
|
|
194
|
+
figsize = mpl_fig.get_size_inches()
|
|
195
|
+
figure_record.figsize = list(figsize)
|
|
196
|
+
figure_record.dpi = int(mpl_fig.dpi)
|
|
197
|
+
|
|
198
|
+
# Capture style from scitex metadata if available
|
|
199
|
+
if hasattr(mpl_fig, "_scitex_theme"):
|
|
200
|
+
if not hasattr(figure_record, "style") or figure_record.style is None:
|
|
201
|
+
figure_record.style = {}
|
|
202
|
+
figure_record.style["theme"] = mpl_fig._scitex_theme
|
|
203
|
+
|
|
204
|
+
except Exception:
|
|
205
|
+
pass # Non-critical
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def load_recipe(
|
|
209
|
+
path: Union[str, Path],
|
|
210
|
+
) -> Any:
|
|
211
|
+
"""Load figrecipe recipe from FTS bundle.
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
path : str or Path
|
|
216
|
+
Path to bundle directory, zip file, or recipe.yaml.
|
|
217
|
+
|
|
218
|
+
Returns
|
|
219
|
+
-------
|
|
220
|
+
tuple
|
|
221
|
+
(fig, axes) reproduced from recipe.
|
|
222
|
+
"""
|
|
223
|
+
if not FIGRECIPE_AVAILABLE:
|
|
224
|
+
raise ImportError("figrecipe is required for loading recipes")
|
|
225
|
+
|
|
226
|
+
path = Path(path)
|
|
227
|
+
|
|
228
|
+
# Handle bundle paths
|
|
229
|
+
if path.is_dir():
|
|
230
|
+
recipe_path = path / "recipe.yaml"
|
|
231
|
+
elif path.suffix == ".zip":
|
|
232
|
+
# figrecipe can handle zip files directly
|
|
233
|
+
recipe_path = path
|
|
234
|
+
else:
|
|
235
|
+
recipe_path = path
|
|
236
|
+
|
|
237
|
+
return fr.reproduce(recipe_path)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def has_figrecipe() -> bool:
|
|
241
|
+
"""Check if figrecipe is available."""
|
|
242
|
+
return FIGRECIPE_AVAILABLE
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
# EOF
|
scitex/bridge/_helpers.py
CHANGED
|
@@ -11,7 +11,8 @@ multiple modules, abstracting away backend-specific details.
|
|
|
11
11
|
|
|
12
12
|
from typing import Union, List, Optional, Literal
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
# StatResult is now a dict - the GUI-specific StatResult is deprecated
|
|
15
|
+
StatResult = dict
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
def add_stats_from_results(
|
scitex/bridge/_plt_vis.py
CHANGED
|
@@ -14,16 +14,29 @@ Provides adapters to:
|
|
|
14
14
|
from typing import Optional, Dict, Any, List, Tuple, Union
|
|
15
15
|
import warnings
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
# Legacy model imports - may not be available (deleted module)
|
|
18
|
+
try:
|
|
19
|
+
from scitex.fig.model import (
|
|
20
|
+
FigureModel,
|
|
21
|
+
AxesModel,
|
|
22
|
+
PlotModel,
|
|
23
|
+
AnnotationModel,
|
|
24
|
+
GuideModel,
|
|
25
|
+
PlotStyle,
|
|
26
|
+
AxesStyle,
|
|
27
|
+
TextStyle,
|
|
28
|
+
)
|
|
29
|
+
VIS_MODEL_AVAILABLE = True
|
|
30
|
+
except ImportError:
|
|
31
|
+
FigureModel = None
|
|
32
|
+
AxesModel = None
|
|
33
|
+
PlotModel = None
|
|
34
|
+
AnnotationModel = None
|
|
35
|
+
GuideModel = None
|
|
36
|
+
PlotStyle = None
|
|
37
|
+
AxesStyle = None
|
|
38
|
+
TextStyle = None
|
|
39
|
+
VIS_MODEL_AVAILABLE = False
|
|
27
40
|
|
|
28
41
|
|
|
29
42
|
def figure_to_vis_model(
|
scitex/bridge/_stats_plt.py
CHANGED
|
@@ -28,7 +28,11 @@ the caller intends (typically data coordinates unless transform is set).
|
|
|
28
28
|
from typing import Optional, Dict, Any, Union, List
|
|
29
29
|
import warnings
|
|
30
30
|
|
|
31
|
-
from
|
|
31
|
+
# Import GUI classes from FTS (single source of truth)
|
|
32
|
+
from scitex.fts._stats import Position
|
|
33
|
+
|
|
34
|
+
# StatResult is now a dict - the GUI-specific StatResult is deprecated
|
|
35
|
+
StatResult = dict
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
def format_stat_for_plot(
|
|
@@ -205,10 +209,19 @@ def _parse_stat_annotation(text: str) -> Optional[StatResult]:
|
|
|
205
209
|
Optional[StatResult]
|
|
206
210
|
Parsed StatResult or None if not parseable
|
|
207
211
|
"""
|
|
208
|
-
from scitex.schema import create_stat_result
|
|
209
|
-
|
|
210
212
|
text = text.strip()
|
|
211
213
|
|
|
214
|
+
def _create_stat_dict(test_type, statistic_name, statistic_value, p_value):
|
|
215
|
+
"""Create a simple stat result dict."""
|
|
216
|
+
from scitex.stats.utils import p2stars
|
|
217
|
+
return {
|
|
218
|
+
"test_type": test_type,
|
|
219
|
+
"test_category": "other",
|
|
220
|
+
"statistic": {"name": statistic_name, "value": statistic_value},
|
|
221
|
+
"p_value": p_value,
|
|
222
|
+
"stars": p2stars(p_value, ns_symbol=False),
|
|
223
|
+
}
|
|
224
|
+
|
|
212
225
|
# Try to detect asterisks pattern
|
|
213
226
|
if text in ["*", "**", "***", "ns", "n.s."]:
|
|
214
227
|
stars = text.replace("n.s.", "ns")
|
|
@@ -219,7 +232,7 @@ def _parse_stat_annotation(text: str) -> Optional[StatResult]:
|
|
|
219
232
|
"*": 0.03,
|
|
220
233
|
"ns": 0.5,
|
|
221
234
|
}.get(stars, 0.5)
|
|
222
|
-
return
|
|
235
|
+
return _create_stat_dict(
|
|
223
236
|
test_type="unknown",
|
|
224
237
|
statistic_name="stat",
|
|
225
238
|
statistic_value=0.0,
|
|
@@ -241,7 +254,7 @@ def _parse_stat_annotation(text: str) -> Optional[StatResult]:
|
|
|
241
254
|
"*": 0.03,
|
|
242
255
|
"ns": 0.5,
|
|
243
256
|
}.get(stars, 0.5)
|
|
244
|
-
return
|
|
257
|
+
return _create_stat_dict(
|
|
245
258
|
test_type="unknown",
|
|
246
259
|
statistic_name=stat_name,
|
|
247
260
|
statistic_value=stat_value,
|
scitex/bridge/_stats_vis.py
CHANGED
|
@@ -26,8 +26,22 @@ When bridging between plt and vis, coordinate transformation may be needed.
|
|
|
26
26
|
|
|
27
27
|
from typing import Optional, Dict, Any, List, Tuple
|
|
28
28
|
|
|
29
|
-
from
|
|
30
|
-
from scitex.
|
|
29
|
+
# Import GUI classes from FTS (single source of truth)
|
|
30
|
+
from scitex.fts._stats import Position, StatPositioning
|
|
31
|
+
|
|
32
|
+
# Legacy model imports - may not be available
|
|
33
|
+
try:
|
|
34
|
+
from scitex.fig.model import AnnotationModel, FigureModel, AxesModel, TextStyle
|
|
35
|
+
VIS_MODEL_AVAILABLE = True
|
|
36
|
+
except ImportError:
|
|
37
|
+
AnnotationModel = None
|
|
38
|
+
FigureModel = None
|
|
39
|
+
AxesModel = None
|
|
40
|
+
TextStyle = None
|
|
41
|
+
VIS_MODEL_AVAILABLE = False
|
|
42
|
+
|
|
43
|
+
# StatResult placeholder for type hints (actual usage is through dict)
|
|
44
|
+
StatResult = dict # Use dict as StatResult is deprecated
|
|
31
45
|
|
|
32
46
|
|
|
33
47
|
def stat_result_to_annotation(
|
scitex/browser/__init__.py
CHANGED
|
@@ -1,56 +1,96 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
2
|
# SciTeX Browser Utilities - Universal Playwright helpers organized by category
|
|
4
3
|
# ----------------------------------------
|
|
5
4
|
|
|
5
|
+
# All browser utilities require playwright - make them optional
|
|
6
|
+
|
|
6
7
|
# Debugging utilities
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
8
|
+
try:
|
|
9
|
+
from .debugging import (
|
|
10
|
+
# Sync browser session for zombie prevention
|
|
11
|
+
SyncBrowserSession,
|
|
12
|
+
# Test monitoring (periodic screenshots via scitex.capture)
|
|
13
|
+
TestMonitor,
|
|
14
|
+
browser_logger,
|
|
15
|
+
collect_console_logs,
|
|
16
|
+
collect_console_logs_detailed,
|
|
17
|
+
create_browser_session_fixture,
|
|
18
|
+
create_failure_capture_fixture,
|
|
19
|
+
create_test_monitor_fixture,
|
|
20
|
+
format_logs_devtools_style,
|
|
21
|
+
highlight_element_async,
|
|
22
|
+
# Visual cursor/feedback utilities (sync and async)
|
|
23
|
+
inject_visual_effects,
|
|
24
|
+
inject_visual_effects_async,
|
|
25
|
+
monitor_test,
|
|
26
|
+
save_failure_artifacts,
|
|
27
|
+
# Failure capture utilities (mirrors console-interceptor.ts)
|
|
28
|
+
setup_console_interceptor,
|
|
29
|
+
show_click_effect,
|
|
30
|
+
show_click_effect_async,
|
|
31
|
+
show_cursor_at,
|
|
32
|
+
show_cursor_at_async,
|
|
33
|
+
show_grid_async,
|
|
34
|
+
show_step,
|
|
35
|
+
show_step_async,
|
|
36
|
+
show_test_result,
|
|
37
|
+
show_test_result_async,
|
|
38
|
+
sync_browser_session,
|
|
39
|
+
)
|
|
40
|
+
except ImportError:
|
|
41
|
+
browser_logger = None
|
|
42
|
+
show_grid_async = None
|
|
43
|
+
highlight_element_async = None
|
|
44
|
+
inject_visual_effects = None
|
|
45
|
+
inject_visual_effects_async = None
|
|
46
|
+
show_cursor_at = None
|
|
47
|
+
show_cursor_at_async = None
|
|
48
|
+
show_click_effect = None
|
|
49
|
+
show_click_effect_async = None
|
|
50
|
+
show_step = None
|
|
51
|
+
show_step_async = None
|
|
52
|
+
show_test_result = None
|
|
53
|
+
show_test_result_async = None
|
|
54
|
+
setup_console_interceptor = None
|
|
55
|
+
collect_console_logs = None
|
|
56
|
+
collect_console_logs_detailed = None
|
|
57
|
+
format_logs_devtools_style = None
|
|
58
|
+
save_failure_artifacts = None
|
|
59
|
+
create_failure_capture_fixture = None
|
|
60
|
+
TestMonitor = None
|
|
61
|
+
create_test_monitor_fixture = None
|
|
62
|
+
monitor_test = None
|
|
63
|
+
SyncBrowserSession = None
|
|
64
|
+
sync_browser_session = None
|
|
65
|
+
create_browser_session_fixture = None
|
|
38
66
|
|
|
39
67
|
# PDF utilities
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
68
|
+
try:
|
|
69
|
+
from .pdf import (
|
|
70
|
+
click_download_for_chrome_pdf_viewer_async,
|
|
71
|
+
detect_chrome_pdf_viewer_async,
|
|
72
|
+
)
|
|
73
|
+
except ImportError:
|
|
74
|
+
detect_chrome_pdf_viewer_async = None
|
|
75
|
+
click_download_for_chrome_pdf_viewer_async = None
|
|
44
76
|
|
|
45
77
|
# Interaction utilities
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
78
|
+
try:
|
|
79
|
+
from .interaction import (
|
|
80
|
+
PopupHandler,
|
|
81
|
+
click_center_async,
|
|
82
|
+
click_with_fallbacks_async,
|
|
83
|
+
close_popups_async,
|
|
84
|
+
ensure_no_popups_async,
|
|
85
|
+
fill_with_fallbacks_async,
|
|
86
|
+
)
|
|
87
|
+
except ImportError:
|
|
88
|
+
click_center_async = None
|
|
89
|
+
click_with_fallbacks_async = None
|
|
90
|
+
fill_with_fallbacks_async = None
|
|
91
|
+
PopupHandler = None
|
|
92
|
+
close_popups_async = None
|
|
93
|
+
ensure_no_popups_async = None
|
|
54
94
|
|
|
55
95
|
__all__ = [
|
|
56
96
|
# Debugging
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"""Browser automation utilities."""
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# Optional: CookieAutoAcceptor requires playwright
|
|
4
|
+
try:
|
|
5
|
+
from .CookieHandler import CookieAutoAcceptor
|
|
6
|
+
except ImportError:
|
|
7
|
+
CookieAutoAcceptor = None
|
|
4
8
|
|
|
5
9
|
__all__ = [
|
|
6
10
|
"CookieAutoAcceptor",
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
2
|
# Timestamp: "2025-08-07 20:04:42 (ywatanabe)"
|
|
4
3
|
# File: /home/ywatanabe/proj/scitex_repo/src/scitex/scholar/browser/local/_BrowserMixin.py
|
|
5
4
|
# ----------------------------------------
|
|
6
5
|
from __future__ import annotations
|
|
6
|
+
|
|
7
7
|
import os
|
|
8
8
|
|
|
9
9
|
__FILE__ = __file__
|
|
10
10
|
__DIR__ = os.path.dirname(__FILE__)
|
|
11
11
|
# ----------------------------------------
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
# Optional dependencies - browser module requires these
|
|
14
|
+
try:
|
|
15
|
+
import aiohttp
|
|
16
|
+
except ImportError:
|
|
17
|
+
aiohttp = None
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from playwright.async_api import Browser, async_playwright
|
|
21
|
+
except ImportError:
|
|
22
|
+
Browser = None
|
|
23
|
+
async_playwright = None
|
|
15
24
|
|
|
16
|
-
|
|
25
|
+
try:
|
|
26
|
+
from scitex.browser.automation import CookieAutoAcceptor
|
|
27
|
+
except ImportError:
|
|
28
|
+
CookieAutoAcceptor = None
|
|
17
29
|
|
|
18
30
|
|
|
19
31
|
class BrowserMixin:
|
|
@@ -236,6 +248,7 @@ class BrowserMixin:
|
|
|
236
248
|
def main(args):
|
|
237
249
|
"""Demonstrate BrowserMixin functionality."""
|
|
238
250
|
import asyncio
|
|
251
|
+
|
|
239
252
|
from scitex.browser.core import BrowserMixin
|
|
240
253
|
|
|
241
254
|
class DemoBrowser(BrowserMixin):
|
scitex/browser/core/__init__.py
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
"""Core browser management components."""
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
# Optional: BrowserMixin requires playwright
|
|
4
|
+
try:
|
|
5
|
+
from .BrowserMixin import BrowserMixin
|
|
6
|
+
except ImportError:
|
|
7
|
+
BrowserMixin = None
|
|
8
|
+
|
|
9
|
+
# Optional: ChromeProfileManager may have dependencies
|
|
10
|
+
try:
|
|
11
|
+
from .ChromeProfileManager import ChromeProfileManager
|
|
12
|
+
except ImportError:
|
|
13
|
+
ChromeProfileManager = None
|
|
5
14
|
|
|
6
15
|
__all__ = [
|
|
7
16
|
"BrowserMixin",
|