scitex 2.0.0__py2.py3-none-any.whl → 2.1.0__py2.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 +53 -15
- scitex/__main__.py +72 -26
- scitex/__version__.py +1 -1
- scitex/_sh.py +145 -23
- scitex/ai/__init__.py +30 -16
- scitex/ai/_gen_ai/_Anthropic.py +5 -7
- scitex/ai/_gen_ai/_BaseGenAI.py +2 -2
- scitex/ai/_gen_ai/_DeepSeek.py +10 -2
- scitex/ai/_gen_ai/_Google.py +2 -2
- scitex/ai/_gen_ai/_Llama.py +2 -2
- scitex/ai/_gen_ai/_OpenAI.py +2 -2
- scitex/ai/_gen_ai/_PARAMS.py +51 -65
- scitex/ai/_gen_ai/_Perplexity.py +2 -2
- scitex/ai/_gen_ai/__init__.py +25 -14
- scitex/ai/_gen_ai/_format_output_func.py +4 -4
- scitex/ai/classification/{classifier_server.py → Classifier.py} +5 -5
- scitex/ai/classification/CrossValidationExperiment.py +374 -0
- scitex/ai/classification/__init__.py +43 -4
- scitex/ai/classification/reporters/_BaseClassificationReporter.py +281 -0
- scitex/ai/classification/reporters/_ClassificationReporter.py +773 -0
- scitex/ai/classification/reporters/_MultiClassificationReporter.py +406 -0
- scitex/ai/classification/reporters/_SingleClassificationReporter.py +1834 -0
- scitex/ai/classification/reporters/__init__.py +11 -0
- scitex/ai/classification/reporters/reporter_utils/_Plotter.py +1028 -0
- scitex/ai/classification/reporters/reporter_utils/__init__.py +80 -0
- scitex/ai/classification/reporters/reporter_utils/aggregation.py +457 -0
- scitex/ai/classification/reporters/reporter_utils/data_models.py +313 -0
- scitex/ai/classification/reporters/reporter_utils/reporting.py +1056 -0
- scitex/ai/classification/reporters/reporter_utils/storage.py +221 -0
- scitex/ai/classification/reporters/reporter_utils/validation.py +395 -0
- scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +568 -0
- scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +688 -0
- scitex/ai/classification/timeseries/_TimeSeriesMetadata.py +139 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +1716 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +1685 -0
- scitex/ai/classification/timeseries/_TimeSeriesStrategy.py +84 -0
- scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +610 -0
- scitex/ai/classification/timeseries/__init__.py +39 -0
- scitex/ai/classification/timeseries/_normalize_timestamp.py +436 -0
- scitex/ai/clustering/_umap.py +2 -2
- scitex/ai/feature_extraction/vit.py +1 -0
- scitex/ai/feature_selection/__init__.py +30 -0
- scitex/ai/feature_selection/feature_selection.py +364 -0
- scitex/ai/loss/multi_task_loss.py +1 -1
- scitex/ai/metrics/__init__.py +51 -4
- scitex/ai/metrics/_calc_bacc.py +61 -0
- scitex/ai/metrics/_calc_bacc_from_conf_mat.py +38 -0
- scitex/ai/metrics/_calc_clf_report.py +78 -0
- scitex/ai/metrics/_calc_conf_mat.py +93 -0
- scitex/ai/metrics/_calc_feature_importance.py +183 -0
- scitex/ai/metrics/_calc_mcc.py +61 -0
- scitex/ai/metrics/_calc_pre_rec_auc.py +116 -0
- scitex/ai/metrics/_calc_roc_auc.py +110 -0
- scitex/ai/metrics/_calc_seizure_prediction_metrics.py +490 -0
- scitex/ai/metrics/{silhoute_score_block.py → _calc_silhouette_score.py} +15 -8
- scitex/ai/metrics/_normalize_labels.py +83 -0
- scitex/ai/plt/__init__.py +47 -8
- scitex/ai/plt/{_conf_mat.py → _plot_conf_mat.py} +158 -87
- scitex/ai/plt/_plot_feature_importance.py +323 -0
- scitex/ai/plt/_plot_learning_curve.py +345 -0
- scitex/ai/plt/_plot_optuna_study.py +225 -0
- scitex/ai/plt/_plot_pre_rec_curve.py +290 -0
- scitex/ai/plt/_plot_roc_curve.py +255 -0
- scitex/ai/training/{learning_curve_logger.py → _LearningCurveLogger.py} +197 -213
- scitex/ai/training/__init__.py +2 -2
- scitex/ai/utils/grid_search.py +3 -3
- scitex/benchmark/__init__.py +52 -0
- scitex/benchmark/benchmark.py +400 -0
- scitex/benchmark/monitor.py +370 -0
- scitex/benchmark/profiler.py +297 -0
- scitex/browser/__init__.py +48 -0
- scitex/browser/automation/CookieHandler.py +216 -0
- scitex/browser/automation/__init__.py +7 -0
- scitex/browser/collaboration/__init__.py +55 -0
- scitex/browser/collaboration/auth_helpers.py +94 -0
- scitex/browser/collaboration/collaborative_agent.py +136 -0
- scitex/browser/collaboration/credential_manager.py +188 -0
- scitex/browser/collaboration/interactive_panel.py +400 -0
- scitex/browser/collaboration/persistent_browser.py +170 -0
- scitex/browser/collaboration/shared_session.py +383 -0
- scitex/browser/collaboration/standard_interactions.py +246 -0
- scitex/browser/collaboration/visual_feedback.py +181 -0
- scitex/browser/core/BrowserMixin.py +326 -0
- scitex/browser/core/ChromeProfileManager.py +446 -0
- scitex/browser/core/__init__.py +9 -0
- scitex/browser/debugging/__init__.py +18 -0
- scitex/browser/debugging/_browser_logger.py +657 -0
- scitex/browser/debugging/_highlight_element.py +143 -0
- scitex/browser/debugging/_show_grid.py +154 -0
- scitex/browser/interaction/__init__.py +24 -0
- scitex/browser/interaction/click_center.py +149 -0
- scitex/browser/interaction/click_with_fallbacks.py +206 -0
- scitex/browser/interaction/close_popups.py +498 -0
- scitex/browser/interaction/fill_with_fallbacks.py +209 -0
- scitex/browser/pdf/__init__.py +14 -0
- scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +200 -0
- scitex/browser/pdf/detect_chrome_pdf_viewer.py +198 -0
- scitex/browser/remote/CaptchaHandler.py +434 -0
- scitex/browser/remote/ZenRowsAPIClient.py +347 -0
- scitex/browser/remote/ZenRowsBrowserManager.py +570 -0
- scitex/browser/remote/__init__.py +11 -0
- scitex/browser/stealth/HumanBehavior.py +344 -0
- scitex/browser/stealth/StealthManager.py +1008 -0
- scitex/browser/stealth/__init__.py +9 -0
- scitex/browser/template.py +122 -0
- scitex/capture/__init__.py +110 -0
- scitex/capture/__main__.py +25 -0
- scitex/capture/capture.py +848 -0
- scitex/capture/cli.py +233 -0
- scitex/capture/gif.py +344 -0
- scitex/capture/mcp_server.py +961 -0
- scitex/capture/session.py +70 -0
- scitex/capture/utils.py +705 -0
- scitex/cli/__init__.py +17 -0
- scitex/cli/cloud.py +447 -0
- scitex/cli/main.py +42 -0
- scitex/cli/scholar.py +280 -0
- scitex/context/_suppress_output.py +5 -3
- scitex/db/__init__.py +30 -3
- scitex/db/__main__.py +75 -0
- scitex/db/_check_health.py +381 -0
- scitex/db/_delete_duplicates.py +25 -386
- scitex/db/_inspect.py +335 -114
- scitex/db/_inspect_optimized.py +301 -0
- scitex/db/{_PostgreSQL.py → _postgresql/_PostgreSQL.py} +3 -3
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BackupMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BatchMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_BlobMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_ConnectionMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_MaintenanceMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_QueryMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_SchemaMixin.py +1 -1
- scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_TransactionMixin.py +1 -1
- scitex/db/_postgresql/__init__.py +6 -0
- scitex/db/_sqlite3/_SQLite3.py +210 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ArrayMixin.py +581 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ArrayMixin_v01-need-_hash-col.py +517 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_BatchMixin.py +1 -1
- scitex/db/_sqlite3/_SQLite3Mixins/_BlobMixin.py +281 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ColumnMixin.py +548 -0
- scitex/db/_sqlite3/_SQLite3Mixins/_ColumnMixin_v01-indentation-issues.py +583 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_ConnectionMixin.py +29 -13
- scitex/db/_sqlite3/_SQLite3Mixins/_GitMixin.py +583 -0
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_ImportExportMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_IndexMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_MaintenanceMixin.py +2 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_QueryMixin.py +37 -10
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_RowMixin.py +46 -6
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_TableMixin.py +56 -10
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/_TransactionMixin.py +1 -1
- scitex/db/{_SQLite3Mixins → _sqlite3/_SQLite3Mixins}/__init__.py +14 -2
- scitex/db/_sqlite3/__init__.py +7 -0
- scitex/db/_sqlite3/_delete_duplicates.py +274 -0
- scitex/decorators/__init__.py +2 -0
- scitex/decorators/_cache_disk.py +13 -5
- scitex/decorators/_cache_disk_async.py +49 -0
- scitex/decorators/_deprecated.py +175 -10
- scitex/decorators/_timeout.py +1 -1
- scitex/dev/_analyze_code_flow.py +2 -2
- scitex/dict/_DotDict.py +73 -15
- scitex/dict/_DotDict_v01-not-handling-recursive-instantiations.py +442 -0
- scitex/dict/_DotDict_v02-not-serializing-Path-object.py +446 -0
- scitex/dict/__init__.py +2 -0
- scitex/dict/_flatten.py +27 -0
- scitex/dsp/_crop.py +2 -2
- scitex/dsp/_demo_sig.py +2 -2
- scitex/dsp/_detect_ripples.py +2 -2
- scitex/dsp/_hilbert.py +2 -2
- scitex/dsp/_listen.py +6 -6
- scitex/dsp/_modulation_index.py +2 -2
- scitex/dsp/_pac.py +1 -1
- scitex/dsp/_psd.py +2 -2
- scitex/dsp/_resample.py +2 -1
- scitex/dsp/_time.py +3 -2
- scitex/dsp/_wavelet.py +3 -2
- scitex/dsp/add_noise.py +2 -2
- scitex/dsp/example.py +1 -0
- scitex/dsp/filt.py +10 -9
- scitex/dsp/template.py +3 -2
- scitex/dsp/utils/_differential_bandpass_filters.py +1 -1
- scitex/dsp/utils/pac.py +2 -2
- scitex/dt/_normalize_timestamp.py +432 -0
- scitex/errors.py +572 -0
- scitex/gen/_DimHandler.py +2 -2
- scitex/gen/__init__.py +37 -7
- scitex/gen/_deprecated_close.py +80 -0
- scitex/gen/_deprecated_start.py +26 -0
- scitex/gen/_detect_environment.py +152 -0
- scitex/gen/_detect_notebook_path.py +169 -0
- scitex/gen/_embed.py +6 -2
- scitex/gen/_get_notebook_path.py +257 -0
- scitex/gen/_less.py +1 -1
- scitex/gen/_list_packages.py +2 -2
- scitex/gen/_norm.py +44 -9
- scitex/gen/_norm_cache.py +269 -0
- scitex/gen/_src.py +3 -5
- scitex/gen/_title_case.py +3 -3
- scitex/io/__init__.py +28 -6
- scitex/io/_glob.py +13 -7
- scitex/io/_load.py +108 -21
- scitex/io/_load_cache.py +303 -0
- scitex/io/_load_configs.py +40 -15
- scitex/io/{_H5Explorer.py → _load_modules/_H5Explorer.py} +80 -17
- scitex/io/_load_modules/_ZarrExplorer.py +114 -0
- scitex/io/_load_modules/_bibtex.py +207 -0
- scitex/io/_load_modules/_hdf5.py +53 -178
- scitex/io/_load_modules/_json.py +5 -3
- scitex/io/_load_modules/_pdf.py +871 -16
- scitex/io/_load_modules/_sqlite3.py +15 -0
- scitex/io/_load_modules/_txt.py +41 -12
- scitex/io/_load_modules/_yaml.py +4 -3
- scitex/io/_load_modules/_zarr.py +126 -0
- scitex/io/_save.py +429 -171
- scitex/io/_save_modules/__init__.py +6 -0
- scitex/io/_save_modules/_bibtex.py +194 -0
- scitex/io/_save_modules/_csv.py +8 -4
- scitex/io/_save_modules/_excel.py +174 -15
- scitex/io/_save_modules/_hdf5.py +251 -226
- scitex/io/_save_modules/_image.py +1 -3
- scitex/io/_save_modules/_json.py +49 -4
- scitex/io/_save_modules/_listed_dfs_as_csv.py +1 -3
- scitex/io/_save_modules/_listed_scalars_as_csv.py +1 -3
- scitex/io/_save_modules/_tex.py +277 -0
- scitex/io/_save_modules/_yaml.py +42 -3
- scitex/io/_save_modules/_zarr.py +160 -0
- scitex/io/utils/__init__.py +20 -0
- scitex/io/utils/h5_to_zarr.py +616 -0
- scitex/linalg/_geometric_median.py +6 -2
- scitex/{gen/_tee.py → logging/_Tee.py} +43 -84
- scitex/logging/__init__.py +122 -0
- scitex/logging/_config.py +158 -0
- scitex/logging/_context.py +103 -0
- scitex/logging/_formatters.py +128 -0
- scitex/logging/_handlers.py +64 -0
- scitex/logging/_levels.py +35 -0
- scitex/logging/_logger.py +163 -0
- scitex/logging/_print_capture.py +95 -0
- scitex/ml/__init__.py +69 -0
- scitex/{ai/genai/anthropic.py → ml/_gen_ai/_Anthropic.py} +13 -19
- scitex/{ai/genai/base_genai.py → ml/_gen_ai/_BaseGenAI.py} +5 -5
- scitex/{ai/genai/deepseek.py → ml/_gen_ai/_DeepSeek.py} +11 -16
- scitex/{ai/genai/google.py → ml/_gen_ai/_Google.py} +7 -15
- scitex/{ai/genai/groq.py → ml/_gen_ai/_Groq.py} +1 -8
- scitex/{ai/genai/llama.py → ml/_gen_ai/_Llama.py} +3 -16
- scitex/{ai/genai/openai.py → ml/_gen_ai/_OpenAI.py} +3 -3
- scitex/{ai/genai/params.py → ml/_gen_ai/_PARAMS.py} +51 -65
- scitex/{ai/genai/perplexity.py → ml/_gen_ai/_Perplexity.py} +3 -14
- scitex/ml/_gen_ai/__init__.py +43 -0
- scitex/{ai/genai/calc_cost.py → ml/_gen_ai/_calc_cost.py} +1 -1
- scitex/{ai/genai/format_output_func.py → ml/_gen_ai/_format_output_func.py} +4 -4
- scitex/{ai/genai/genai_factory.py → ml/_gen_ai/_genai_factory.py} +8 -8
- scitex/ml/activation/__init__.py +8 -0
- scitex/ml/activation/_define.py +11 -0
- scitex/{ai/classifier_server.py → ml/classification/Classifier.py} +5 -5
- scitex/ml/classification/CrossValidationExperiment.py +374 -0
- scitex/ml/classification/__init__.py +46 -0
- scitex/ml/classification/reporters/_BaseClassificationReporter.py +281 -0
- scitex/ml/classification/reporters/_ClassificationReporter.py +773 -0
- scitex/ml/classification/reporters/_MultiClassificationReporter.py +406 -0
- scitex/ml/classification/reporters/_SingleClassificationReporter.py +1834 -0
- scitex/ml/classification/reporters/__init__.py +11 -0
- scitex/ml/classification/reporters/reporter_utils/_Plotter.py +1028 -0
- scitex/ml/classification/reporters/reporter_utils/__init__.py +80 -0
- scitex/ml/classification/reporters/reporter_utils/aggregation.py +457 -0
- scitex/ml/classification/reporters/reporter_utils/data_models.py +313 -0
- scitex/ml/classification/reporters/reporter_utils/reporting.py +1056 -0
- scitex/ml/classification/reporters/reporter_utils/storage.py +221 -0
- scitex/ml/classification/reporters/reporter_utils/validation.py +395 -0
- scitex/ml/classification/timeseries/_TimeSeriesBlockingSplit.py +568 -0
- scitex/ml/classification/timeseries/_TimeSeriesCalendarSplit.py +688 -0
- scitex/ml/classification/timeseries/_TimeSeriesMetadata.py +139 -0
- scitex/ml/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +1716 -0
- scitex/ml/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +1685 -0
- scitex/ml/classification/timeseries/_TimeSeriesStrategy.py +84 -0
- scitex/ml/classification/timeseries/_TimeSeriesStratifiedSplit.py +610 -0
- scitex/ml/classification/timeseries/__init__.py +39 -0
- scitex/ml/classification/timeseries/_normalize_timestamp.py +436 -0
- scitex/ml/clustering/__init__.py +11 -0
- scitex/ml/clustering/_pca.py +115 -0
- scitex/ml/clustering/_umap.py +376 -0
- scitex/ml/feature_extraction/__init__.py +56 -0
- scitex/ml/feature_extraction/vit.py +149 -0
- scitex/ml/feature_selection/__init__.py +30 -0
- scitex/ml/feature_selection/feature_selection.py +364 -0
- scitex/ml/loss/_L1L2Losses.py +34 -0
- scitex/ml/loss/__init__.py +12 -0
- scitex/ml/loss/multi_task_loss.py +47 -0
- scitex/ml/metrics/__init__.py +56 -0
- scitex/ml/metrics/_calc_bacc.py +61 -0
- scitex/ml/metrics/_calc_bacc_from_conf_mat.py +38 -0
- scitex/ml/metrics/_calc_clf_report.py +78 -0
- scitex/ml/metrics/_calc_conf_mat.py +93 -0
- scitex/ml/metrics/_calc_feature_importance.py +183 -0
- scitex/ml/metrics/_calc_mcc.py +61 -0
- scitex/ml/metrics/_calc_pre_rec_auc.py +116 -0
- scitex/ml/metrics/_calc_roc_auc.py +110 -0
- scitex/ml/metrics/_calc_seizure_prediction_metrics.py +490 -0
- scitex/ml/metrics/_calc_silhouette_score.py +503 -0
- scitex/ml/metrics/_normalize_labels.py +83 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/__init__.py +0 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/__init__.py +3 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger.py +207 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger2020.py +238 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/ranger913A.py +215 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/ranger/rangerqh.py +184 -0
- scitex/ml/optim/Ranger_Deep_Learning_Optimizer/setup.py +24 -0
- scitex/ml/optim/__init__.py +13 -0
- scitex/ml/optim/_get_set.py +31 -0
- scitex/ml/optim/_optimizers.py +71 -0
- scitex/ml/plt/__init__.py +60 -0
- scitex/ml/plt/_plot_conf_mat.py +663 -0
- scitex/ml/plt/_plot_feature_importance.py +323 -0
- scitex/ml/plt/_plot_learning_curve.py +345 -0
- scitex/ml/plt/_plot_optuna_study.py +225 -0
- scitex/ml/plt/_plot_pre_rec_curve.py +290 -0
- scitex/ml/plt/_plot_roc_curve.py +255 -0
- scitex/ml/sk/__init__.py +11 -0
- scitex/ml/sk/_clf.py +58 -0
- scitex/ml/sk/_to_sktime.py +100 -0
- scitex/ml/sklearn/__init__.py +26 -0
- scitex/ml/sklearn/clf.py +58 -0
- scitex/ml/sklearn/to_sktime.py +100 -0
- scitex/{ai/training/early_stopping.py → ml/training/_EarlyStopping.py} +1 -2
- scitex/{ai → ml/training}/_LearningCurveLogger.py +198 -242
- scitex/ml/training/__init__.py +7 -0
- scitex/ml/utils/__init__.py +22 -0
- scitex/ml/utils/_check_params.py +50 -0
- scitex/ml/utils/_default_dataset.py +46 -0
- scitex/ml/utils/_format_samples_for_sktime.py +26 -0
- scitex/ml/utils/_label_encoder.py +134 -0
- scitex/ml/utils/_merge_labels.py +22 -0
- scitex/ml/utils/_sliding_window_data_augmentation.py +11 -0
- scitex/ml/utils/_under_sample.py +51 -0
- scitex/ml/utils/_verify_n_gpus.py +16 -0
- scitex/ml/utils/grid_search.py +148 -0
- scitex/nn/_BNet.py +15 -9
- scitex/nn/_Filters.py +2 -2
- scitex/nn/_ModulationIndex.py +2 -2
- scitex/nn/_PAC.py +1 -1
- scitex/nn/_Spectrogram.py +12 -3
- scitex/nn/__init__.py +9 -10
- scitex/path/__init__.py +18 -0
- scitex/path/_clean.py +4 -0
- scitex/path/_find.py +9 -4
- scitex/path/_symlink.py +348 -0
- scitex/path/_version.py +4 -3
- scitex/pd/__init__.py +2 -0
- scitex/pd/_get_unique.py +99 -0
- scitex/plt/__init__.py +114 -5
- scitex/plt/_subplots/_AxesWrapper.py +1 -3
- scitex/plt/_subplots/_AxisWrapper.py +7 -3
- scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +47 -13
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +160 -2
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +26 -4
- scitex/plt/_subplots/_AxisWrapperMixins/_UnitAwareMixin.py +322 -0
- scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +1 -0
- scitex/plt/_subplots/_FigWrapper.py +62 -6
- scitex/plt/_subplots/_export_as_csv.py +43 -27
- scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +5 -4
- scitex/plt/_subplots/_export_as_csv_formatters/_format_annotate.py +81 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_bar.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_barh.py +20 -5
- scitex/plt/_subplots/_export_as_csv_formatters/_format_boxplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_contour.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_errorbar.py +35 -18
- scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_fill.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_fill_between.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_hist.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot.py +15 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_box.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_conf_mat.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_ecdf.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_fillv.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_heatmap.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_image.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_joyplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_line.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_ci.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_mean_std.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_median_iqr.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_raster.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_rectangle.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter.py +35 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter_hist.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_shaded_line.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_violin.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_scatter.py +6 -4
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_barplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_boxplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_heatmap.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_histplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_kdeplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_scatterplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_stripplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_swarmplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_violinplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_text.py +60 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_violin.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/_format_violinplot.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters/test_formatters.py +1 -3
- scitex/plt/_subplots/_export_as_csv_formatters.py +56 -59
- scitex/plt/ax/_style/_hide_spines.py +1 -3
- scitex/plt/ax/_style/_rotate_labels.py +180 -76
- scitex/plt/ax/_style/_rotate_labels_v01.py +248 -0
- scitex/plt/ax/_style/_set_meta.py +11 -4
- scitex/plt/ax/_style/_set_supxyt.py +3 -3
- scitex/plt/ax/_style/_set_xyt.py +3 -3
- scitex/plt/ax/_style/_share_axes.py +2 -2
- scitex/plt/color/__init__.py +4 -4
- scitex/plt/color/{_get_colors_from_cmap.py → _get_colors_from_conf_matap.py} +7 -7
- scitex/plt/utils/_configure_mpl.py +99 -86
- scitex/plt/utils/_histogram_utils.py +1 -3
- scitex/plt/utils/_is_valid_axis.py +1 -3
- scitex/plt/utils/_scitex_config.py +1 -0
- scitex/repro/__init__.py +75 -0
- scitex/{reproduce → repro}/_gen_ID.py +1 -1
- scitex/{reproduce → repro}/_gen_timestamp.py +1 -1
- scitex/repro_rng/_RandomStateManager.py +590 -0
- scitex/repro_rng/_RandomStateManager_v01-no-verbose-options.py +414 -0
- scitex/repro_rng/__init__.py +39 -0
- scitex/reproduce/__init__.py +25 -13
- scitex/reproduce/_hash_array.py +22 -0
- scitex/resource/_get_processor_usages.py +4 -4
- scitex/resource/_get_specs.py +2 -2
- scitex/resource/_log_processor_usages.py +2 -2
- scitex/rng/_RandomStateManager.py +590 -0
- scitex/rng/_RandomStateManager_v01-no-verbose-options.py +414 -0
- scitex/rng/__init__.py +39 -0
- scitex/scholar/__init__.py +309 -19
- scitex/scholar/__main__.py +319 -0
- scitex/scholar/auth/ScholarAuthManager.py +308 -0
- scitex/scholar/auth/__init__.py +12 -0
- scitex/scholar/auth/core/AuthenticationGateway.py +473 -0
- scitex/scholar/auth/core/BrowserAuthenticator.py +386 -0
- scitex/scholar/auth/core/StrategyResolver.py +309 -0
- scitex/scholar/auth/core/__init__.py +16 -0
- scitex/scholar/auth/gateway/_OpenURLLinkFinder.py +120 -0
- scitex/scholar/auth/gateway/_OpenURLResolver.py +209 -0
- scitex/scholar/auth/gateway/__init__.py +38 -0
- scitex/scholar/auth/gateway/_resolve_functions.py +101 -0
- scitex/scholar/auth/providers/BaseAuthenticator.py +166 -0
- scitex/scholar/auth/providers/EZProxyAuthenticator.py +484 -0
- scitex/scholar/auth/providers/OpenAthensAuthenticator.py +619 -0
- scitex/scholar/auth/providers/ShibbolethAuthenticator.py +686 -0
- scitex/scholar/auth/providers/__init__.py +18 -0
- scitex/scholar/auth/session/AuthCacheManager.py +189 -0
- scitex/scholar/auth/session/SessionManager.py +159 -0
- scitex/scholar/auth/session/__init__.py +11 -0
- scitex/scholar/auth/sso/BaseSSOAutomator.py +373 -0
- scitex/scholar/auth/sso/OpenAthensSSOAutomator.py +378 -0
- scitex/scholar/auth/sso/SSOAutomator.py +180 -0
- scitex/scholar/auth/sso/UniversityOfMelbourneSSOAutomator.py +380 -0
- scitex/scholar/auth/sso/__init__.py +15 -0
- scitex/scholar/browser/ScholarBrowserManager.py +705 -0
- scitex/scholar/browser/__init__.py +38 -0
- scitex/scholar/browser/utils/__init__.py +13 -0
- scitex/scholar/browser/utils/click_and_wait.py +205 -0
- scitex/scholar/browser/utils/close_unwanted_pages.py +140 -0
- scitex/scholar/browser/utils/wait_redirects.py +732 -0
- scitex/scholar/config/PublisherRules.py +132 -0
- scitex/scholar/config/ScholarConfig.py +126 -0
- scitex/scholar/config/__init__.py +17 -0
- scitex/scholar/core/Paper.py +627 -0
- scitex/scholar/core/Papers.py +722 -0
- scitex/scholar/core/Scholar.py +1975 -0
- scitex/scholar/core/__init__.py +9 -0
- scitex/scholar/impact_factor/ImpactFactorEngine.py +204 -0
- scitex/scholar/impact_factor/__init__.py +20 -0
- scitex/scholar/impact_factor/estimation/ImpactFactorEstimationEngine.py +0 -0
- scitex/scholar/impact_factor/estimation/__init__.py +40 -0
- scitex/scholar/impact_factor/estimation/build_database.py +0 -0
- scitex/scholar/impact_factor/estimation/core/__init__.py +28 -0
- scitex/scholar/impact_factor/estimation/core/cache_manager.py +523 -0
- scitex/scholar/impact_factor/estimation/core/calculator.py +355 -0
- scitex/scholar/impact_factor/estimation/core/journal_matcher.py +428 -0
- scitex/scholar/integration/__init__.py +59 -0
- scitex/scholar/integration/base.py +502 -0
- scitex/scholar/integration/mendeley/__init__.py +22 -0
- scitex/scholar/integration/mendeley/exporter.py +166 -0
- scitex/scholar/integration/mendeley/importer.py +236 -0
- scitex/scholar/integration/mendeley/linker.py +79 -0
- scitex/scholar/integration/mendeley/mapper.py +212 -0
- scitex/scholar/integration/zotero/__init__.py +27 -0
- scitex/scholar/integration/zotero/__main__.py +264 -0
- scitex/scholar/integration/zotero/exporter.py +351 -0
- scitex/scholar/integration/zotero/importer.py +372 -0
- scitex/scholar/integration/zotero/linker.py +415 -0
- scitex/scholar/integration/zotero/mapper.py +286 -0
- scitex/scholar/metadata_engines/ScholarEngine.py +588 -0
- scitex/scholar/metadata_engines/__init__.py +21 -0
- scitex/scholar/metadata_engines/individual/ArXivEngine.py +397 -0
- scitex/scholar/metadata_engines/individual/CrossRefEngine.py +274 -0
- scitex/scholar/metadata_engines/individual/CrossRefLocalEngine.py +263 -0
- scitex/scholar/metadata_engines/individual/OpenAlexEngine.py +350 -0
- scitex/scholar/metadata_engines/individual/PubMedEngine.py +329 -0
- scitex/scholar/metadata_engines/individual/SemanticScholarEngine.py +438 -0
- scitex/scholar/metadata_engines/individual/URLDOIEngine.py +410 -0
- scitex/scholar/metadata_engines/individual/_BaseDOIEngine.py +487 -0
- scitex/scholar/metadata_engines/individual/__init__.py +7 -0
- scitex/scholar/metadata_engines/utils/_PubMedConverter.py +469 -0
- scitex/scholar/metadata_engines/utils/_URLDOIExtractor.py +283 -0
- scitex/scholar/metadata_engines/utils/__init__.py +30 -0
- scitex/scholar/metadata_engines/utils/_metadata2bibtex.py +103 -0
- scitex/scholar/metadata_engines/utils/_standardize_metadata.py +376 -0
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +579 -0
- scitex/scholar/pdf_download/__init__.py +5 -0
- scitex/scholar/pdf_download/strategies/__init__.py +38 -0
- scitex/scholar/pdf_download/strategies/chrome_pdf_viewer.py +376 -0
- scitex/scholar/pdf_download/strategies/direct_download.py +131 -0
- scitex/scholar/pdf_download/strategies/manual_download_fallback.py +167 -0
- scitex/scholar/pdf_download/strategies/manual_download_utils.py +996 -0
- scitex/scholar/pdf_download/strategies/response_body.py +207 -0
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +364 -0
- scitex/scholar/pipelines/ScholarPipelineParallel.py +478 -0
- scitex/scholar/pipelines/ScholarPipelineSingle.py +767 -0
- scitex/scholar/pipelines/__init__.py +49 -0
- scitex/scholar/storage/BibTeXHandler.py +1018 -0
- scitex/scholar/storage/PaperIO.py +468 -0
- scitex/scholar/storage/ScholarLibrary.py +182 -0
- scitex/scholar/storage/_DeduplicationManager.py +548 -0
- scitex/scholar/storage/_LibraryCacheManager.py +724 -0
- scitex/scholar/storage/_LibraryManager.py +1835 -0
- scitex/scholar/storage/__init__.py +28 -0
- scitex/scholar/url_finder/ScholarURLFinder.py +379 -0
- scitex/scholar/url_finder/__init__.py +7 -0
- scitex/scholar/url_finder/strategies/__init__.py +33 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_direct_links.py +261 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_dropdown.py +67 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_href.py +204 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_navigation.py +256 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_publisher_patterns.py +165 -0
- scitex/scholar/url_finder/strategies/find_pdf_urls_by_zotero_translators.py +163 -0
- scitex/scholar/url_finder/strategies/find_supplementary_urls_by_href.py +70 -0
- scitex/scholar/utils/__init__.py +22 -0
- scitex/scholar/utils/bibtex/__init__.py +9 -0
- scitex/scholar/utils/bibtex/_parse_bibtex.py +71 -0
- scitex/scholar/utils/cleanup/__init__.py +8 -0
- scitex/scholar/utils/cleanup/_cleanup_scholar_processes.py +96 -0
- scitex/scholar/utils/cleanup/cleanup_old_extractions.py +117 -0
- scitex/scholar/utils/text/_TextNormalizer.py +407 -0
- scitex/scholar/utils/text/__init__.py +9 -0
- scitex/scholar/zotero/__init__.py +38 -0
- scitex/session/__init__.py +51 -0
- scitex/session/_lifecycle.py +736 -0
- scitex/session/_manager.py +102 -0
- scitex/session/template.py +122 -0
- scitex/stats/__init__.py +30 -26
- scitex/stats/correct/__init__.py +21 -0
- scitex/stats/correct/_correct_bonferroni.py +551 -0
- scitex/stats/correct/_correct_fdr.py +634 -0
- scitex/stats/correct/_correct_holm.py +548 -0
- scitex/stats/correct/_correct_sidak.py +499 -0
- scitex/stats/descriptive/__init__.py +85 -0
- scitex/stats/descriptive/_circular.py +540 -0
- scitex/stats/descriptive/_describe.py +219 -0
- scitex/stats/descriptive/_nan.py +518 -0
- scitex/stats/descriptive/_real.py +189 -0
- scitex/stats/effect_sizes/__init__.py +41 -0
- scitex/stats/effect_sizes/_cliffs_delta.py +325 -0
- scitex/stats/effect_sizes/_cohens_d.py +342 -0
- scitex/stats/effect_sizes/_epsilon_squared.py +315 -0
- scitex/stats/effect_sizes/_eta_squared.py +302 -0
- scitex/stats/effect_sizes/_prob_superiority.py +296 -0
- scitex/stats/posthoc/__init__.py +19 -0
- scitex/stats/posthoc/_dunnett.py +463 -0
- scitex/stats/posthoc/_games_howell.py +383 -0
- scitex/stats/posthoc/_tukey_hsd.py +367 -0
- scitex/stats/power/__init__.py +19 -0
- scitex/stats/power/_power.py +433 -0
- scitex/stats/template.py +119 -0
- scitex/stats/utils/__init__.py +62 -0
- scitex/stats/utils/_effect_size.py +985 -0
- scitex/stats/utils/_formatters.py +270 -0
- scitex/stats/utils/_normalizers.py +927 -0
- scitex/stats/utils/_power.py +433 -0
- scitex/stats_v01/_EffectSizeCalculator.py +488 -0
- scitex/stats_v01/_StatisticalValidator.py +411 -0
- scitex/stats_v01/__init__.py +60 -0
- scitex/stats_v01/_additional_tests.py +415 -0
- scitex/{stats → stats_v01}/_p2stars.py +19 -5
- scitex/stats_v01/_two_sample_tests.py +141 -0
- scitex/stats_v01/desc/__init__.py +83 -0
- scitex/stats_v01/desc/_circular.py +540 -0
- scitex/stats_v01/desc/_describe.py +219 -0
- scitex/stats_v01/desc/_nan.py +518 -0
- scitex/{stats/desc/_nan.py → stats_v01/desc/_nan_v01-20250920_145731.py} +23 -12
- scitex/stats_v01/desc/_real.py +189 -0
- scitex/stats_v01/tests/__corr_test_optimized.py +221 -0
- scitex/stats_v01/tests/_corr_test_optimized.py +179 -0
- scitex/str/__init__.py +1 -3
- scitex/str/_clean_path.py +6 -2
- scitex/str/_latex_fallback.py +267 -160
- scitex/str/_parse.py +44 -36
- scitex/str/_printc.py +1 -3
- scitex/template/__init__.py +87 -0
- scitex/template/_create_project.py +267 -0
- scitex/template/create_pip_project.py +80 -0
- scitex/template/create_research.py +80 -0
- scitex/template/create_singularity.py +80 -0
- scitex/units.py +291 -0
- scitex/utils/_compress_hdf5.py +14 -3
- scitex/utils/_email.py +21 -2
- scitex/utils/_grid.py +6 -4
- scitex/utils/_notify.py +13 -10
- scitex/utils/_verify_scitex_format.py +589 -0
- scitex/utils/_verify_scitex_format_v01.py +370 -0
- scitex/utils/template.py +122 -0
- scitex/web/_search_pubmed.py +62 -16
- scitex-2.1.0.dist-info/LICENSE +21 -0
- scitex-2.1.0.dist-info/METADATA +677 -0
- scitex-2.1.0.dist-info/RECORD +919 -0
- {scitex-2.0.0.dist-info → scitex-2.1.0.dist-info}/WHEEL +1 -1
- scitex-2.1.0.dist-info/entry_points.txt +3 -0
- scitex/ai/__Classifiers.py +0 -101
- scitex/ai/classification/classification_reporter.py +0 -1137
- scitex/ai/classification/classifiers.py +0 -101
- scitex/ai/classification_reporter.py +0 -1161
- scitex/ai/genai/__init__.py +0 -277
- scitex/ai/genai/anthropic_provider.py +0 -320
- scitex/ai/genai/anthropic_refactored.py +0 -109
- scitex/ai/genai/auth_manager.py +0 -200
- scitex/ai/genai/base_provider.py +0 -291
- scitex/ai/genai/chat_history.py +0 -307
- scitex/ai/genai/cost_tracker.py +0 -276
- scitex/ai/genai/deepseek_provider.py +0 -251
- scitex/ai/genai/google_provider.py +0 -228
- scitex/ai/genai/groq_provider.py +0 -248
- scitex/ai/genai/image_processor.py +0 -250
- scitex/ai/genai/llama_provider.py +0 -214
- scitex/ai/genai/mock_provider.py +0 -127
- scitex/ai/genai/model_registry.py +0 -304
- scitex/ai/genai/openai_provider.py +0 -293
- scitex/ai/genai/perplexity_provider.py +0 -205
- scitex/ai/genai/provider_base.py +0 -302
- scitex/ai/genai/provider_factory.py +0 -370
- scitex/ai/genai/response_handler.py +0 -235
- scitex/ai/layer/_Pass.py +0 -21
- scitex/ai/layer/__init__.py +0 -10
- scitex/ai/layer/_switch.py +0 -8
- scitex/ai/metrics/_bACC.py +0 -51
- scitex/ai/plt/_learning_curve.py +0 -194
- scitex/ai/plt/_optuna_study.py +0 -111
- scitex/ai/plt/aucs/__init__.py +0 -2
- scitex/ai/plt/aucs/example.py +0 -60
- scitex/ai/plt/aucs/pre_rec_auc.py +0 -223
- scitex/ai/plt/aucs/roc_auc.py +0 -246
- scitex/ai/sampling/undersample.py +0 -29
- scitex/db/_SQLite3.py +0 -2136
- scitex/db/_SQLite3Mixins/_BlobMixin.py +0 -229
- scitex/gen/_close.py +0 -222
- scitex/gen/_start.py +0 -451
- scitex/general/__init__.py +0 -5
- scitex/io/_load_modules/_db.py +0 -24
- scitex/life/__init__.py +0 -10
- scitex/life/_monitor_rain.py +0 -49
- scitex/reproduce/_fix_seeds.py +0 -45
- scitex/res/__init__.py +0 -5
- scitex/scholar/_local_search.py +0 -454
- scitex/scholar/_paper.py +0 -244
- scitex/scholar/_pdf_downloader.py +0 -325
- scitex/scholar/_search.py +0 -393
- scitex/scholar/_vector_search.py +0 -370
- scitex/scholar/_web_sources.py +0 -457
- scitex/stats/desc/__init__.py +0 -40
- scitex-2.0.0.dist-info/METADATA +0 -307
- scitex-2.0.0.dist-info/RECORD +0 -572
- scitex-2.0.0.dist-info/licenses/LICENSE +0 -7
- /scitex/ai/{act → activation}/__init__.py +0 -0
- /scitex/ai/{act → activation}/_define.py +0 -0
- /scitex/ai/{early_stopping.py → training/_EarlyStopping.py} +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_ImportExportMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_IndexMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_RowMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/_TableMixin.py +0 -0
- /scitex/db/{_PostgreSQLMixins → _postgresql/_PostgreSQLMixins}/__init__.py +0 -0
- /scitex/{stats → stats_v01}/_calc_partial_corr.py +0 -0
- /scitex/{stats → stats_v01}/_corr_test_multi.py +0 -0
- /scitex/{stats → stats_v01}/_corr_test_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_describe_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_multiple_corrections.py +0 -0
- /scitex/{stats → stats_v01}/_nan_stats.py +0 -0
- /scitex/{stats → stats_v01}/_p2stars_wrapper.py +0 -0
- /scitex/{stats → stats_v01}/_statistical_tests.py +0 -0
- /scitex/{stats/desc/_describe.py → stats_v01/desc/_describe_v01-20250920_145731.py} +0 -0
- /scitex/{stats/desc/_real.py → stats_v01/desc/_real_v01-20250920_145731.py} +0 -0
- /scitex/{stats → stats_v01}/multiple/__init__.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_bonferroni_correction.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_fdr_correction.py +0 -0
- /scitex/{stats → stats_v01}/multiple/_multicompair.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test_multi.py +0 -0
- /scitex/{stats → stats_v01}/tests/__corr_test_single.py +0 -0
- /scitex/{stats → stats_v01}/tests/__init__.py +0 -0
- /scitex/{stats → stats_v01}/tests/_brunner_munzel_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/_nocorrelation_test.py +0 -0
- /scitex/{stats → stats_v01}/tests/_smirnov_grubbs.py +0 -0
- {scitex-2.0.0.dist-info → scitex-2.1.0.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "2025-
|
|
4
|
-
# File:
|
|
3
|
+
# Timestamp: "2025-10-13 07:12:49 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_repo/src/scitex/logging/_Tee.py
|
|
5
|
+
# ----------------------------------------
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import os
|
|
8
|
+
__FILE__ = (
|
|
9
|
+
"./src/scitex/logging/_Tee.py"
|
|
10
|
+
)
|
|
11
|
+
__DIR__ = os.path.dirname(__FILE__)
|
|
12
|
+
# ----------------------------------------
|
|
5
13
|
|
|
6
14
|
THIS_FILE = "/home/ywatanabe/proj/scitex_repo/src/scitex/gen/_tee.py"
|
|
7
15
|
|
|
@@ -25,60 +33,31 @@ Prerequisites:
|
|
|
25
33
|
import os as _os
|
|
26
34
|
import re
|
|
27
35
|
import sys
|
|
28
|
-
from typing import Any,
|
|
36
|
+
from typing import Any, TextIO
|
|
29
37
|
|
|
30
38
|
from ..str._clean_path import clean_path
|
|
31
|
-
from ..path import split
|
|
32
39
|
from ..str._printc import printc
|
|
33
40
|
|
|
34
41
|
"""Functions & Classes"""
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# >>> import sys
|
|
41
|
-
# >>> sys.stdout = Tee(sys.stdout, "stdout.txt")
|
|
42
|
-
# >>> sys.stderr = Tee(sys.stderr, "stderr.txt")
|
|
43
|
-
# >>> print("Hello") # Outputs to both console and stdout.txt
|
|
44
|
-
# >>> raise Exception("Error") # Outputs to both console and stderr.txt
|
|
45
|
-
# """
|
|
46
|
-
|
|
47
|
-
# def __init__(self, sys_stdout_or_stderr, spath):
|
|
48
|
-
# """
|
|
49
|
-
# Parameters
|
|
50
|
-
# ----------
|
|
51
|
-
# stream : TextIO
|
|
52
|
-
# Original output stream (sys.stdout or sys.stderr)
|
|
53
|
-
# log_path : str
|
|
54
|
-
# Path to log file
|
|
55
|
-
# """
|
|
56
|
-
# self._files = [sys_stdout_or_stderr, open(spath, "w")]
|
|
57
|
-
# self._is_stderr = sys_stdout_or_stderr is sys.stderr
|
|
58
|
-
|
|
59
|
-
# def __getattr__(self, attr, *args):
|
|
60
|
-
# return self._wrap(attr, *args)
|
|
61
|
-
|
|
62
|
-
# def _wrap(self, attr, *args):
|
|
63
|
-
# def g(*a, **kw):
|
|
64
|
-
# for f in self._files:
|
|
65
|
-
# if self._is_stderr and f is not sys.stderr:
|
|
66
|
-
# # Filter tqdm lines from log file
|
|
67
|
-
# msg = a[0] if a else ""
|
|
68
|
-
# if not re.match(r"^[\s]*[0-9]+%.*\[A*$", msg):
|
|
69
|
-
# res = getattr(f, attr, *args)(*a, **kw)
|
|
70
|
-
# else:
|
|
71
|
-
# res = getattr(f, attr, *args)(*a, **kw)
|
|
72
|
-
# return res
|
|
73
|
-
|
|
74
|
-
# return g
|
|
42
|
+
def _get_logger():
|
|
43
|
+
"""Get logger lazily to avoid circular import during module initialization."""
|
|
44
|
+
from scitex import logging
|
|
45
|
+
|
|
46
|
+
return logging.getLogger(__name__)
|
|
75
47
|
|
|
76
48
|
|
|
77
49
|
class Tee:
|
|
78
|
-
def __init__(self, stream: TextIO, log_path: str) -> None:
|
|
50
|
+
def __init__(self, stream: TextIO, log_path: str, verbose=True) -> None:
|
|
51
|
+
self.verbose = verbose
|
|
79
52
|
self._stream = stream
|
|
53
|
+
self._log_path = log_path
|
|
80
54
|
try:
|
|
81
55
|
self._log_file = open(log_path, "w", buffering=1) # Line buffering
|
|
56
|
+
if verbose:
|
|
57
|
+
# Show where logs are being saved using scitex logging
|
|
58
|
+
logger = _get_logger()
|
|
59
|
+
stream_name = "stderr" if stream is sys.stderr else "stdout"
|
|
60
|
+
logger.debug(f"Tee [{stream_name}]: {log_path}")
|
|
82
61
|
except Exception as e:
|
|
83
62
|
printc(f"Failed to open log file {log_path}: {e}", c="red")
|
|
84
63
|
self._log_file = None
|
|
@@ -118,6 +97,10 @@ class Tee:
|
|
|
118
97
|
try:
|
|
119
98
|
self._log_file.flush()
|
|
120
99
|
self._log_file.close()
|
|
100
|
+
if self.verbose:
|
|
101
|
+
# Use lazy logger to avoid circular import
|
|
102
|
+
logger = _get_logger()
|
|
103
|
+
logger.debug(f"Tee: Closed log file: {self._log_path}")
|
|
121
104
|
self._log_file = None # Prevent double-close
|
|
122
105
|
except Exception:
|
|
123
106
|
pass
|
|
@@ -128,45 +111,16 @@ class Tee:
|
|
|
128
111
|
if hasattr(self, "_log_file") and self._log_file is not None:
|
|
129
112
|
try:
|
|
130
113
|
# Check if the file object is still valid
|
|
131
|
-
if
|
|
114
|
+
if (
|
|
115
|
+
hasattr(self._log_file, "closed")
|
|
116
|
+
and not self._log_file.closed
|
|
117
|
+
):
|
|
132
118
|
self.close()
|
|
133
119
|
except Exception:
|
|
134
120
|
# Silently ignore exceptions during cleanup
|
|
135
121
|
pass
|
|
136
122
|
|
|
137
123
|
|
|
138
|
-
# class Tee:
|
|
139
|
-
# def __init__(self, stream: TextIO, log_path: str) -> None:
|
|
140
|
-
# self._files: List[TextIO] = [stream, open(log_path, "w")]
|
|
141
|
-
# self._is_stderr: bool = stream is sys.stderr
|
|
142
|
-
# self._stream = stream
|
|
143
|
-
|
|
144
|
-
# def write(self, data: Any) -> None:
|
|
145
|
-
# for file in self._files:
|
|
146
|
-
# if hasattr(file, 'write'):
|
|
147
|
-
# if self._is_stderr and file is not sys.stderr:
|
|
148
|
-
# if isinstance(data, str) and not re.match(r"^[\s]*[0-9]+%.*\[A*$", data):
|
|
149
|
-
# file.write(data)
|
|
150
|
-
# else:
|
|
151
|
-
# file.write(data)
|
|
152
|
-
|
|
153
|
-
# def flush(self) -> None:
|
|
154
|
-
# for file in self._files:
|
|
155
|
-
# if hasattr(file, 'flush'):
|
|
156
|
-
# file.flush()
|
|
157
|
-
|
|
158
|
-
# def isatty(self) -> bool:
|
|
159
|
-
# return getattr(self._stream, 'isatty', lambda: False)()
|
|
160
|
-
|
|
161
|
-
# def fileno(self) -> int:
|
|
162
|
-
# """Delegate fileno to original stream for IPython compatibility"""
|
|
163
|
-
# return self._stream.fileno()
|
|
164
|
-
|
|
165
|
-
# @property
|
|
166
|
-
# def buffer(self):
|
|
167
|
-
# return getattr(self._stream, 'buffer', self._stream)
|
|
168
|
-
|
|
169
|
-
|
|
170
124
|
def tee(sys, sdir=None, verbose=True):
|
|
171
125
|
"""Redirects stdout and stderr to both console and log files.
|
|
172
126
|
|
|
@@ -213,26 +167,31 @@ def tee(sys, sdir=None, verbose=True):
|
|
|
213
167
|
|
|
214
168
|
if verbose:
|
|
215
169
|
message = f"Standard output/error are being logged at:\n\t{spath_stdout}\n\t{spath_stderr}"
|
|
216
|
-
|
|
170
|
+
logger = _get_logger()
|
|
171
|
+
logger.info(message)
|
|
172
|
+
# printc(message)
|
|
217
173
|
|
|
218
174
|
return sys_stdout, sys_stderr
|
|
219
175
|
|
|
220
176
|
|
|
221
|
-
main = tee
|
|
222
|
-
|
|
223
177
|
if __name__ == "__main__":
|
|
224
|
-
#
|
|
178
|
+
# Argument Parser
|
|
225
179
|
import matplotlib.pyplot as plt
|
|
180
|
+
|
|
226
181
|
import scitex
|
|
227
182
|
|
|
183
|
+
main = tee
|
|
184
|
+
|
|
228
185
|
# import argparse
|
|
229
186
|
# parser = argparse.ArgumentParser(description='')
|
|
230
187
|
# parser.add_argument('--var', '-v', type=int, default=1, help='')
|
|
231
188
|
# parser.add_argument('--flag', '-f', action='store_true', default=False, help='')
|
|
232
189
|
# args = parser.parse_args()
|
|
233
190
|
# Main
|
|
234
|
-
CONFIG, sys.stdout, sys.stderr, plt, CC = scitex.
|
|
191
|
+
CONFIG, sys.stdout, sys.stderr, plt, CC = scitex.session.start(
|
|
192
|
+
sys, plt, verbose=False
|
|
193
|
+
)
|
|
235
194
|
main(sys, CONFIG["SDIR"])
|
|
236
|
-
scitex.
|
|
195
|
+
scitex.session.close(CONFIG, verbose=False, notify=False)
|
|
237
196
|
|
|
238
197
|
# EOF
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-08-21 20:09:30 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/SciTeX-Code/src/scitex/logging/__init__.py
|
|
5
|
+
# ----------------------------------------
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import os
|
|
8
|
+
__FILE__ = __file__
|
|
9
|
+
__DIR__ = os.path.dirname(__FILE__)
|
|
10
|
+
# ----------------------------------------
|
|
11
|
+
|
|
12
|
+
"""Modular logging utilities for SciTeX.
|
|
13
|
+
|
|
14
|
+
This module provides enhanced logging capabilities with both console and file output,
|
|
15
|
+
ensuring consistent logging across the SciTeX package.
|
|
16
|
+
|
|
17
|
+
Migration:
|
|
18
|
+
# OLD (deprecated)
|
|
19
|
+
from scitex import logging
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
# NEW (recommended)
|
|
23
|
+
from scitex import logging
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
from scitex import logging # DEPRECATED
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
logger.success("Operation completed successfully")
|
|
30
|
+
logger.fail("Operation failed")
|
|
31
|
+
|
|
32
|
+
# Configure logging with file output
|
|
33
|
+
logging.configure(level='info', enable_file=True)
|
|
34
|
+
|
|
35
|
+
# Get current log file location
|
|
36
|
+
log_file = logging.get_log_path()
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
import warnings
|
|
40
|
+
|
|
41
|
+
# Issue deprecation warning when module is imported
|
|
42
|
+
warnings.warn(
|
|
43
|
+
"scitex.logging is deprecated. Use scitex.logging instead. "
|
|
44
|
+
"The scitex.logging module will be removed in a future version.",
|
|
45
|
+
DeprecationWarning,
|
|
46
|
+
stacklevel=2
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
import logging as _logging
|
|
50
|
+
|
|
51
|
+
from ._Tee import Tee, tee
|
|
52
|
+
# Import modular components
|
|
53
|
+
from ._levels import SUCCESS, FAIL, DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
54
|
+
from ._logger import SciTeXLogger, setup_logger_class
|
|
55
|
+
from ._formatters import SciTeXConsoleFormatter, SciTeXFileFormatter
|
|
56
|
+
from ._handlers import create_console_handler, create_file_handler, get_default_log_path
|
|
57
|
+
from ._config import (
|
|
58
|
+
set_level,
|
|
59
|
+
get_level,
|
|
60
|
+
enable_file_logging,
|
|
61
|
+
is_file_logging_enabled,
|
|
62
|
+
configure,
|
|
63
|
+
get_log_path
|
|
64
|
+
)
|
|
65
|
+
from ._print_capture import (
|
|
66
|
+
PrintCapture,
|
|
67
|
+
enable_print_capture,
|
|
68
|
+
disable_print_capture,
|
|
69
|
+
is_print_capture_enabled
|
|
70
|
+
)
|
|
71
|
+
from ._context import log_to_file
|
|
72
|
+
|
|
73
|
+
# Re-export standard logging functions for compatibility
|
|
74
|
+
getLogger = _logging.getLogger
|
|
75
|
+
basicConfig = _logging.basicConfig
|
|
76
|
+
disable = _logging.disable
|
|
77
|
+
|
|
78
|
+
level_by_env = os.getenv("SCITEX_LOGGING_LEVEL", "INFO").upper()
|
|
79
|
+
level_map = {
|
|
80
|
+
"DEBU": DEBUG,
|
|
81
|
+
"DEBUG": DEBUG,
|
|
82
|
+
"INFO": INFO,
|
|
83
|
+
"WARN": WARNING,
|
|
84
|
+
"WARNING": WARNING,
|
|
85
|
+
"ERRO": ERROR,
|
|
86
|
+
"ERROR": ERROR,
|
|
87
|
+
"CRIT": CRITICAL,
|
|
88
|
+
"CRITICAL": CRITICAL,
|
|
89
|
+
"SUCC": SUCCESS,
|
|
90
|
+
"SUCCESS": SUCCESS,
|
|
91
|
+
"FAIL": FAIL,
|
|
92
|
+
}
|
|
93
|
+
level = level_map.get(level_by_env, INFO)
|
|
94
|
+
|
|
95
|
+
# Auto-configure logging on import with file logging enabled, print capture disabled by default
|
|
96
|
+
configure(level=level, enable_file=True, enable_console=True, capture_prints=False)
|
|
97
|
+
|
|
98
|
+
# Export only essential public functions - minimal API
|
|
99
|
+
__all__ = [
|
|
100
|
+
# Core logging functions (most commonly used)
|
|
101
|
+
'getLogger',
|
|
102
|
+
|
|
103
|
+
# Log levels
|
|
104
|
+
'DEBUG',
|
|
105
|
+
'INFO',
|
|
106
|
+
'WARNING',
|
|
107
|
+
'ERROR',
|
|
108
|
+
'CRITICAL',
|
|
109
|
+
'SUCCESS',
|
|
110
|
+
'FAIL',
|
|
111
|
+
|
|
112
|
+
# Configuration (minimal set)
|
|
113
|
+
'configure',
|
|
114
|
+
'get_log_path',
|
|
115
|
+
'Tee',
|
|
116
|
+
'tee',
|
|
117
|
+
|
|
118
|
+
# Context managers
|
|
119
|
+
'log_to_file',
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
# EOF
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-08-21 21:41:37 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_repo/src/scitex/log/_config.py
|
|
5
|
+
# ----------------------------------------
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import os
|
|
8
|
+
__FILE__ = __file__
|
|
9
|
+
__DIR__ = os.path.dirname(__FILE__)
|
|
10
|
+
# ----------------------------------------
|
|
11
|
+
|
|
12
|
+
"""Configuration and setup for SciTeX logging."""
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from typing import Optional, Union
|
|
16
|
+
|
|
17
|
+
from ._handlers import create_console_handler, create_file_handler, get_default_log_path
|
|
18
|
+
from ._levels import CRITICAL, DEBUG, ERROR, FAIL, INFO, SUCCESS, WARNING
|
|
19
|
+
from ._logger import setup_logger_class
|
|
20
|
+
|
|
21
|
+
# Global level variable
|
|
22
|
+
_GLOBAL_LEVEL = None
|
|
23
|
+
_FILE_LOGGING_ENABLED = True # Enable file logging by default
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def set_level(level: Union[str, int]):
|
|
27
|
+
"""Set global log level for all SciTeX loggers."""
|
|
28
|
+
global _GLOBAL_LEVEL
|
|
29
|
+
|
|
30
|
+
level_map = {
|
|
31
|
+
"debug": DEBUG,
|
|
32
|
+
"info": INFO,
|
|
33
|
+
"warning": WARNING,
|
|
34
|
+
"error": ERROR,
|
|
35
|
+
"critical": CRITICAL,
|
|
36
|
+
"success": SUCCESS,
|
|
37
|
+
"fail": FAIL,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if isinstance(level, str):
|
|
41
|
+
level = level_map.get(level.lower(), level)
|
|
42
|
+
|
|
43
|
+
_GLOBAL_LEVEL = level
|
|
44
|
+
logging.getLogger().setLevel(level)
|
|
45
|
+
|
|
46
|
+
# Update all existing handlers
|
|
47
|
+
for handler in logging.getLogger().handlers:
|
|
48
|
+
handler.setLevel(level)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_level():
|
|
52
|
+
"""Get current global log level."""
|
|
53
|
+
return _GLOBAL_LEVEL or logging.getLogger().level
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def enable_file_logging(enabled: bool = True):
|
|
57
|
+
"""Enable or disable file logging globally."""
|
|
58
|
+
global _FILE_LOGGING_ENABLED
|
|
59
|
+
_FILE_LOGGING_ENABLED = enabled
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def is_file_logging_enabled():
|
|
63
|
+
"""Check if file logging is enabled."""
|
|
64
|
+
return _FILE_LOGGING_ENABLED
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def configure(
|
|
68
|
+
level: Union[str, int] = "info",
|
|
69
|
+
log_file: Optional[str] = None,
|
|
70
|
+
enable_file: bool = True,
|
|
71
|
+
enable_console: bool = True,
|
|
72
|
+
capture_prints: bool = True,
|
|
73
|
+
max_file_size: int = 10 * 1024 * 1024,
|
|
74
|
+
backup_count: int = 5,
|
|
75
|
+
):
|
|
76
|
+
"""Configure logging for SciTeX with both console and file output.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
level: Log level (string or logging constant)
|
|
80
|
+
log_file: Path to log file (default: ~/.scitex/logs/scitex-YYYY-MM-DD.log)
|
|
81
|
+
enable_file: Whether to enable file logging
|
|
82
|
+
enable_console: Whether to enable console logging
|
|
83
|
+
capture_prints: Whether to capture print() statements to logs
|
|
84
|
+
max_file_size: Maximum size of log file before rotation (default: 10MB)
|
|
85
|
+
backup_count: Number of backup files to keep (default: 5)
|
|
86
|
+
"""
|
|
87
|
+
# Setup custom logger class
|
|
88
|
+
setup_logger_class()
|
|
89
|
+
|
|
90
|
+
# Convert level if string
|
|
91
|
+
level_map = {
|
|
92
|
+
"debug": DEBUG,
|
|
93
|
+
"info": INFO,
|
|
94
|
+
"warning": WARNING,
|
|
95
|
+
"error": ERROR,
|
|
96
|
+
"critical": CRITICAL,
|
|
97
|
+
"success": SUCCESS,
|
|
98
|
+
"fail": FAIL,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if isinstance(level, str):
|
|
102
|
+
level = level_map.get(level.lower(), level)
|
|
103
|
+
|
|
104
|
+
# Set global level
|
|
105
|
+
set_level(level)
|
|
106
|
+
|
|
107
|
+
# Clear any existing handlers
|
|
108
|
+
root_logger = logging.getLogger()
|
|
109
|
+
for handler in root_logger.handlers[:]:
|
|
110
|
+
root_logger.removeHandler(handler)
|
|
111
|
+
|
|
112
|
+
handlers = []
|
|
113
|
+
|
|
114
|
+
# Add console handler if enabled
|
|
115
|
+
if enable_console:
|
|
116
|
+
console_handler = create_console_handler(level)
|
|
117
|
+
handlers.append(console_handler)
|
|
118
|
+
|
|
119
|
+
# Add file handler if enabled
|
|
120
|
+
if enable_file and is_file_logging_enabled():
|
|
121
|
+
if log_file is None:
|
|
122
|
+
log_file = get_default_log_path()
|
|
123
|
+
|
|
124
|
+
file_handler = create_file_handler(
|
|
125
|
+
log_file, level, max_bytes=max_file_size, backup_count=backup_count
|
|
126
|
+
)
|
|
127
|
+
handlers.append(file_handler)
|
|
128
|
+
|
|
129
|
+
# Configure basic logging with our handlers
|
|
130
|
+
logging.basicConfig(
|
|
131
|
+
level=level, handlers=handlers, force=True # Force reconfiguration
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Enable print capture if requested
|
|
135
|
+
if capture_prints:
|
|
136
|
+
from ._print_capture import enable_print_capture
|
|
137
|
+
|
|
138
|
+
enable_print_capture()
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def get_log_path():
|
|
142
|
+
"""Get the current log file path."""
|
|
143
|
+
for handler in logging.getLogger().handlers:
|
|
144
|
+
if hasattr(handler, "baseFilename"):
|
|
145
|
+
return handler.baseFilename
|
|
146
|
+
return None
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
__all__ = [
|
|
150
|
+
"set_level",
|
|
151
|
+
"get_level",
|
|
152
|
+
"enable_file_logging",
|
|
153
|
+
"is_file_logging_enabled",
|
|
154
|
+
"configure",
|
|
155
|
+
"get_log_path",
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
# EOF
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-10-11 22:30:00 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_repo/src/scitex/logging/_context.py
|
|
5
|
+
# ----------------------------------------
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import os
|
|
8
|
+
__FILE__ = (
|
|
9
|
+
"./src/scitex/logging/_context.py"
|
|
10
|
+
)
|
|
11
|
+
__DIR__ = os.path.dirname(__FILE__)
|
|
12
|
+
# ----------------------------------------
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
Context manager for temporary logging to specific files.
|
|
16
|
+
|
|
17
|
+
Provides clean API for adding/removing file handlers during execution.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import logging as _logging
|
|
21
|
+
from contextlib import contextmanager
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Optional, Union
|
|
24
|
+
|
|
25
|
+
from ._formatters import SciTeXFileFormatter
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@contextmanager
|
|
29
|
+
def log_to_file(
|
|
30
|
+
file_path: Union[str, Path],
|
|
31
|
+
level: int = _logging.DEBUG,
|
|
32
|
+
mode: str = 'w',
|
|
33
|
+
formatter: Optional[_logging.Formatter] = None,
|
|
34
|
+
):
|
|
35
|
+
"""Context manager to temporarily log all output to a specific file.
|
|
36
|
+
|
|
37
|
+
Usage:
|
|
38
|
+
from scitex import logging
|
|
39
|
+
logger = logging.getLogger(__name__)
|
|
40
|
+
|
|
41
|
+
with logging.log_to_file("/path/to/log.txt"):
|
|
42
|
+
logger.info("This goes to both console and /path/to/log.txt")
|
|
43
|
+
logger.success("This too!")
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
file_path: Path to log file
|
|
47
|
+
level: Logging level for this handler (default: DEBUG)
|
|
48
|
+
mode: File mode ('w' for overwrite, 'a' for append)
|
|
49
|
+
formatter: Custom formatter (default: SciTeXFileFormatter)
|
|
50
|
+
|
|
51
|
+
Yields:
|
|
52
|
+
The file handler (can be ignored)
|
|
53
|
+
"""
|
|
54
|
+
# Ensure directory exists
|
|
55
|
+
file_path = Path(file_path)
|
|
56
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
57
|
+
|
|
58
|
+
# Create handler
|
|
59
|
+
handler = _logging.FileHandler(str(file_path), mode=mode)
|
|
60
|
+
handler.setLevel(level)
|
|
61
|
+
|
|
62
|
+
# Set formatter
|
|
63
|
+
if formatter is None:
|
|
64
|
+
formatter = SciTeXFileFormatter()
|
|
65
|
+
handler.setFormatter(formatter)
|
|
66
|
+
|
|
67
|
+
# Add to root logger
|
|
68
|
+
root_logger = _logging.getLogger()
|
|
69
|
+
root_logger.addHandler(handler)
|
|
70
|
+
|
|
71
|
+
# Log where output is going (lazy import to avoid circular dependency)
|
|
72
|
+
def _log_info():
|
|
73
|
+
try:
|
|
74
|
+
from scitex import logging
|
|
75
|
+
logger = logging.getLogger(__name__)
|
|
76
|
+
logger.info(f"Logging to: {file_path}")
|
|
77
|
+
except:
|
|
78
|
+
pass # Silently fail if logging not ready
|
|
79
|
+
|
|
80
|
+
_log_info()
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
yield handler
|
|
84
|
+
finally:
|
|
85
|
+
# Clean up handler
|
|
86
|
+
root_logger.removeHandler(handler)
|
|
87
|
+
handler.close()
|
|
88
|
+
|
|
89
|
+
# Log completion (lazy import)
|
|
90
|
+
def _log_saved():
|
|
91
|
+
try:
|
|
92
|
+
from scitex import logging
|
|
93
|
+
logger = logging.getLogger(__name__)
|
|
94
|
+
logger.info(f"Log saved: {file_path}")
|
|
95
|
+
except:
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
_log_saved()
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
__all__ = ['log_to_file']
|
|
102
|
+
|
|
103
|
+
# EOF
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Timestamp: "2025-10-11 00:17:43 (ywatanabe)"
|
|
4
|
+
# File: /home/ywatanabe/proj/scitex_repo/src/scitex/logging/_formatters.py
|
|
5
|
+
# ----------------------------------------
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import os
|
|
8
|
+
__FILE__ = (
|
|
9
|
+
"./src/scitex/logging/_formatters.py"
|
|
10
|
+
)
|
|
11
|
+
__DIR__ = os.path.dirname(__FILE__)
|
|
12
|
+
# ----------------------------------------
|
|
13
|
+
|
|
14
|
+
__FILE__ = __file__
|
|
15
|
+
"""Custom formatters for SciTeX logging."""
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
# Global format configuration via environment variable
|
|
21
|
+
# Options: default, minimal, detailed, debug, full
|
|
22
|
+
# SCITEX_LOG_FORMAT=debug python script.py
|
|
23
|
+
LOG_FORMAT = os.getenv("SCITEX_LOG_FORMAT", "default")
|
|
24
|
+
|
|
25
|
+
# Available format templates
|
|
26
|
+
FORMAT_TEMPLATES = {
|
|
27
|
+
"minimal": "%(levelname)s: %(message)s",
|
|
28
|
+
"default": "%(levelname)s: %(message)s",
|
|
29
|
+
"detailed": "%(levelname)s: [%(name)s] %(message)s",
|
|
30
|
+
"debug": "%(levelname)s: [%(filename)s:%(lineno)d - %(funcName)s()] %(message)s",
|
|
31
|
+
"full": "%(asctime)s - %(levelname)s: [%(filename)s:%(lineno)d - %(name)s.%(funcName)s()] %(message)s",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SciTeXConsoleFormatter(logging.Formatter):
|
|
36
|
+
"""Custom formatter with color support and configurable format."""
|
|
37
|
+
|
|
38
|
+
# ANSI color codes for log levels
|
|
39
|
+
COLORS = {
|
|
40
|
+
"DEBU": "\033[90m", # Grey
|
|
41
|
+
"INFO": "\033[90m", # Grey
|
|
42
|
+
"SUCC": "\033[32m", # Green
|
|
43
|
+
"WARN": "\033[33m", # Yellow
|
|
44
|
+
"FAIL": "\033[91m", # Light Red
|
|
45
|
+
"ERRO": "\033[31m", # Red
|
|
46
|
+
"CRIT": "\033[35m", # Magenta
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# Color name to ANSI code mapping
|
|
50
|
+
COLOR_NAMES = {
|
|
51
|
+
"black": "\033[30m",
|
|
52
|
+
"red": "\033[31m",
|
|
53
|
+
"green": "\033[32m",
|
|
54
|
+
"yellow": "\033[33m",
|
|
55
|
+
"blue": "\033[34m",
|
|
56
|
+
"magenta": "\033[35m",
|
|
57
|
+
"cyan": "\033[36m",
|
|
58
|
+
"white": "\033[37m",
|
|
59
|
+
"grey": "\033[90m",
|
|
60
|
+
"light_red": "\033[91m",
|
|
61
|
+
"light_green": "\033[92m",
|
|
62
|
+
"light_yellow": "\033[93m",
|
|
63
|
+
"light_blue": "\033[94m",
|
|
64
|
+
"light_magenta": "\033[95m",
|
|
65
|
+
"light_cyan": "\033[96m",
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
RESET = "\033[0m"
|
|
69
|
+
|
|
70
|
+
def __init__(self, fmt=None, indent_width=2):
|
|
71
|
+
"""
|
|
72
|
+
Initialize with format from global config.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
fmt: Format template string
|
|
76
|
+
indent_width: Number of spaces per indent level (default: 2)
|
|
77
|
+
"""
|
|
78
|
+
if fmt is None:
|
|
79
|
+
fmt = FORMAT_TEMPLATES.get(LOG_FORMAT, FORMAT_TEMPLATES["default"])
|
|
80
|
+
super().__init__(fmt)
|
|
81
|
+
self.indent_width = indent_width
|
|
82
|
+
|
|
83
|
+
def format(self, record):
|
|
84
|
+
# Apply indentation if specified in record
|
|
85
|
+
indent_level = getattr(record, "indent", 0)
|
|
86
|
+
if indent_level > 0:
|
|
87
|
+
indent = " " * (indent_level * self.indent_width)
|
|
88
|
+
record.msg = f"{indent}{record.msg}"
|
|
89
|
+
|
|
90
|
+
# Use parent formatter to apply template
|
|
91
|
+
formatted = super().format(record)
|
|
92
|
+
|
|
93
|
+
if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
|
|
94
|
+
# Check for custom color override
|
|
95
|
+
custom_color = getattr(record, "color", None)
|
|
96
|
+
|
|
97
|
+
if custom_color and custom_color in self.COLOR_NAMES:
|
|
98
|
+
# Use custom color
|
|
99
|
+
color = self.COLOR_NAMES[custom_color]
|
|
100
|
+
return f"{color}{formatted}{self.RESET}"
|
|
101
|
+
else:
|
|
102
|
+
# Use default color for log level
|
|
103
|
+
levelname = record.levelname
|
|
104
|
+
if levelname in self.COLORS:
|
|
105
|
+
color = self.COLORS[levelname]
|
|
106
|
+
return f"{color}{formatted}{self.RESET}"
|
|
107
|
+
|
|
108
|
+
return formatted
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class SciTeXFileFormatter(logging.Formatter):
|
|
112
|
+
"""Custom formatter for file output without colors."""
|
|
113
|
+
|
|
114
|
+
def __init__(self):
|
|
115
|
+
super().__init__(
|
|
116
|
+
fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
117
|
+
datefmt="%Y-%m-%d %H:%M:%S",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
__all__ = [
|
|
122
|
+
"SciTeXConsoleFormatter",
|
|
123
|
+
"SciTeXFileFormatter",
|
|
124
|
+
"LOG_FORMAT",
|
|
125
|
+
"FORMAT_TEMPLATES",
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
# EOF
|