scitex 2.13.0__py3-none-any.whl → 2.15.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scitex/__init__.py +80 -2
- scitex/__version__.py +11 -8
- scitex/_env_loader.py +156 -0
- scitex/_mcp_resources/__init__.py +37 -0
- scitex/_mcp_resources/_cheatsheet.py +135 -0
- scitex/_mcp_resources/_figrecipe.py +138 -0
- scitex/_mcp_resources/_formats.py +102 -0
- scitex/_mcp_resources/_modules.py +337 -0
- scitex/_mcp_resources/_session.py +149 -0
- scitex/_mcp_tools/__init__.py +40 -0
- scitex/_mcp_tools/audio.py +200 -0
- scitex/_mcp_tools/canvas.py +128 -0
- scitex/_mcp_tools/capture.py +174 -0
- scitex/_mcp_tools/diagram.py +22 -0
- scitex/_mcp_tools/introspect.py +191 -0
- scitex/_mcp_tools/plt.py +305 -0
- scitex/_mcp_tools/scholar.py +447 -0
- scitex/_mcp_tools/social.py +244 -0
- scitex/_mcp_tools/stats.py +206 -0
- scitex/_mcp_tools/template.py +66 -0
- scitex/_mcp_tools/ui.py +80 -0
- scitex/_mcp_tools/writer.py +37 -0
- scitex/ai/_gen_ai/_PARAMS.py +10 -7
- scitex/ai/classification/reporters/_ClassificationReporter.py +0 -0
- scitex/ai/classification/reporters/_SingleClassificationReporter.py +45 -1603
- scitex/ai/classification/reporters/_mixins/__init__.py +36 -0
- scitex/ai/classification/reporters/_mixins/_constants.py +67 -0
- scitex/ai/classification/reporters/_mixins/_cv_summary.py +387 -0
- scitex/ai/classification/reporters/_mixins/_feature_importance.py +119 -0
- scitex/ai/classification/reporters/_mixins/_metrics.py +275 -0
- scitex/ai/classification/reporters/_mixins/_plotting.py +179 -0
- scitex/ai/classification/reporters/_mixins/_reports.py +153 -0
- scitex/ai/classification/reporters/_mixins/_storage.py +160 -0
- scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +0 -0
- scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +0 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +0 -0
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +0 -0
- scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +0 -0
- scitex/ai/classification/timeseries/_normalize_timestamp.py +0 -0
- scitex/ai/metrics/_calc_seizure_prediction_metrics.py +0 -0
- scitex/ai/plt/_plot_feature_importance.py +0 -0
- scitex/ai/plt/_plot_learning_curve.py +0 -0
- scitex/ai/plt/_plot_optuna_study.py +0 -0
- scitex/ai/plt/_plot_pre_rec_curve.py +0 -0
- scitex/ai/plt/_plot_roc_curve.py +0 -0
- scitex/ai/plt/_stx_conf_mat.py +0 -0
- scitex/ai/training/_LearningCurveLogger.py +0 -0
- scitex/audio/README.md +88 -7
- scitex/audio/__init__.py +127 -60
- scitex/audio/__main__.py +17 -21
- scitex/audio/_branding.py +185 -0
- scitex/audio/_mcp/__init__.py +36 -0
- scitex/audio/_mcp/handlers.py +419 -0
- scitex/audio/_mcp/speak_handlers.py +238 -0
- scitex/audio/_mcp/tool_schemas.py +203 -0
- scitex/audio/_relay.py +225 -0
- scitex/audio/engines/elevenlabs_engine.py +6 -1
- scitex/audio/mcp_server.py +355 -337
- scitex/bridge/_figrecipe.py +40 -8
- scitex/bridge/_stats_plt.py +2 -4
- scitex/bridge/_stats_vis.py +7 -5
- scitex/browser/automation/CookieHandler.py +0 -0
- scitex/browser/collaboration/__init__.py +0 -1
- scitex/browser/core/BrowserMixin.py +0 -0
- scitex/browser/core/ChromeProfileManager.py +10 -3
- scitex/browser/debugging/_browser_logger.py +6 -9
- scitex/browser/debugging/_highlight_element.py +0 -0
- scitex/browser/debugging/_show_grid.py +0 -0
- scitex/browser/interaction/click_center.py +0 -0
- scitex/browser/interaction/click_with_fallbacks.py +0 -0
- scitex/browser/interaction/close_popups.py +0 -0
- scitex/browser/interaction/fill_with_fallbacks.py +0 -0
- scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +0 -0
- scitex/browser/pdf/detect_chrome_pdf_viewer.py +0 -0
- scitex/browser/stealth/HumanBehavior.py +0 -0
- scitex/browser/stealth/StealthManager.py +0 -0
- scitex/canvas/README.md +1 -1
- scitex/canvas/_mcp/__init__.py +4 -0
- scitex/canvas/_mcp/handlers.py +372 -0
- scitex/canvas/_mcp/tool_schemas.py +219 -0
- scitex/canvas/editor/_dearpygui/__init__.py +25 -0
- scitex/canvas/editor/_dearpygui/_editor.py +147 -0
- scitex/canvas/editor/_dearpygui/_handlers.py +476 -0
- scitex/canvas/editor/_dearpygui/_panels/__init__.py +17 -0
- scitex/canvas/editor/_dearpygui/_panels/_control.py +119 -0
- scitex/canvas/editor/_dearpygui/_panels/_element_controls.py +190 -0
- scitex/canvas/editor/_dearpygui/_panels/_preview.py +43 -0
- scitex/canvas/editor/_dearpygui/_panels/_sections.py +390 -0
- scitex/canvas/editor/_dearpygui/_plotting.py +187 -0
- scitex/canvas/editor/_dearpygui/_rendering.py +504 -0
- scitex/canvas/editor/_dearpygui/_selection.py +295 -0
- scitex/canvas/editor/_dearpygui/_state.py +93 -0
- scitex/canvas/editor/_dearpygui/_utils.py +61 -0
- scitex/canvas/editor/flask_editor/templates/__init__.py +32 -70
- scitex/canvas/mcp_server.py +2 -2
- scitex/capture/__init__.py +0 -1
- scitex/capture/_mcp/__init__.py +11 -0
- scitex/capture/_mcp/handlers.py +438 -0
- scitex/capture/_mcp/tool_schemas.py +270 -0
- scitex/cli/__init__.py +44 -2
- scitex/cli/audio.py +150 -3
- scitex/cli/browser.py +310 -0
- scitex/cli/capture.py +14 -3
- scitex/cli/introspect.py +443 -0
- scitex/cli/main.py +230 -103
- scitex/cli/mcp.py +362 -0
- scitex/cli/repro.py +18 -0
- scitex/cli/resource.py +18 -0
- scitex/cli/scholar/__init__.py +97 -0
- scitex/cli/scholar/_crossref_scitex.py +296 -0
- scitex/cli/scholar/_fetch.py +369 -0
- scitex/cli/scholar/_jobs.py +306 -0
- scitex/cli/scholar/_library.py +152 -0
- scitex/cli/scholar/_utils.py +35 -0
- scitex/cli/social.py +314 -0
- scitex/cli/stats.py +18 -0
- scitex/cli/template.py +18 -0
- scitex/cli/tex.py +18 -0
- scitex/cli/writer.py +190 -20
- scitex/compat/__init__.py +74 -0
- scitex/config/README.md +1 -1
- scitex/config/__init__.py +16 -2
- scitex/config/_env_registry.py +191 -0
- scitex/config/default.yaml +31 -0
- scitex/cv/__init__.py +87 -0
- scitex/cv/_draw.py +236 -0
- scitex/cv/_filters.py +217 -0
- scitex/cv/_io.py +157 -0
- scitex/cv/_transform.py +184 -0
- scitex/dev/__init__.py +2 -0
- scitex/dev/cv/__init__.py +60 -0
- scitex/dev/cv/_compose.py +330 -0
- scitex/dev/cv/_title_card.py +351 -0
- scitex/dev/plt/__init__.py +0 -0
- scitex/dev/plt/demo_plotters/__init__.py +0 -0
- scitex/dev/plt/mpl/get_dir_ax.py +0 -0
- scitex/dev/plt/mpl/get_signatures.py +0 -0
- scitex/dev/plt/mpl/get_signatures_details.py +0 -0
- scitex/diagram/__init__.py +42 -19
- scitex/diagram/mcp_server.py +13 -125
- scitex/dt/_normalize_timestamp.py +0 -0
- scitex/gen/__init__.py +0 -0
- scitex/gen/misc.py +0 -0
- scitex/git/_init.py +2 -2
- scitex/git/_session.py +0 -0
- scitex/introspect/__init__.py +75 -0
- scitex/introspect/_call_graph.py +303 -0
- scitex/introspect/_class_hierarchy.py +163 -0
- scitex/introspect/_core.py +42 -0
- scitex/introspect/_docstring.py +131 -0
- scitex/introspect/_examples.py +113 -0
- scitex/introspect/_imports.py +271 -0
- scitex/introspect/_mcp/__init__.py +37 -0
- scitex/introspect/_mcp/handlers.py +208 -0
- scitex/introspect/_members.py +151 -0
- scitex/introspect/_resolve.py +89 -0
- scitex/introspect/_signature.py +131 -0
- scitex/introspect/_source.py +80 -0
- scitex/introspect/_type_hints.py +172 -0
- scitex/io/bundle/README.md +1 -1
- scitex/io/bundle/kinds/__init__.py +0 -0
- scitex/io/bundle/kinds/_figure/__init__.py +0 -0
- scitex/io/bundle/kinds/_plot/__init__.py +0 -0
- scitex/io/bundle/kinds/_shape/__init__.py +0 -0
- scitex/io/bundle/kinds/_text/__init__.py +0 -0
- scitex/logging/_context.py +5 -4
- scitex/mcp_server.py +170 -145
- scitex/plt/__init__.py +249 -548
- scitex/plt/_figrecipe_integration.py +121 -0
- scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +5 -10
- scitex/plt/_subplots/_FigWrapper.py +139 -88
- scitex/plt/_subplots/_export_as_csv_formatters/_format_pcolormesh.py +0 -0
- scitex/plt/_subplots/_export_as_csv_formatters/_format_stackplot.py +0 -0
- scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/plt/gallery/README.md +1 -1
- scitex/plt/styles/_plot_postprocess.py +35 -117
- scitex/plt/styles/_postprocess_helpers.py +158 -0
- scitex/plt/utils/_hitmap/__init__.py +82 -0
- scitex/plt/utils/_hitmap/_artist_extraction.py +343 -0
- scitex/plt/utils/_hitmap/_color_application.py +346 -0
- scitex/plt/utils/_hitmap/_color_conversion.py +121 -0
- scitex/plt/utils/_hitmap/_constants.py +40 -0
- scitex/plt/utils/_hitmap/_hitmap_core.py +334 -0
- scitex/plt/utils/_hitmap/_path_extraction.py +357 -0
- scitex/plt/utils/_hitmap/_query.py +113 -0
- scitex/plt/utils/_hitmap.py +46 -1616
- scitex/plt/utils/_metadata/__init__.py +80 -0
- scitex/plt/utils/_metadata/_artists/__init__.py +25 -0
- scitex/plt/utils/_metadata/_artists/_base.py +195 -0
- scitex/plt/utils/_metadata/_artists/_collections.py +356 -0
- scitex/plt/utils/_metadata/_artists/_extract.py +57 -0
- scitex/plt/utils/_metadata/_artists/_images.py +80 -0
- scitex/plt/utils/_metadata/_artists/_lines.py +261 -0
- scitex/plt/utils/_metadata/_artists/_patches.py +247 -0
- scitex/plt/utils/_metadata/_artists/_text.py +106 -0
- scitex/plt/utils/_metadata/_csv.py +416 -0
- scitex/plt/utils/_metadata/_detect.py +225 -0
- scitex/plt/utils/_metadata/_legend.py +127 -0
- scitex/plt/utils/_metadata/_rounding.py +117 -0
- scitex/plt/utils/_metadata/_verification.py +202 -0
- scitex/repro/_RandomStateManager.py +0 -0
- scitex/repro/_gen_ID.py +0 -0
- scitex/repro/_gen_timestamp.py +0 -0
- scitex/repro/_hash_array.py +0 -0
- scitex/schema/README.md +1 -1
- scitex/scholar/__init__.py +8 -0
- scitex/scholar/_mcp/__init__.py +4 -0
- scitex/scholar/_mcp/all_handlers.py +74 -0
- scitex/scholar/_mcp/crossref_handlers.py +265 -0
- scitex/scholar/_mcp/handlers.py +1478 -0
- scitex/scholar/_mcp/job_handlers.py +172 -0
- scitex/scholar/_mcp/job_tool_schemas.py +166 -0
- scitex/scholar/_mcp/tool_schemas.py +505 -0
- scitex/scholar/auth/core/BrowserAuthenticator.py +126 -9
- scitex/scholar/auth/providers/OpenAthensAuthenticator.py +55 -210
- scitex/scholar/auth/providers/_notifications.py +417 -0
- scitex/scholar/auth/sso/BaseSSOAutomator.py +36 -17
- scitex/scholar/auth/sso/UniversityOfMelbourneSSOAutomator.py +8 -15
- scitex/scholar/citation_graph/__init__.py +0 -1
- scitex/scholar/config/core/_PathManager.py +5 -1
- scitex/scholar/config/default.yaml +1 -1
- scitex/scholar/core/Paper.py +19 -41
- scitex/scholar/core/Scholar.py +64 -1688
- scitex/scholar/core/_mixins/__init__.py +36 -0
- scitex/scholar/core/_mixins/_enrichers.py +270 -0
- scitex/scholar/core/_mixins/_library_handlers.py +100 -0
- scitex/scholar/core/_mixins/_loaders.py +103 -0
- scitex/scholar/core/_mixins/_pdf_download.py +375 -0
- scitex/scholar/core/_mixins/_pipeline.py +312 -0
- scitex/scholar/core/_mixins/_project_handlers.py +125 -0
- scitex/scholar/core/_mixins/_savers.py +69 -0
- scitex/scholar/core/_mixins/_search.py +103 -0
- scitex/scholar/core/_mixins/_services.py +88 -0
- scitex/scholar/core/_mixins/_url_finding.py +105 -0
- scitex/scholar/core/journal_normalizer.py +36 -25
- scitex/scholar/crossref_scitex.py +367 -0
- scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/scholar/examples/00_run_all.sh +120 -0
- scitex/scholar/examples/07_storage_integration.py +0 -0
- scitex/scholar/impact_factor/estimation/__init__.py +0 -1
- scitex/scholar/impact_factor/jcr/ImpactFactorJCREngine.py +19 -6
- scitex/scholar/impact_factor/jcr/build_database.py +0 -0
- scitex/scholar/jobs/_Job.py +266 -0
- scitex/scholar/jobs/_JobManager.py +458 -0
- scitex/scholar/jobs/__init__.py +74 -0
- scitex/scholar/jobs/_errors.py +346 -0
- scitex/scholar/jobs/_executors.py +397 -0
- scitex/scholar/mcp_server.py +52 -2
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +38 -416
- scitex/scholar/pdf_download/_cli.py +154 -0
- scitex/scholar/pdf_download/strategies/__init__.py +11 -8
- scitex/scholar/pdf_download/strategies/chrome_pdf_viewer.py +11 -11
- scitex/scholar/pdf_download/strategies/manual_download_fallback.py +80 -3
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +73 -121
- scitex/scholar/pipelines/ScholarPipelineParallel.py +83 -140
- scitex/scholar/pipelines/ScholarPipelineSearchParallel.py +11 -13
- scitex/scholar/pipelines/ScholarPipelineSingle.py +83 -656
- scitex/scholar/pipelines/_single_steps.py +465 -0
- scitex/scholar/storage/BibTeXHandler.py +71 -23
- scitex/scholar/storage/PaperIO.py +53 -18
- scitex/scholar/storage/_BibTeXValidator.py +571 -0
- scitex/scholar/storage/_LibraryManager.py +97 -1695
- scitex/scholar/storage/__init__.py +17 -3
- scitex/scholar/storage/_mixins/__init__.py +30 -0
- scitex/scholar/storage/_mixins/_bibtex_handlers.py +128 -0
- scitex/scholar/storage/_mixins/_library_operations.py +218 -0
- scitex/scholar/storage/_mixins/_metadata_conversion.py +226 -0
- scitex/scholar/storage/_mixins/_paper_saving.py +456 -0
- scitex/scholar/storage/_mixins/_resolution.py +376 -0
- scitex/scholar/storage/_mixins/_storage_helpers.py +121 -0
- scitex/scholar/storage/_mixins/_symlink_handlers.py +226 -0
- scitex/scholar/url_finder/translators/individual/cell_press.py +131 -4
- scitex/security/README.md +3 -3
- scitex/security/__init__.py +0 -1
- scitex/session/README.md +1 -1
- scitex/session/__init__.py +0 -0
- scitex/session/_decorator.py +0 -0
- scitex/session/_lifecycle.py +0 -0
- scitex/sh/README.md +1 -1
- scitex/social/__init__.py +153 -0
- scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
- scitex/stats/__init__.py +14 -2
- scitex/stats/__main__.py +2 -2
- scitex/stats/_figrecipe_integration.py +116 -0
- scitex/stats/_mcp/__init__.py +4 -0
- scitex/stats/_mcp/handlers.py +1191 -0
- scitex/stats/_mcp/tool_schemas.py +384 -0
- scitex/stats/auto/__init__.py +0 -1
- scitex/stats/correct/_correct_bonferroni.py +0 -0
- scitex/stats/correct/_correct_fdr.py +0 -0
- scitex/stats/correct/_correct_fdr_.py +0 -0
- scitex/stats/correct/_correct_holm.py +0 -0
- scitex/stats/correct/_correct_sidak.py +0 -0
- scitex/stats/effect_sizes/_cliffs_delta.py +0 -0
- scitex/stats/effect_sizes/_cohens_d.py +0 -0
- scitex/stats/effect_sizes/_epsilon_squared.py +0 -0
- scitex/stats/effect_sizes/_eta_squared.py +0 -0
- scitex/stats/effect_sizes/_prob_superiority.py +0 -0
- scitex/stats/mcp_server.py +2 -2
- scitex/stats/posthoc/_dunnett.py +0 -0
- scitex/stats/posthoc/_games_howell.py +0 -0
- scitex/stats/posthoc/_tukey_hsd.py +0 -0
- scitex/stats/power/_power.py +0 -0
- scitex/stats/utils/_effect_size.py +0 -0
- scitex/stats/utils/_formatters.py +0 -0
- scitex/stats/utils/_power.py +0 -0
- scitex/template/README.md +1 -1
- scitex/template/_mcp/__init__.py +4 -0
- scitex/template/_mcp/handlers.py +259 -0
- scitex/template/_mcp/tool_schemas.py +112 -0
- scitex/template/clone_writer_directory.py +6 -6
- scitex/template/mcp_server.py +2 -2
- scitex/ui/__init__.py +173 -0
- scitex/ui/_backends/__init__.py +66 -0
- scitex/ui/_backends/_audio.py +86 -0
- scitex/ui/_backends/_config.py +250 -0
- scitex/ui/_backends/_desktop.py +184 -0
- scitex/ui/_backends/_emacs.py +210 -0
- scitex/ui/_backends/_email.py +78 -0
- scitex/ui/_backends/_matplotlib.py +118 -0
- scitex/ui/_backends/_playwright.py +109 -0
- scitex/ui/_backends/_types.py +58 -0
- scitex/ui/_backends/_webhook.py +77 -0
- scitex/ui/_backends.py +37 -0
- scitex/ui/_mcp/__init__.py +23 -0
- scitex/ui/_mcp/handlers.py +260 -0
- scitex/ui/_mcp/tool_schemas.py +107 -0
- scitex/ui/mcp_server.py +151 -0
- scitex/utils/_email.py +85 -7
- scitex/utils/_notify.py +16 -5
- scitex/utils/_search.py +11 -9
- scitex/utils/_verify_scitex_format.py +0 -0
- scitex/writer/README.md +1 -1
- scitex/writer/Writer.py +110 -111
- scitex/writer/__init__.py +26 -48
- scitex/writer/_clone_writer_project.py +0 -0
- scitex/writer/_compile/__init__.py +5 -4
- scitex/writer/_compile/_compile_async.py +130 -0
- scitex/writer/_compile/_compile_unified.py +148 -0
- scitex/writer/_compile/_runner.py +2 -2
- scitex/writer/_compile/_validator.py +3 -3
- scitex/writer/_compile/manuscript.py +1 -1
- scitex/writer/_compile/revision.py +1 -1
- scitex/writer/_compile/supplementary.py +1 -1
- scitex/writer/_dataclasses/config/_WriterConfig.py +175 -0
- scitex/writer/_dataclasses/contents/_ManuscriptContents.py +236 -0
- scitex/writer/_dataclasses/core/_Document.py +146 -0
- scitex/writer/_dataclasses/core/_DocumentSection.py +546 -0
- scitex/writer/_dataclasses/results/_CompilationResult.py +165 -0
- scitex/writer/_dataclasses/results/_LaTeXIssue.py +102 -0
- scitex/writer/_dataclasses/tree/MINIMUM_FILES.md +121 -0
- scitex/writer/_mcp/__init__.py +4 -0
- scitex/writer/_mcp/handlers.py +32 -0
- scitex/writer/_mcp/tool_schemas.py +33 -0
- scitex/writer/_project/_trees.py +2 -2
- scitex/writer/utils/__init__.py +19 -2
- scitex/writer/utils/_converters.py +635 -0
- scitex/writer/utils/_parse_latex_logs.py +1 -1
- scitex/writer/utils/_verify_tree_structure.py +205 -0
- scitex-2.15.1.dist-info/METADATA +648 -0
- scitex-2.15.1.dist-info/RECORD +2553 -0
- scitex-2.15.1.dist-info/entry_points.txt +12 -0
- scitex/audio/_mcp_handlers.py +0 -256
- scitex/audio/_mcp_tool_schemas.py +0 -203
- scitex/canvas/_mcp_handlers.py +0 -372
- scitex/canvas/_mcp_tool_schemas.py +0 -219
- scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
- scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
- scitex/capture/mcp_handlers.py +0 -401
- scitex/capture/mcp_tool_defs.py +0 -192
- scitex/capture/mcp_tools.py +0 -241
- scitex/capture/mcp_utils.py +0 -30
- scitex/cli/scholar.py +0 -313
- scitex/diagram/_compile.py +0 -312
- scitex/diagram/_diagram.py +0 -355
- scitex/diagram/_mcp_handlers.py +0 -400
- scitex/diagram/_mcp_tool_schemas.py +0 -157
- scitex/diagram/_presets.py +0 -173
- scitex/diagram/_schema.py +0 -182
- scitex/diagram/_split.py +0 -278
- scitex/plt/_mcp_handlers.py +0 -361
- scitex/plt/_mcp_tool_schemas.py +0 -169
- scitex/plt/mcp_server.py +0 -205
- scitex/scholar/.legacy/Scholar.py +0 -400
- scitex/scholar/.legacy/_Scholar.py +0 -1763
- scitex/scholar/.legacy/_ScholarAPI.py +0 -316
- scitex/scholar/.legacy/_tmp/search_engine/_BaseSearchEngine.py +0 -101
- scitex/scholar/.legacy/_tmp/search_engine/_UnifiedSearcher.py +0 -392
- scitex/scholar/.legacy/_tmp/search_engine/__init__.py +0 -53
- scitex/scholar/.legacy/_tmp/search_engine/local/_LocalSearchEngine.py +0 -134
- scitex/scholar/.legacy/_tmp/search_engine/local/_VectorSearchEngine.py +0 -129
- scitex/scholar/.legacy/_tmp/search_engine/web/_ArxivSearchEngine.py +0 -279
- scitex/scholar/.legacy/_tmp/search_engine/web/_CrossRefSearchEngine.py +0 -319
- scitex/scholar/.legacy/_tmp/search_engine/web/_GoogleScholarSearchEngine.py +0 -209
- scitex/scholar/.legacy/_tmp/search_engine/web/_PubMedSearchEngine.py +0 -374
- scitex/scholar/.legacy/_tmp/search_engine/web/_SemanticScholarSearchEngine.py +0 -362
- scitex/scholar/.legacy/database/README.md +0 -121
- scitex/scholar/.legacy/database/README_CONCURRENT_ACCESS.md +0 -103
- scitex/scholar/.legacy/database/_DatabaseEntry.py +0 -232
- scitex/scholar/.legacy/database/_DatabaseIndex.py +0 -426
- scitex/scholar/.legacy/database/_LibraryManager.py +0 -276
- scitex/scholar/.legacy/database/_PaperDatabase.py +0 -543
- scitex/scholar/.legacy/database/_ScholarDatabaseIntegration.py +0 -391
- scitex/scholar/.legacy/database/_StorageIntegratedDB.py +0 -619
- scitex/scholar/.legacy/database/_ZoteroCompatibleDB.py +0 -1194
- scitex/scholar/.legacy/database/__init__.py +0 -28
- scitex/scholar/.legacy/database/manage.py +0 -274
- scitex/scholar/.legacy/lookup/_LookupIndex.py +0 -470
- scitex/scholar/.legacy/lookup/__init__.py +0 -22
- scitex/scholar/.legacy/metadata/README.md +0 -62
- scitex/scholar/.legacy/metadata/__init__.py +0 -1
- scitex/scholar/.legacy/metadata/doi/README.md +0 -368
- scitex/scholar/.legacy/metadata/doi/__init__.py +0 -7
- scitex/scholar/.legacy/metadata/doi/batch/_MetadataHandlerForBatchDOIResolution.py +0 -304
- scitex/scholar/.legacy/metadata/doi/batch/_ProgressManagerForBatchDOIResolution.py +0 -304
- scitex/scholar/.legacy/metadata/doi/batch/_SourceStatsManagerForBatchDOIResolution.py +0 -299
- scitex/scholar/.legacy/metadata/doi/batch/__init__.py +0 -26
- scitex/scholar/.legacy/metadata/doi/resolvers/_BatchDOIResolver.py +0 -586
- scitex/scholar/.legacy/metadata/doi/resolvers/_BibTeXDOIResolver.py +0 -609
- scitex/scholar/.legacy/metadata/doi/resolvers/_DOIResolver.py +0 -192
- scitex/scholar/.legacy/metadata/doi/resolvers/_SingleDOIResolver.py +0 -395
- scitex/scholar/.legacy/metadata/doi/resolvers/__init__.py +0 -2
- scitex/scholar/.legacy/metadata/doi/sources/.combined-SemanticScholarSource/_SemanticScholarSource.py +0 -289
- scitex/scholar/.legacy/metadata/doi/sources/.combined-SemanticScholarSource/_SemanticScholarSourceEnhanced.py +0 -229
- scitex/scholar/.legacy/metadata/doi/sources/_ArXivSource.py +0 -306
- scitex/scholar/.legacy/metadata/doi/sources/_BaseDOISource.py +0 -347
- scitex/scholar/.legacy/metadata/doi/sources/_CrossRefLocalSource.py +0 -79
- scitex/scholar/.legacy/metadata/doi/sources/_CrossRefSource.py +0 -225
- scitex/scholar/.legacy/metadata/doi/sources/_OpenAlexSource.py +0 -306
- scitex/scholar/.legacy/metadata/doi/sources/_PubMedSource.py +0 -302
- scitex/scholar/.legacy/metadata/doi/sources/_SemanticScholarSource.py +0 -341
- scitex/scholar/.legacy/metadata/doi/sources/_SourceManager.py +0 -317
- scitex/scholar/.legacy/metadata/doi/sources/_SourceResolutionStrategy.py +0 -595
- scitex/scholar/.legacy/metadata/doi/sources/_SourceRotationManager.py +0 -585
- scitex/scholar/.legacy/metadata/doi/sources/_URLDOISource.py +0 -394
- scitex/scholar/.legacy/metadata/doi/sources/_UnifiedSource.py +0 -412
- scitex/scholar/.legacy/metadata/doi/sources/__init__.py +0 -38
- scitex/scholar/.legacy/metadata/doi/utils/_PubMedConverter.py +0 -465
- scitex/scholar/.legacy/metadata/doi/utils/_RateLimitHandler.py +0 -707
- scitex/scholar/.legacy/metadata/doi/utils/_TextNormalizer.py +0 -587
- scitex/scholar/.legacy/metadata/doi/utils/_URLDOIExtractor.py +0 -278
- scitex/scholar/.legacy/metadata/doi/utils/__init__.py +0 -40
- scitex/scholar/.legacy/metadata/doi/utils/_to_complete_metadata_structure.py +0 -315
- scitex/scholar/.legacy/metadata/enrichment/README.md +0 -51
- scitex/scholar/.legacy/metadata/enrichment/_LibraryEnricher.py +0 -99
- scitex/scholar/.legacy/metadata/enrichment/__init__.py +0 -2
- scitex/scholar/.legacy/metadata/enrichment/enrichers/_ImpactFactorEnricher.py +0 -107
- scitex/scholar/.legacy/metadata/enrichment/enrichers/_SmartEnricher.py +0 -164
- scitex/scholar/.legacy/metadata/enrichment/enrichers/__init__.py +0 -4
- scitex/scholar/.legacy/metadata/enrichment/sources/_UnifiedMetadataSource.py +0 -126
- scitex/scholar/.legacy/metadata/enrichment/sources/__init__.py +0 -3
- scitex/scholar/.legacy/metadata/query_to_full_meta_json.py +0 -184
- scitex/scholar/.legacy/metadata/urls/.tmp/open_url/KNOWN_RESOLVERS.py +0 -462
- scitex/scholar/.legacy/metadata/urls/.tmp/open_url/README.md +0 -223
- scitex/scholar/.legacy/metadata/urls/.tmp/open_url/_DOIToURLResolver.py +0 -694
- scitex/scholar/.legacy/metadata/urls/.tmp/open_url/_OpenURLResolver.py +0 -1160
- scitex/scholar/.legacy/metadata/urls/.tmp/open_url/_ResolverLinkFinder.py +0 -344
- scitex/scholar/.legacy/metadata/urls/.tmp/open_url/__init__.py +0 -24
- scitex/scholar/.legacy/metadata/urls/README.md +0 -142
- scitex/scholar/.legacy/metadata/urls/_URLMetadataHandler.py +0 -383
- scitex/scholar/.legacy/metadata/urls/_ZoteroTranslatorRunner.py +0 -294
- scitex/scholar/.legacy/metadata/urls/__init__.py +0 -39
- scitex/scholar/.legacy/metadata/urls/_finder.py +0 -319
- scitex/scholar/.legacy/metadata/urls/_handler.py +0 -326
- scitex/scholar/.legacy/metadata/urls/_resolver.py +0 -287
- scitex/scholar/.legacy/metadata/urls/docs/CORE_URL_TYPES.md +0 -187
- scitex/scholar/.legacy/metadata/urls/docs/URL_SCHEMA.md +0 -223
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/.eslintrc +0 -11
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/AGPL +0 -22
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/checkDeletedTxt.sh +0 -46
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/eslint-plugin-zotero-translator/bin/teslint.js +0 -9
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/eslint-plugin-zotero-translator/index.js +0 -15
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/eslint-plugin-zotero-translator/package-lock.json +0 -151
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/eslint-plugin-zotero-translator/package.json +0 -21
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/eslint-plugin-zotero-translator/processor.js +0 -257
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/helper.sh +0 -29
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/lint.sh +0 -12
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/pull-request-check/check-pull-request.sh +0 -39
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/pull-request-check/selenium-test.js +0 -147
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/pull-request-check/translator-server.js +0 -72
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.ci/updateTypes.mjs +0 -75
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.editorconfig +0 -8
- scitex/scholar/.legacy/metadata/urls/zotero_translators/.eslintrc +0 -70
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ABC News Australia.js +0 -224
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ACLS Humanities EBook.js +0 -165
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ACLWeb.js +0 -600
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ACM Digital Library.js +0 -710
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ACS Publications.js +0 -633
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ADS Bibcode.js +0 -664
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AEA Web.js +0 -450
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AGRIS.js +0 -311
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AIP.js +0 -295
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AMS Journals.js +0 -136
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AMS MathSciNet (Legacy).js +0 -313
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AMS MathSciNet.js +0 -288
- scitex/scholar/.legacy/metadata/urls/zotero_translators/APA PsycNET.js +0 -915
- scitex/scholar/.legacy/metadata/urls/zotero_translators/APN.ru.js +0 -132
- scitex/scholar/.legacy/metadata/urls/zotero_translators/APS-Physics.js +0 -204
- scitex/scholar/.legacy/metadata/urls/zotero_translators/APS.js +0 -542
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ARTFL Encyclopedie.js +0 -283
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ARTnews.js +0 -155
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ARTstor.js +0 -619
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ASCE.js +0 -199
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ASCO Meeting Library.js +0 -153
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ASTIS.js +0 -337
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ATS International Journal.js +0 -290
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Access Engineering.js +0 -384
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Access Medicine.js +0 -343
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Access Science.js +0 -391
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Adam Matthew Digital.js +0 -405
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Agencia del ISBN.js +0 -77
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Ahval News.js +0 -309
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Air University Journals.js +0 -236
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Airiti.js +0 -423
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Alexander Street Press.js +0 -198
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AllAfrica.js +0 -291
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Alsharekh.js +0 -242
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AlterNet.js +0 -134
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Aluka.js +0 -261
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Amazon.js +0 -1043
- scitex/scholar/.legacy/metadata/urls/zotero_translators/American Archive of Public Broadcasting.js +0 -592
- scitex/scholar/.legacy/metadata/urls/zotero_translators/American Institute of Aeronautics and Astronautics.js +0 -210
- scitex/scholar/.legacy/metadata/urls/zotero_translators/American Prospect.js +0 -114
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Ancestry.com US Federal Census.js +0 -164
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Annual Reviews.js +0 -329
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Antikvarium.hu.js +0 -280
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AquaDocs.js +0 -390
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Archeion.js +0 -249
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Archiv fuer Sozialgeschichte.js +0 -157
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Archive Ouverte en Sciences de l'Information et de la Communication (AOSIC).js +0 -179
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Archives Canada.js +0 -142
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Ariana News.js +0 -203
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Art Institute of Chicago.js +0 -279
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Artefacts Canada.js +0 -192
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Artforum.js +0 -438
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Atlanta Journal-Constitution.js +0 -311
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Atypon Journals.js +0 -1204
- scitex/scholar/.legacy/metadata/urls/zotero_translators/AustLII and NZLII.js +0 -604
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Australian Dictionary of Biography.js +0 -196
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BAILII.js +0 -176
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BBC Genome.js +0 -254
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BBC.js +0 -430
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BIBSYS.js +0 -112
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BOCC.js +0 -217
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BOE.js +0 -229
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BOFiP-Impots.js +0 -132
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Baidu Scholar.js +0 -276
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bangkok Post.js +0 -216
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Baruch Foundation.js +0 -175
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Beobachter.js +0 -175
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bezneng Gajit.js +0 -92
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BibLaTeX.js +0 -888
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BibTeX.js +0 -4236
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Biblio.com.js +0 -216
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bibliontology RDF.js +0 -1166
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Biblioteca Nacional de Maestros.js +0 -213
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bibliotheque et Archives Nationale du Quebec (Pistard).js +0 -147
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bibliotheque et Archives Nationales du Quebec.js +0 -266
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bibliotheque nationale de France.js +0 -872
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BioMed Central.js +0 -585
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BioOne.js +0 -233
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bioconductor.js +0 -343
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Blaetter.js +0 -192
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Blogger.js +0 -244
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bloomberg.js +0 -205
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bloomsbury Food Library.js +0 -296
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bluesky.js +0 -195
- scitex/scholar/.legacy/metadata/urls/zotero_translators/BnF ISBN.js +0 -129
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bookmarks.js +0 -282
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bookshop.org.js +0 -223
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Boston Review.js +0 -332
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bosworth Toller's Anglo-Saxon Dictionary Online.js +0 -496
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bracero History Archive.js +0 -200
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Brill.js +0 -434
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Brukerhandboken.js +0 -153
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bryn Mawr Classical Review.js +0 -303
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Bundesgesetzblatt.js +0 -231
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Business Standard.js +0 -151
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CABI - CAB Abstracts.js +0 -317
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CAOD.js +0 -260
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CBC.js +0 -439
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CCfr (BnF).js +0 -162
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CERN Document Server.js +0 -277
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CEUR Workshop Proceedings.js +0 -145
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CFF References.js +0 -170
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CFF.js +0 -113
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CIA World Factbook.js +0 -128
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CLACSO.js +0 -226
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CLASE.js +0 -135
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CNKI.js +0 -731
- scitex/scholar/.legacy/metadata/urls/zotero_translators/COBISS.js +0 -1945
- scitex/scholar/.legacy/metadata/urls/zotero_translators/COinS.js +0 -336
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CQ Press.js +0 -418
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CROSBI.js +0 -227
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CSIRO Publishing.js +0 -139
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CSL JSON.js +0 -203
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CSV.js +0 -294
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Cairn.info.js +0 -368
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CalMatters.js +0 -228
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Calisphere.js +0 -355
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Camara Brasileira do Livro ISBN.js +0 -842
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Cambridge Core.js +0 -580
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Cambridge Engage Preprints.js +0 -276
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CanLII.js +0 -284
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Canada.com.js +0 -171
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Canadian Letters and Images.js +0 -148
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Canadiana.ca.js +0 -196
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Cascadilla Proceedings Project.js +0 -390
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Cell Press.js +0 -516
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Central and Eastern European Online Library Journals.js +0 -313
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Champlain Society - Collection.js +0 -220
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Chicago Journal of Theoretical Computer Science.js +0 -203
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Christian Science Monitor.js +0 -148
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Chronicling America.js +0 -131
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CiNii Research.js +0 -168
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Citavi 5 XML.js +0 -516
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CiteSeer.js +0 -196
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Citizen Lab.js +0 -347
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Civilization.ca.js +0 -146
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Climate Change and Human Health Literature Portal.js +0 -283
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Clinical Key.js +0 -367
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Code4Lib Journal.js +0 -143
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Colorado State Legislature.js +0 -215
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Columbia University Press.js +0 -238
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Common-Place.js +0 -218
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Computer History Museum Archive.js +0 -1319
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Copernicus.js +0 -461
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Cornell LII.js +0 -252
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Cornell University Press.js +0 -235
- scitex/scholar/.legacy/metadata/urls/zotero_translators/CourtListener.js +0 -265
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Crossref REST.js +0 -1757
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Crossref Unixref XML.js +0 -965
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Current Affairs.js +0 -160
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DABI.js +0 -476
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DAI-Zenon.js +0 -392
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DART-Europe.js +0 -176
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DBLP Computer Science Bibliography.js +0 -462
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DBpia.js +0 -233
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DEPATISnet.js +0 -373
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DOAJ.js +0 -242
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DOI Content Negotiation.js +0 -352
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DOI.js +0 -322
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DPLA.js +0 -425
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DSpace Intermediate Metadata.js +0 -208
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Dagens Nyheter.js +0 -369
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Dagstuhl Research Online Publication Server.js +0 -278
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Dar Almandumah.js +0 -253
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Data.gov.js +0 -225
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Databrary.js +0 -184
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Datacite JSON.js +0 -1182
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Dataverse.js +0 -418
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Daum News.js +0 -139
- scitex/scholar/.legacy/metadata/urls/zotero_translators/De Gruyter Brill.js +0 -674
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Defense Technical Information Center.js +0 -146
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Delpher.js +0 -413
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Demographic Research.js +0 -164
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Denik CZ.js +0 -273
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Der Freitag.js +0 -236
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Der Spiegel.js +0 -479
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Desiring God.js +0 -216
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Deutsche Fotothek.js +0 -364
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Deutsche Nationalbibliothek.js +0 -594
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Dialnet.js +0 -258
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Die Zeit.js +0 -378
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DigiZeitschriften.js +0 -269
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Digital Humanities Quarterly.js +0 -207
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Digital Spy.js +0 -215
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Dimensions.js +0 -233
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Douban.js +0 -316
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Dreier Neuerscheinungsdienst.js +0 -209
- scitex/scholar/.legacy/metadata/urls/zotero_translators/DrugBank.ca.js +0 -209
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Dryad Digital Repository.js +0 -323
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Duke University Press Books.js +0 -250
- scitex/scholar/.legacy/metadata/urls/zotero_translators/E-periodica Switzerland.js +0 -347
- scitex/scholar/.legacy/metadata/urls/zotero_translators/EBSCO Discovery Layer.js +0 -147
- scitex/scholar/.legacy/metadata/urls/zotero_translators/EBSCOhost.js +0 -592
- scitex/scholar/.legacy/metadata/urls/zotero_translators/EIDR.js +0 -184
- scitex/scholar/.legacy/metadata/urls/zotero_translators/EPA National Library Catalog.js +0 -245
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ERIC.js +0 -986
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ESpacenet.js +0 -465
- scitex/scholar/.legacy/metadata/urls/zotero_translators/EUR-Lex.js +0 -423
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Eastview.js +0 -336
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Edinburgh University Press Journals.js +0 -178
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Education Week.js +0 -197
- scitex/scholar/.legacy/metadata/urls/zotero_translators/El Comercio (Peru).js +0 -347
- scitex/scholar/.legacy/metadata/urls/zotero_translators/El Pais.js +0 -262
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Electronic Colloquium on Computational Complexity.js +0 -230
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Elicit.js +0 -120
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Elsevier Health Journals.js +0 -531
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Elsevier Pure.js +0 -420
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Embedded Metadata.js +0 -1951
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Emerald Insight.js +0 -626
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Encyclopedia of Chicago.js +0 -162
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Encyclopedia of Korean Culture.js +0 -221
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Endnote XML.js +0 -1407
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Engineering Village.js +0 -139
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Envidat.js +0 -331
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Epicurious.js +0 -144
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Erudit.js +0 -272
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Euclid.js +0 -220
- scitex/scholar/.legacy/metadata/urls/zotero_translators/EurasiaNet.js +0 -109
- scitex/scholar/.legacy/metadata/urls/zotero_translators/EurogamerUSgamer.js +0 -380
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Europe PMC.js +0 -448
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Evernote.js +0 -104
- scitex/scholar/.legacy/metadata/urls/zotero_translators/F1000 Research.js +0 -655
- scitex/scholar/.legacy/metadata/urls/zotero_translators/FAO Publications.js +0 -1139
- scitex/scholar/.legacy/metadata/urls/zotero_translators/FAZ.NET.js +0 -231
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Fachportal Padagogik.js +0 -839
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Factiva.js +0 -302
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Failed Architecture.js +0 -114
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Fairfax Australia.js +0 -200
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Fatcat.js +0 -425
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Figshare.js +0 -191
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Financial Times.js +0 -187
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Finna.js +0 -357
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Flickr.js +0 -318
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Foreign Affairs.js +0 -485
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Foreign Policy.js +0 -146
- scitex/scholar/.legacy/metadata/urls/zotero_translators/FreeCite.js +0 -95
- scitex/scholar/.legacy/metadata/urls/zotero_translators/FreePatentsOnline.js +0 -265
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Frieze.js +0 -243
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Frontiers.js +0 -667
- scitex/scholar/.legacy/metadata/urls/zotero_translators/GMS German Medical Science.js +0 -319
- scitex/scholar/.legacy/metadata/urls/zotero_translators/GPO Access e-CFR.js +0 -134
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Gale Databases.js +0 -324
- scitex/scholar/.legacy/metadata/urls/zotero_translators/GaleGDC.js +0 -189
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Galegroup.js +0 -327
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Gallica.js +0 -194
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Game Studies.js +0 -155
- scitex/scholar/.legacy/metadata/urls/zotero_translators/GameSpot.js +0 -199
- scitex/scholar/.legacy/metadata/urls/zotero_translators/GameStar GamePro.js +0 -198
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Gasyrlar Awazy.js +0 -156
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Gemeinsamer Bibliotheksverbund ISBN.js +0 -23
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Gene Ontology.js +0 -128
- scitex/scholar/.legacy/metadata/urls/zotero_translators/GitHub.js +0 -501
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Globes.js +0 -243
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Gmail.js +0 -64
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Goodreads.js +0 -219
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Google Books.js +0 -552
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Google Patents.js +0 -959
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Google Play.js +0 -186
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Google Presentation.js +0 -104
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Google Research.js +0 -221
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Google Scholar.js +0 -1361
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Gulag Many Days, Many Lives.js +0 -179
- scitex/scholar/.legacy/metadata/urls/zotero_translators/HAL Archives Ouvertes.js +0 -429
- scitex/scholar/.legacy/metadata/urls/zotero_translators/HCSP.js +0 -312
- scitex/scholar/.legacy/metadata/urls/zotero_translators/HUDOC.js +0 -650
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Haaretz.js +0 -562
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Habr.js +0 -232
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Handelszeitung.js +0 -273
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Hanrei Watch.js +0 -123
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Harper's Magazine.js +0 -365
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Harvard Business Review.js +0 -326
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Harvard Caselaw Access Project.js +0 -244
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Harvard University Press Books.js +0 -286
- scitex/scholar/.legacy/metadata/urls/zotero_translators/HathiTrust.js +0 -311
- scitex/scholar/.legacy/metadata/urls/zotero_translators/HeinOnline.js +0 -266
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Heise.js +0 -200
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Herder.js +0 -236
- scitex/scholar/.legacy/metadata/urls/zotero_translators/HighBeam.js +0 -198
- scitex/scholar/.legacy/metadata/urls/zotero_translators/HighWire 2.0.js +0 -1355
- scitex/scholar/.legacy/metadata/urls/zotero_translators/HighWire.js +0 -209
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Hindawi Publishers.js +0 -177
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Hispanic-American Periodical Index.js +0 -236
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Homeland Security Digital Library.js +0 -426
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Huff Post.js +0 -223
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Human Rights Watch.js +0 -450
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IBISWorld.js +0 -171
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IDEA ALM.js +0 -536
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IEEE Computer Society.js +0 -429
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IEEE Xplore.js +0 -1000
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IETF.js +0 -451
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IGN.js +0 -136
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IMDb.js +0 -566
- scitex/scholar/.legacy/metadata/urls/zotero_translators/INSPIRE.js +0 -247
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IPCC.js +0 -757
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ISTC.js +0 -181
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Idref.js +0 -179
- scitex/scholar/.legacy/metadata/urls/zotero_translators/In These Times.js +0 -196
- scitex/scholar/.legacy/metadata/urls/zotero_translators/InfoTrac.js +0 -279
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Informationssystem Medienpaedagogik.js +0 -305
- scitex/scholar/.legacy/metadata/urls/zotero_translators/IngentaConnect.js +0 -312
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Inside Higher Ed.js +0 -167
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Insignia OPAC.js +0 -114
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Institute of Contemporary Art.js +0 -180
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Institute of Physics.js +0 -340
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Integrum.js +0 -173
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Intellixir.js +0 -264
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Inter-Research Science Center.js +0 -185
- scitex/scholar/.legacy/metadata/urls/zotero_translators/International Nuclear Information System.js +0 -285
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Internet Archive Scholar.js +0 -106
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Internet Archive Wayback Machine.js +0 -152
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Internet Archive.js +0 -552
- scitex/scholar/.legacy/metadata/urls/zotero_translators/InvenioRDM.js +0 -1260
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Isidore.js +0 -235
- scitex/scholar/.legacy/metadata/urls/zotero_translators/J-Stage.js +0 -272
- scitex/scholar/.legacy/metadata/urls/zotero_translators/JETS.js +0 -122
- scitex/scholar/.legacy/metadata/urls/zotero_translators/JISC Historical Texts.js +0 -273
- scitex/scholar/.legacy/metadata/urls/zotero_translators/JRC Publications Repository.js +0 -569
- scitex/scholar/.legacy/metadata/urls/zotero_translators/JSTOR.js +0 -821
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Jahrbuch.js +0 -213
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Japan Times Online.js +0 -138
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Journal of Electronic Publishing.js +0 -147
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Journal of Extension.js +0 -288
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Journal of Machine Learning Research.js +0 -441
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Journal of Religion and Society.js +0 -174
- scitex/scholar/.legacy/metadata/urls/zotero_translators/JurPC.js +0 -274
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Juricaf.js +0 -141
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Juris.js +0 -728
- scitex/scholar/.legacy/metadata/urls/zotero_translators/K10plus ISBN.js +0 -386
- scitex/scholar/.legacy/metadata/urls/zotero_translators/KStudy.js +0 -632
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Kanopy.js +0 -358
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Khaama Press.js +0 -249
- scitex/scholar/.legacy/metadata/urls/zotero_translators/KitapYurdu.com.js +0 -376
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Kommersant.js +0 -174
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Korean National Library.js +0 -621
- scitex/scholar/.legacy/metadata/urls/zotero_translators/L'Annee Philologique.js +0 -267
- scitex/scholar/.legacy/metadata/urls/zotero_translators/LA Times.js +0 -239
- scitex/scholar/.legacy/metadata/urls/zotero_translators/LIBRIS ISBN.js +0 -103
- scitex/scholar/.legacy/metadata/urls/zotero_translators/LIVIVO.js +0 -260
- scitex/scholar/.legacy/metadata/urls/zotero_translators/LWN.net.js +0 -315
- scitex/scholar/.legacy/metadata/urls/zotero_translators/La Croix.js +0 -237
- scitex/scholar/.legacy/metadata/urls/zotero_translators/La Nacion (Argentina).js +0 -231
- scitex/scholar/.legacy/metadata/urls/zotero_translators/La Presse.js +0 -218
- scitex/scholar/.legacy/metadata/urls/zotero_translators/La Republica (Peru).js +0 -174
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Lagen.nu.js +0 -214
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Landesbibliographie Baden-Wurttemberg.js +0 -324
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Lapham's Quarterly.js +0 -1062
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Le Devoir.js +0 -167
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Le Figaro.js +0 -225
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Le Maitron.js +0 -484
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Le Monde.js +0 -258
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Le monde diplomatique.js +0 -200
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Legifrance.js +0 -641
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Legislative Insight.js +0 -406
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Lexis+.js +0 -264
- scitex/scholar/.legacy/metadata/urls/zotero_translators/LexisNexis.js +0 -505
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Libraries Tasmania.js +0 -778
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Aleph).js +0 -385
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Amicus).js +0 -254
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Aquabrowser).js +0 -253
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (BiblioCommons).js +0 -249
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Blacklight).js +0 -341
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Capita Prism).js +0 -162
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (DRA).js +0 -203
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Dynix).js +0 -315
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Encore).js +0 -211
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (InnoPAC).js +0 -305
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Koha).js +0 -225
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Mango).js +0 -285
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (OPALS).js +0 -200
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (PICA).js +0 -2120
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (PICA2).js +0 -331
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Pika).js +0 -488
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Polaris).js +0 -183
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Quolto).js +0 -320
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (RERO ILS).js +0 -754
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (SIRSI eLibrary).js +0 -407
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (SIRSI).js +0 -452
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (SLIMS).js +0 -146
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (TIND ILS).js +0 -773
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (TLCYouSeeMore).js +0 -132
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (TinREAD).js +0 -277
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (VTLS).js +0 -125
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Visual Library 2021).js +0 -765
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Voyager 7).js +0 -199
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Catalog (Voyager).js +0 -212
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Genesis.js +0 -337
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library Hub Discover.js +0 -359
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library of Congress Digital Collections.js +0 -869
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Library of Congress ISBN.js +0 -86
- scitex/scholar/.legacy/metadata/urls/zotero_translators/LingBuzz.js +0 -359
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Lippincott Williams and Wilkins.js +0 -341
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Literary Hub.js +0 -950
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Litres.js +0 -236
- scitex/scholar/.legacy/metadata/urls/zotero_translators/LiveJournal.js +0 -219
- scitex/scholar/.legacy/metadata/urls/zotero_translators/London Review of Books.js +0 -291
- scitex/scholar/.legacy/metadata/urls/zotero_translators/LookUs.js +0 -260
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Lulu.js +0 -264
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MAB2.js +0 -373
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MARC.js +0 -1080
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MARCXML.js +0 -489
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MCV.js +0 -258
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MDPI Journals.js +0 -356
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MEDLINEnbib.js +0 -1561
- scitex/scholar/.legacy/metadata/urls/zotero_translators/METS.js +0 -384
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MIDAS Journals.js +0 -343
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MIT Press Books.js +0 -637
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MODS.js +0 -2545
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MPG PuRe.js +0 -541
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Mailman.js +0 -136
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Mainichi Daily News.js +0 -189
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Mastodon.js +0 -198
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Matbugat.ru.js +0 -110
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Max Planck Institute for the History of Science Virtual Laboratory Library.js +0 -136
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Medium.js +0 -208
- scitex/scholar/.legacy/metadata/urls/zotero_translators/MetaLib.js +0 -126
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Microbiology Society Journals.js +0 -343
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Microsoft Academic.js +0 -424
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Mikromarc.js +0 -207
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Milli Kutuphane.js +0 -244
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Musee du Louvre.js +0 -265
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NASA ADS.js +0 -889
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NASA NTRS.js +0 -610
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NCBI Nucleotide.js +0 -227
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NPR.js +0 -341
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NRC Research Press.js +0 -181
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NRC.nl.js +0 -226
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NTSB Accident Reports.js +0 -226
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NYPL Menus.js +0 -275
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NYPL Research Catalog.js +0 -458
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NYTimes.com.js +0 -858
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NZZ.ch.js +0 -272
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Nagoya University OPAC.js +0 -336
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Academies Press.js +0 -243
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Agriculture Library.js +0 -524
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Archives of Australia.js +0 -522
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Archives of South Africa.js +0 -122
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Bureau of Economic Research.js +0 -363
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Diet Library Catalogue.js +0 -333
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Gallery of Art - USA.js +0 -149
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Gallery of Australia.js +0 -252
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Library of Australia (new catalog).js +0 -223
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Library of Belarus.js +0 -171
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Library of Norway.js +0 -310
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Library of Poland ISBN.js +0 -140
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Post.js +0 -186
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Technical Reports Library.js +0 -276
- scitex/scholar/.legacy/metadata/urls/zotero_translators/National Transportation Library ROSA P.js +0 -562
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Nature Publishing Group.js +0 -3394
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Neural Information Processing Systems.js +0 -385
- scitex/scholar/.legacy/metadata/urls/zotero_translators/New Left Review.js +0 -245
- scitex/scholar/.legacy/metadata/urls/zotero_translators/New Zealand Herald.js +0 -282
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Newlines Magazine.js +0 -190
- scitex/scholar/.legacy/metadata/urls/zotero_translators/News Corp Australia.js +0 -251
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NewsBank.js +0 -202
- scitex/scholar/.legacy/metadata/urls/zotero_translators/NewsnetTamedia.js +0 -509
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Noor Digital Library.js +0 -267
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Note HTML.js +0 -206
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Note Markdown.js +0 -1638
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Notre Dame Philosophical Reviews.js +0 -201
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OAPEN.js +0 -331
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OCLC WorldCat FirstSearch.js +0 -213
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OECD.js +0 -216
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ORCID.js +0 -104
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OSF Preprints.js +0 -417
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OSTI Energy Citations.js +0 -202
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OVID Tagged.js +0 -1226
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OZON.ru.js +0 -465
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OhioLINK.js +0 -43
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Old Bailey Online.js +0 -315
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Open Conf.js +0 -172
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Open Knowledge Repository.js +0 -811
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Open WorldCat.js +0 -1401
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OpenAlex JSON.js +0 -740
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OpenAlex.js +0 -444
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OpenEdition Books.js +0 -155
- scitex/scholar/.legacy/metadata/urls/zotero_translators/OpenEdition Journals.js +0 -432
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Optical Society of America.js +0 -562
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Optimization Online.js +0 -418
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Ovid.js +0 -302
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Oxford Dictionaries Premium.js +0 -194
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Oxford English Dictionary.js +0 -122
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Oxford Music and Art Online.js +0 -120
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Oxford Reference.js +0 -202
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Oxford University Press.js +0 -277
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PC Gamer.js +0 -302
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PC Games.js +0 -128
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PEI Archival Information Network.js +0 -242
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PEP Web.js +0 -165
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PKP Catalog Systems.js +0 -1455
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PLoS Journals.js +0 -284
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PRC History Review.js +0 -298
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Pajhwok Afghan News.js +0 -198
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Papers Past.js +0 -297
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Paris Review.js +0 -227
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Pastebin.js +0 -199
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Patents - USPTO.js +0 -210
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Peeters.js +0 -587
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Perceiving Systems.js +0 -350
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Perlego.js +0 -416
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PhilPapers.js +0 -249
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Philosopher's Imprint.js +0 -169
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Pleade.js +0 -329
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Polygon.js +0 -270
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Potsdamer Neueste Nachrichten.js +0 -188
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Preprints.org.js +0 -305
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Primo 2018.js +0 -126
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Primo Normalized XML.js +0 -987
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Primo.js +0 -322
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ProMED.js +0 -66
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ProQuest Ebook Central.js +0 -226
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ProQuest PolicyFile.js +0 -115
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ProQuest.js +0 -2210
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Probing the Past.js +0 -151
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Project Gutenberg.js +0 -191
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Project MUSE.js +0 -451
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Protein Data Bank.js +0 -445
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PubFactory Journals.js +0 -712
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PubMed Central.js +0 -577
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PubMed XML.js +0 -1139
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PubMed.js +0 -1317
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PubPub.js +0 -530
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Public Record Office Victoria.js +0 -252
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Publications Office of the European Union.js +0 -540
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Publications du Quebec.js +0 -225
- scitex/scholar/.legacy/metadata/urls/zotero_translators/PyPI.js +0 -288
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Qatar Digital Library.js +0 -802
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Queensland State Archives.js +0 -303
- scitex/scholar/.legacy/metadata/urls/zotero_translators/R-Packages.js +0 -410
- scitex/scholar/.legacy/metadata/urls/zotero_translators/RAND.js +0 -283
- scitex/scholar/.legacy/metadata/urls/zotero_translators/RDF.js +0 -1777
- scitex/scholar/.legacy/metadata/urls/zotero_translators/REDALYC.js +0 -196
- scitex/scholar/.legacy/metadata/urls/zotero_translators/RIS.js +0 -7265
- scitex/scholar/.legacy/metadata/urls/zotero_translators/RSC Publishing.js +0 -250
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Radio Free Europe Radio Liberty.js +0 -706
- scitex/scholar/.legacy/metadata/urls/zotero_translators/RePEc - Econpapers.js +0 -725
- scitex/scholar/.legacy/metadata/urls/zotero_translators/RePEc - IDEAS.js +0 -337
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Rechtspraak.nl.js +0 -295
- scitex/scholar/.legacy/metadata/urls/zotero_translators/RefWorks Tagged.js +0 -1185
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ReferBibIX.js +0 -463
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Regeringskansliet.js +0 -89
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Research Square.js +0 -335
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ResearchGate.js +0 -394
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Retsinformation.js +0 -348
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Reuters.js +0 -255
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Rock, Paper, Shotgun.js +0 -304
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Roll Call.js +0 -173
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Russian State Library.js +0 -1517
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SAE Papers.js +0 -241
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SAGE Journals.js +0 -427
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SAGE Knowledge.js +0 -505
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SAILDART.js +0 -364
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SALT Research Archives.js +0 -196
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SFU IPinCH.js +0 -946
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SIPRI.js +0 -256
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SIRS Knowledge Source.js +0 -546
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SLUB Dresden.js +0 -300
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SORA.js +0 -340
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SSOAR.js +0 -399
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SSRN.js +0 -235
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SVT Nyheter.js +0 -381
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Sacramento Bee.js +0 -274
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Safari Books Online.js +0 -391
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Scholars Portal Journals.js +0 -220
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Scholia.js +0 -189
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Schweizer Radio und Fernsehen SRF.js +0 -152
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SciELO.js +0 -440
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ScienceDirect.js +0 -1304
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Scopus.js +0 -418
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Semantic Scholar.js +0 -513
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Silverchair.js +0 -886
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Slate.js +0 -228
- scitex/scholar/.legacy/metadata/urls/zotero_translators/SlideShare.js +0 -112
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Springer Link.js +0 -696
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Stack Exchange.js +0 -134
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Standard Ebooks.js +0 -198
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Stanford Encyclopedia of Philosophy.js +0 -285
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Stanford University Press.js +0 -343
- scitex/scholar/.legacy/metadata/urls/zotero_translators/State Records Office of Western Australia.js +0 -439
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Stitcher.js +0 -141
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Store norske leksikon.js +0 -291
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Stuff.co.nz.js +0 -446
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Substack.js +0 -237
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Sud Ouest.js +0 -181
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Sueddeutsche.de.js +0 -205
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Summon 2.js +0 -117
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Superlib.js +0 -647
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Svenska Dagbladet.js +0 -274
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Sveriges radio.js +0 -416
- scitex/scholar/.legacy/metadata/urls/zotero_translators/TEI.js +0 -648
- scitex/scholar/.legacy/metadata/urls/zotero_translators/TV by the Numbers.js +0 -194
- scitex/scholar/.legacy/metadata/urls/zotero_translators/TVNZ.js +0 -165
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Tagesspiegel.js +0 -249
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Talis Aspire.js +0 -316
- scitex/scholar/.legacy/metadata/urls/zotero_translators/TalisPrism.js +0 -445
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Tatknigafund.js +0 -174
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Tatpressa.ru.js +0 -121
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Taylor & Francis eBooks.js +0 -334
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Taylor and Francis+NEJM.js +0 -813
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Tesis Doctorals en Xarxa.js +0 -233
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Art Newspaper.js +0 -268
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Atlantic.js +0 -535
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Boston Globe.js +0 -285
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Chronicle of Higher Education.js +0 -308
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Daily Beast.js +0 -183
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Economic Times - The Times of India.js +0 -305
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Economist.js +0 -207
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Free Dictionary.js +0 -58
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Globe and Mail.js +0 -241
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Guardian.js +0 -717
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Hamilton Spectator.js +0 -129
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Hindu.js +0 -318
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Independent.js +0 -184
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Intercept.js +0 -258
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Met.js +0 -300
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Microfinance Gateway.js +0 -174
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Nation.js +0 -188
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The National Archives (UK).js +0 -242
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The New Republic.js +0 -160
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The New York Review of Books.js +0 -467
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The New Yorker.js +0 -360
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Open Library.js +0 -220
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Straits Times.js +0 -528
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Telegraph.js +0 -337
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Times and Sunday Times.js +0 -180
- scitex/scholar/.legacy/metadata/urls/zotero_translators/The Times of Israel.js +0 -151
- scitex/scholar/.legacy/metadata/urls/zotero_translators/TheMarker.js +0 -108
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Theory of Computing.js +0 -488
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ThesesFR.js +0 -298
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Thieme.js +0 -326
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Time.com.js +0 -557
- scitex/scholar/.legacy/metadata/urls/zotero_translators/TimesMachine.js +0 -222
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Tony Blair Institute for Global Change.js +0 -195
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Toronto Star.js +0 -331
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Transportation Research Board.js +0 -253
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Treesearch.js +0 -535
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Trove.js +0 -616
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Tumblr.js +0 -179
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Twitter.js +0 -413
- scitex/scholar/.legacy/metadata/urls/zotero_translators/UChicago VuFind.js +0 -907
- scitex/scholar/.legacy/metadata/urls/zotero_translators/UNZ Print Archive.js +0 -276
- scitex/scholar/.legacy/metadata/urls/zotero_translators/UPCommons.js +0 -227
- scitex/scholar/.legacy/metadata/urls/zotero_translators/US National Archives Research Catalog.js +0 -275
- scitex/scholar/.legacy/metadata/urls/zotero_translators/USENIX.js +0 -151
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Ubiquity Journals.js +0 -228
- scitex/scholar/.legacy/metadata/urls/zotero_translators/University Press Scholarship.js +0 -301
- scitex/scholar/.legacy/metadata/urls/zotero_translators/University of California Press Books.js +0 -403
- scitex/scholar/.legacy/metadata/urls/zotero_translators/University of Chicago Press Books.js +0 -378
- scitex/scholar/.legacy/metadata/urls/zotero_translators/University of Wisconsin-Madison Libraries Catalog.js +0 -298
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Unqualified Dublin Core RDF.js +0 -153
- scitex/scholar/.legacy/metadata/urls/zotero_translators/UpToDate References.js +0 -203
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Vanity Fair.js +0 -242
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Verniana-Jules Verne Studies.js +0 -190
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Verso Books.js +0 -311
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Vice.js +0 -445
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Victoria & Albert Museum.js +0 -277
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Vimeo.js +0 -188
- scitex/scholar/.legacy/metadata/urls/zotero_translators/VoxEU.js +0 -151
- scitex/scholar/.legacy/metadata/urls/zotero_translators/WHO.js +0 -458
- scitex/scholar/.legacy/metadata/urls/zotero_translators/WIPO.js +0 -189
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wall Street Journal.js +0 -525
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wanfang Data.js +0 -310
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Washington Monthly.js +0 -195
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Washington Post.js +0 -447
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Web of Science Nextgen.js +0 -715
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Web of Science Tagged.js +0 -1242
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Web of Science.js +0 -228
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Welt Online.js +0 -161
- scitex/scholar/.legacy/metadata/urls/zotero_translators/WestLaw UK.js +0 -190
- scitex/scholar/.legacy/metadata/urls/zotero_translators/WikiLeaks PlusD.js +0 -182
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wikidata QuickStatements.js +0 -306
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wikidata.js +0 -911
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wikimedia Commons.js +0 -285
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wikipedia Citation Templates.js +0 -432
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wikipedia.js +0 -385
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wikisource.js +0 -399
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wikiwand.js +0 -122
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wiktionary.js +0 -141
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wildlife Biology in Practice.js +0 -172
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wiley Online Library.js +0 -1412
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wilson Center Digital Archive.js +0 -321
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Winnipeg Free Press.js +0 -204
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Wired.js +0 -249
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Womennews.js +0 -230
- scitex/scholar/.legacy/metadata/urls/zotero_translators/World Digital Library.js +0 -403
- scitex/scholar/.legacy/metadata/urls/zotero_translators/World History Connected.js +0 -185
- scitex/scholar/.legacy/metadata/urls/zotero_translators/World Shakespeare Bibliography Online.js +0 -595
- scitex/scholar/.legacy/metadata/urls/zotero_translators/WorldCat Discovery Service.js +0 -630
- scitex/scholar/.legacy/metadata/urls/zotero_translators/XML ContextObject.js +0 -274
- scitex/scholar/.legacy/metadata/urls/zotero_translators/YPSF.js +0 -224
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Yandex Books.js +0 -265
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Ynet.js +0 -171
- scitex/scholar/.legacy/metadata/urls/zotero_translators/YouTube.js +0 -209
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ZIPonline.js +0 -267
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ZOBODAT.js +0 -341
- scitex/scholar/.legacy/metadata/urls/zotero_translators/Zotero RDF.js +0 -583
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ZoteroBib.js +0 -94
- scitex/scholar/.legacy/metadata/urls/zotero_translators/arXiv.org.js +0 -1099
- scitex/scholar/.legacy/metadata/urls/zotero_translators/artnet.js +0 -207
- scitex/scholar/.legacy/metadata/urls/zotero_translators/beck-online.js +0 -1339
- scitex/scholar/.legacy/metadata/urls/zotero_translators/clinicaltrials.gov.js +0 -331
- scitex/scholar/.legacy/metadata/urls/zotero_translators/dLibra.js +0 -367
- scitex/scholar/.legacy/metadata/urls/zotero_translators/dejure.org.js +0 -242
- scitex/scholar/.legacy/metadata/urls/zotero_translators/deleted.txt +0 -132
- scitex/scholar/.legacy/metadata/urls/zotero_translators/dhistory.js +0 -103
- scitex/scholar/.legacy/metadata/urls/zotero_translators/digibib.net.js +0 -245
- scitex/scholar/.legacy/metadata/urls/zotero_translators/eLibrary.ru.js +0 -867
- scitex/scholar/.legacy/metadata/urls/zotero_translators/eLife.js +0 -462
- scitex/scholar/.legacy/metadata/urls/zotero_translators/eMJA.js +0 -246
- scitex/scholar/.legacy/metadata/urls/zotero_translators/eMedicine.js +0 -123
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ePrint IACR.js +0 -608
- scitex/scholar/.legacy/metadata/urls/zotero_translators/ebrary.js +0 -140
- scitex/scholar/.legacy/metadata/urls/zotero_translators/etatar.ru.js +0 -104
- scitex/scholar/.legacy/metadata/urls/zotero_translators/feb-web.ru.js +0 -167
- scitex/scholar/.legacy/metadata/urls/zotero_translators/fishpond.co.nz.js +0 -224
- scitex/scholar/.legacy/metadata/urls/zotero_translators/fr-online.de.js +0 -209
- scitex/scholar/.legacy/metadata/urls/zotero_translators/govinfo.js +0 -189
- scitex/scholar/.legacy/metadata/urls/zotero_translators/index.d.ts +0 -1646
- scitex/scholar/.legacy/metadata/urls/zotero_translators/informIT database.js +0 -248
- scitex/scholar/.legacy/metadata/urls/zotero_translators/io-port.js +0 -68
- scitex/scholar/.legacy/metadata/urls/zotero_translators/jsconfig.json +0 -10
- scitex/scholar/.legacy/metadata/urls/zotero_translators/jurion.js +0 -377
- scitex/scholar/.legacy/metadata/urls/zotero_translators/mEDRA.js +0 -597
- scitex/scholar/.legacy/metadata/urls/zotero_translators/magazines.russ.ru.js +0 -120
- scitex/scholar/.legacy/metadata/urls/zotero_translators/medes.js +0 -284
- scitex/scholar/.legacy/metadata/urls/zotero_translators/newshub.co.nz.js +0 -206
- scitex/scholar/.legacy/metadata/urls/zotero_translators/newspapers.com.js +0 -335
- scitex/scholar/.legacy/metadata/urls/zotero_translators/openJur.js +0 -161
- scitex/scholar/.legacy/metadata/urls/zotero_translators/package-lock.json +0 -2345
- scitex/scholar/.legacy/metadata/urls/zotero_translators/package.json +0 -24
- scitex/scholar/.legacy/metadata/urls/zotero_translators/reddit.js +0 -275
- scitex/scholar/.legacy/metadata/urls/zotero_translators/sbn.it.js +0 -186
- scitex/scholar/.legacy/metadata/urls/zotero_translators/scinapse.js +0 -273
- scitex/scholar/.legacy/metadata/urls/zotero_translators/semantics Visual Library.js +0 -643
- scitex/scholar/.legacy/metadata/urls/zotero_translators/taz.de.js +0 -200
- scitex/scholar/.legacy/metadata/urls/zotero_translators/unAPI.js +0 -481
- scitex/scholar/.legacy/metadata/urls/zotero_translators/wiso.js +0 -314
- scitex/scholar/.legacy/metadata/urls/zotero_translators/zbMATH.js +0 -278
- scitex/scholar/.legacy/metadata/urls/zotero_translators/zotero.org.js +0 -311
- scitex/scholar/.legacy/search/README.md +0 -205
- scitex/scholar/.legacy/search/_Embedder.py +0 -329
- scitex/scholar/.legacy/search/_SemanticSearch.py +0 -278
- scitex/scholar/.legacy/search/_SemanticSearchEngine.py +0 -452
- scitex/scholar/.legacy/search/_UnifiedSearcher.py +0 -1353
- scitex/scholar/.legacy/search/_VectorDatabase.py +0 -443
- scitex/scholar/.legacy/search/__init__.py +0 -25
- scitex/scholar/.legacy/storage/_EnhancedStorageManager.py +0 -617
- scitex/scholar/.legacy/storage/__init__.py +0 -19
- scitex/scholar/CLAUDE.md +0 -257
- scitex/scholar/TODO.md +0 -174
- scitex/scholar/_mcp_handlers.py +0 -685
- scitex/scholar/_mcp_tool_schemas.py +0 -339
- scitex/scholar/docs/backup/papers-orig.bib +0 -698
- scitex/scholar/docs/backup/papers.bib.zip +0 -0
- scitex/scholar/docs/to_claude/bin/elisp/check_parens.sh +0 -56
- scitex/scholar/docs/to_claude/bin/elisp/elisp-ci/README.md +0 -412
- scitex/scholar/docs/to_claude/bin/elisp/elisp-ci/elisp-ci +0 -622
- scitex/scholar/docs/to_claude/bin/elisp/elisp-ci/elisp-ci-simple +0 -105
- scitex/scholar/docs/to_claude/bin/elisp/find_incorrect_require_provide_statements.sh +0 -113
- scitex/scholar/docs/to_claude/bin/elisp/run_tests_elisp.sh +0 -532
- scitex/scholar/docs/to_claude/bin/elisp/run_tests_elisp_v02.sh +0 -555
- scitex/scholar/docs/to_claude/bin/elisp/sync_elisp_tdd.sh +0 -626
- scitex/scholar/docs/to_claude/bin/general/claude_emacs_server.sh +0 -192
- scitex/scholar/docs/to_claude/bin/general/create_github_release.sh +0 -36
- scitex/scholar/docs/to_claude/bin/general/find_errors.sh +0 -75
- scitex/scholar/docs/to_claude/bin/general/rename.sh +0 -145
- scitex/scholar/docs/to_claude/bin/general/render_mermaid.sh +0 -116
- scitex/scholar/docs/to_claude/bin/general/safe_rm.sh +0 -75
- scitex/scholar/docs/to_claude/bin/general/view_repo.sh +0 -4
- scitex/scholar/docs/to_claude/bin/general/wsl2-buzzer.sh +0 -73
- scitex/scholar/docs/to_claude/bin/python/black_all.sh +0 -41
- scitex/scholar/docs/to_claude/bin/python/run_tests_python_pip_package.sh +0 -291
- scitex/scholar/docs/to_claude/bin/safe_rm.sh +0 -3
- scitex/scholar/docs/to_claude/bin/slurm/README.md +0 -54
- scitex/scholar/docs/to_claude/bin/slurm/login.sh +0 -23
- scitex/scholar/docs/to_claude/bin/slurm/request.sh +0 -62
- scitex/scholar/docs/to_claude/bin/slurm/run.sh +0 -73
- scitex/scholar/docs/to_claude/examples/README.md +0 -9
- scitex/scholar/docs/to_claude/examples/example-elisp-project-emacs-hello-world/ELISP-TEST-REPORT-20250513-012234-48-PASSED-49-TOTAL-97-PERCENT.org +0 -105
- scitex/scholar/docs/to_claude/examples/example-elisp-project-emacs-hello-world/LATEST-ELISP-REPORT.org +0 -105
- scitex/scholar/docs/to_claude/examples/example-elisp-project-emacs-hello-world/README.md +0 -11
- scitex/scholar/docs/to_claude/examples/example-elisp-project-emacs-hello-world/run_tests.sh +0 -652
- scitex/scholar/docs/to_claude/examples/example-elisp-project-emacs-hello-world/tests/test-ehw-core/ELISP-TEST-REPORT-20250512-235622-0-SUCCESS-4-TOTAL-0-PERCENT.org +0 -25
- scitex/scholar/docs/to_claude/examples/example-elisp-project-emacs-hello-world/tests/test-ehw-friends/ELISP-TEST-REPORT-20250512-235622-0-SUCCESS-34-TOTAL-0-PERCENT.org +0 -66
- scitex/scholar/docs/to_claude/examples/example-elisp-project-emacs-hello-world/tests/test-ehw-prep/ELISP-TEST-REPORT-20250512-235622-0-SUCCESS-5-TOTAL-0-PERCENT.org +0 -26
- scitex/scholar/docs/to_claude/examples/example-elisp-project-emacs-hello-world/tests/test-ehw-utils/ELISP-TEST-REPORT-20250512-235622-0-SUCCESS-4-TOTAL-0-PERCENT.org +0 -25
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/.gitignore +0 -626
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/README.md +0 -155
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/config/MNIST.yaml +0 -24
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/config/PATH.yaml +0 -30
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/data/.gitkeep +0 -0
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/scripts/mnist/clf_svm.py +0 -124
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/scripts/mnist/download.py +0 -165
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/scripts/mnist/main.sh +0 -26
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/scripts/mnist/plot_conf_mat.py +0 -86
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/scripts/mnist/plot_digits.py +0 -118
- scitex/scholar/docs/to_claude/examples/example-python-project-scitex/scripts/mnist/plot_umap_space.py +0 -110
- scitex/scholar/docs/to_claude/guidelines/README.md +0 -9
- scitex/scholar/docs/to_claude/guidelines/USER_PHILOSOPHY/01_DEVELOPMENT_CYCLE.md +0 -47
- scitex/scholar/docs/to_claude/guidelines/USER_PHILOSOPHY/02_NAMING_CONVENSIONS.md +0 -91
- scitex/scholar/docs/to_claude/guidelines/USER_PHILOSOPHY/03_ARCHITECTUAL_AGREEMENT_PROCESS.md +0 -86
- scitex/scholar/docs/to_claude/guidelines/USER_PHILOSOPHY/04_ARCHITECTURE_PREDEFINED.md +0 -77
- scitex/scholar/docs/to_claude/guidelines/USER_PHILOSOPHY/05_PRIORITY_CONFIG.md +0 -22
- scitex/scholar/docs/to_claude/guidelines/USER_PHILOSOPHY/06_MULTIPLE_SPECIAL_AGENTS.md +0 -35
- scitex/scholar/docs/to_claude/guidelines/USER_PHILOSOPHY/07_DEBUGGING_TECHNIQUES.md +0 -153
- scitex/scholar/docs/to_claude/guidelines/command/IMPORTANT-rm.md +0 -69
- scitex/scholar/docs/to_claude/guidelines/command/IMPORTANT-tree.md +0 -162
- scitex/scholar/docs/to_claude/guidelines/elisp/IMPORTANT-ELISP-01-basic.md +0 -65
- scitex/scholar/docs/to_claude/guidelines/elisp/IMPORTANT-ELISP-02-project-structure.md +0 -97
- scitex/scholar/docs/to_claude/guidelines/elisp/IMPORTANT-ELISP-03-file-template.md +0 -70
- scitex/scholar/docs/to_claude/guidelines/elisp/IMPORTANT-ELISP-04-coding-style.md +0 -42
- scitex/scholar/docs/to_claude/guidelines/elisp/IMPORTANT-ELISP-05-testing-guide.md +0 -190
- scitex/scholar/docs/to_claude/guidelines/elisp/IMPORTANT-ELISP-99-example-project.md +0 -15
- scitex/scholar/docs/to_claude/guidelines/elisp/ci.md +0 -650
- scitex/scholar/docs/to_claude/guidelines/elisp/testing-with-docker.md +0 -243
- scitex/scholar/docs/to_claude/guidelines/programming_common/EXAMPLE-README-MODULE-ROOT.md +0 -32
- scitex/scholar/docs/to_claude/guidelines/programming_common/EXAMPLE-README-REPOSITORY-ROOT.md +0 -60
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-art-of-readable-code.md +0 -1317
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-art-of-testing.md +0 -799
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-cleanliness.md +0 -18
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-documentation-performance-claims.md +0 -163
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-general.md +0 -156
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-refactoring.md +0 -32
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-regression-prevention.md +0 -14
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-slurm.md +0 -73
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-start-from-small.md +0 -30
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-test-driven-workflow.md +0 -80
- scitex/scholar/docs/to_claude/guidelines/programming_common/IMPORTANT-version-control.md +0 -47
- scitex/scholar/docs/to_claude/guidelines/programming_common/clean-code.md +0 -305
- scitex/scholar/docs/to_claude/guidelines/programming_common/debugging-message.md +0 -52
- scitex/scholar/docs/to_claude/guidelines/programming_common/do-not-repeat-yourself.md +0 -27
- scitex/scholar/docs/to_claude/guidelines/programming_common/emacs-server.md +0 -39
- scitex/scholar/docs/to_claude/guidelines/programming_common/keep-it-simple-stupid.md +0 -19
- scitex/scholar/docs/to_claude/guidelines/programming_common/renaming-and-cleaning-workflow.md +0 -311
- scitex/scholar/docs/to_claude/guidelines/programming_common/screen.md +0 -32
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-CLAUDE_ID.md +0 -15
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-beyond-control.md +0 -14
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-bug-report.md +0 -43
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-cleanliness.md +0 -162
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-communication.md +0 -13
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-do-not-create-any-new-file-nor-directory-in-project-root.md +0 -9
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-documentation.md +0 -11
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-feature-request.md +0 -33
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-general-multi-agent-coordination.md +0 -311
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-multi-agent-protocol.md +0 -97
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-project-management-bulletin-board.md +0 -48
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-project-management-markdown.md +0 -156
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-project-management-org.org +0 -161
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-tools.md +0 -10
- scitex/scholar/docs/to_claude/guidelines/project/IMPORTANT-understand-message-in-filename.md +0 -12
- scitex/scholar/docs/to_claude/guidelines/project/general.md +0 -7
- scitex/scholar/docs/to_claude/guidelines/project/report.md +0 -50
- scitex/scholar/docs/to_claude/guidelines/project/timeline-gantt-chart.md +0 -49
- scitex/scholar/docs/to_claude/guidelines/python/CHECKLIST.md +0 -51
- scitex/scholar/docs/to_claude/guidelines/python/HOW-TO-DEBUG-with-MULTIPLE_AGENTS.md +0 -191
- scitex/scholar/docs/to_claude/guidelines/python/Machine-Learning.md +0 -15
- scitex/scholar/docs/to_claude/guidelines/python/NOT-FULL-PYTEST-BUT-PARTIAL-PYTEST.md +0 -21
- scitex/scholar/docs/to_claude/guidelines/python/django.md +0 -217
- scitex/scholar/docs/to_claude/guidelines/python/env.md +0 -10
- scitex/scholar/docs/to_claude/guidelines/python/general.md +0 -55
- scitex/scholar/docs/to_claude/guidelines/python/official/cipdb-README.md +0 -219
- scitex/scholar/docs/to_claude/guidelines/python/official/fastmcp-README.md +0 -442
- scitex/scholar/docs/to_claude/guidelines/python/official/fastmcp-TESTING.md +0 -146
- scitex/scholar/docs/to_claude/guidelines/python/official/icecream-README.md +0 -433
- scitex/scholar/docs/to_claude/guidelines/python/official/priority_config-README.md +0 -126
- scitex/scholar/docs/to_claude/guidelines/python/scitex/01-basic.md +0 -42
- scitex/scholar/docs/to_claude/guidelines/python/scitex/02-file-template.md +0 -132
- scitex/scholar/docs/to_claude/guidelines/python/scitex/03-configuration.md +0 -53
- scitex/scholar/docs/to_claude/guidelines/python/scitex/04-coding-style.md +0 -126
- scitex/scholar/docs/to_claude/guidelines/python/scitex/05-testing-guide.md +0 -56
- scitex/scholar/docs/to_claude/guidelines/python/scitex/06-examples-guide.md +0 -42
- scitex/scholar/docs/to_claude/guidelines/python/scitex/11-gen-module.md +0 -15
- scitex/scholar/docs/to_claude/guidelines/python/scitex/11-session-module.md +0 -24
- scitex/scholar/docs/to_claude/guidelines/python/scitex/12-io-module.md +0 -112
- scitex/scholar/docs/to_claude/guidelines/python/scitex/13-plt-module.md +0 -101
- scitex/scholar/docs/to_claude/guidelines/python/scitex/14-dsp-module.md +0 -78
- scitex/scholar/docs/to_claude/guidelines/python/scitex/15-pd-module.md +0 -24
- scitex/scholar/docs/to_claude/guidelines/python/scitex/16-stats-module.md +0 -79
- scitex/scholar/docs/to_claude/guidelines/python/scitex/17-other-modules.md +0 -23
- scitex/scholar/docs/to_claude/guidelines/python/scitex/17-str-module.md +0 -24
- scitex/scholar/docs/to_claude/guidelines/python/scitex/18-directory-structure-for-scientific-work.md +0 -48
- scitex/scholar/docs/to_claude/guidelines/python/scitex/19-directory-structure-for-pip-package.md +0 -234
- scitex/scholar/docs/to_claude/guidelines/python/scitex/99-example-project.md +0 -19
- scitex/scholar/docs/to_claude/guidelines/python/zen_of_python.md +0 -82
- scitex/scholar/docs/to_claude/guidelines/science/IMPORTANT-general.md +0 -16
- scitex/scholar/docs/to_claude/guidelines/science/IMPORTANT-scientific-attitude.md +0 -25
- scitex/scholar/docs/to_claude/guidelines/science/scientific-writing-abstract.md +0 -93
- scitex/scholar/docs/to_claude/guidelines/science/scientific-writing-discussion.md +0 -116
- scitex/scholar/docs/to_claude/guidelines/science/scientific-writing-general-1.md +0 -157
- scitex/scholar/docs/to_claude/guidelines/science/scientific-writing-general-2.md +0 -83
- scitex/scholar/docs/to_claude/guidelines/science/scientific-writing-introduction.md +0 -123
- scitex/scholar/docs/to_claude/guidelines/science/scientific-writing-methods.md +0 -88
- scitex/scholar/docs/to_claude/guidelines/shell/IMPORTANT-general.md +0 -196
- scitex/scholar/examples/SUGGESTIONS.md +0 -865
- scitex/scholar/examples/dev.py +0 -38
- scitex/scholar/library/neurovista/info/bibtex/seizure_prediction_enriched.bib +0 -1092
- scitex/stats/_mcp_handlers.py +0 -1191
- scitex/stats/_mcp_tool_schemas.py +0 -384
- scitex/template/.legacy/_clone_project.py +0 -267
- scitex/template/_mcp_handlers.py +0 -259
- scitex/template/_mcp_tool_schemas.py +0 -112
- scitex/writer/.legacy/Writer_v01-refactored.py +0 -189
- scitex/writer/.legacy/_compile.py +0 -342
- scitex/writer/_compile_async.py +0 -126
- scitex/writer/_validate_tree_structures.py +0 -197
- scitex/writer/dataclasses/config/_WriterConfig.py +0 -175
- scitex/writer/dataclasses/contents/_ManuscriptContents.py +0 -236
- scitex/writer/dataclasses/core/_Document.py +0 -146
- scitex/writer/dataclasses/core/_DocumentSection.py +0 -546
- scitex/writer/dataclasses/results/_CompilationResult.py +0 -165
- scitex/writer/dataclasses/results/_LaTeXIssue.py +0 -102
- scitex/writer/dataclasses/tree/MINIMUM_FILES.md +0 -121
- scitex/writer/tests/__init__.py +0 -3
- scitex/writer/tests/test_diff_between.py +0 -451
- scitex/writer/tests/test_document_section.py +0 -311
- scitex/writer/tests/test_document_workflow.py +0 -393
- scitex/writer/tests/test_writer.py +0 -361
- scitex/writer/tests/test_writer_integration.py +0 -303
- scitex-2.13.0.dist-info/METADATA +0 -1231
- scitex-2.13.0.dist-info/RECORD +0 -3402
- scitex-2.13.0.dist-info/entry_points.txt +0 -11
- /scitex/scholar/docs/{SUMMARY.md → 00_SUMMARY.md} +0 -0
- /scitex/scholar/docs/{STORAGE_ARCHITECTURE.md → 01_STORAGE_ARCHITECTURE.md} +0 -0
- /scitex/scholar/docs/{PIPELINE_ORGANIZATION.md → 02_PIPELINE_ORGANIZATION.md} +0 -0
- /scitex/scholar/docs/{PIPELINE_IMPLEMENTATION_PLAN.md → 03_PIPELINE_IMPLEMENTATION_PLAN.md} +0 -0
- /scitex/scholar/docs/{PIPELINE_IMPLEMENTATION_COMPLETE.md → 04_PIPELINE_IMPLEMENTATION_COMPLETE.md} +0 -0
- /scitex/scholar/docs/{DETAILS_FOR_DEVELOPERS.md → 05_DETAILS_FOR_DEVELOPERS.md} +0 -0
- /scitex/scholar/docs/{IMPACT_FACTOR_CITATION_INTEGRATION.md → 06_IMPACT_FACTOR_CITATION_INTEGRATION.md} +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/__init__.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/config/_CONSTANTS.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/config/__init__.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/contents/_RevisionContents.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/contents/_SupplementaryContents.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/contents/__init__.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/core/__init__.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/results/_SaveSectionsResponse.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/results/_SectionReadResponse.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/results/__init__.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/tree/_ConfigTree.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/tree/_ManuscriptTree.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/tree/_RevisionTree.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/tree/_ScriptsTree.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/tree/_SharedTree.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/tree/_SupplementaryTree.py +0 -0
- /scitex/writer/{dataclasses → _dataclasses}/tree/__init__.py +0 -0
- {scitex-2.13.0.dist-info → scitex-2.15.1.dist-info}/WHEEL +0 -0
- {scitex-2.13.0.dist-info → scitex-2.15.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,1763 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
# Timestamp: "2025-08-02 20:08:29 (ywatanabe)"
|
|
4
|
-
# File: /home/ywatanabe/proj/scitex_repo/src/scitex/scholar/_Scholar.py
|
|
5
|
-
# ----------------------------------------
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
import os
|
|
8
|
-
|
|
9
|
-
__FILE__ = __file__
|
|
10
|
-
__DIR__ = os.path.dirname(__FILE__)
|
|
11
|
-
# ----------------------------------------
|
|
12
|
-
|
|
13
|
-
"""
|
|
14
|
-
Unified Scholar class for scientific literature management.
|
|
15
|
-
|
|
16
|
-
This is the main entry point for all scholar functionality, providing:
|
|
17
|
-
- Simple, intuitive API
|
|
18
|
-
- Smart defaults
|
|
19
|
-
- Method chaining
|
|
20
|
-
- Progressive disclosure of advanced features
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
import asyncio
|
|
24
|
-
import re
|
|
25
|
-
from pathlib import Path
|
|
26
|
-
from typing import Any, Dict, List, Optional, Union
|
|
27
|
-
|
|
28
|
-
from scitex import logging
|
|
29
|
-
|
|
30
|
-
# PDF extraction is now handled by scitex.io
|
|
31
|
-
from scitex.errors import (
|
|
32
|
-
BibTeXEnrichmentError,
|
|
33
|
-
ConfigurationError,
|
|
34
|
-
ScholarError,
|
|
35
|
-
SciTeXWarning,
|
|
36
|
-
)
|
|
37
|
-
from ..io import load
|
|
38
|
-
from scitex.scholar.core import Paper
|
|
39
|
-
from .core._Papers import Papers
|
|
40
|
-
from scitex.scholar.config import ScholarConfig
|
|
41
|
-
from .metadata.doi._SingleDOIResolver import SingleDOIResolver
|
|
42
|
-
from .download._ScholarPDFDownloader import ScholarPDFDownloader
|
|
43
|
-
from .metadata.enrichment._MetadataEnricher import MetadataEnricher
|
|
44
|
-
|
|
45
|
-
# SmartScholarPDFDownloader removed - using ScholarPDFDownloader directly
|
|
46
|
-
from .search._UnifiedSearcher import UnifiedSearcher
|
|
47
|
-
from .utils._paths import get_scholar_dir
|
|
48
|
-
|
|
49
|
-
logger = logging.getLogger(__name__)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class Scholar:
|
|
53
|
-
"""
|
|
54
|
-
Main interface for SciTeX Scholar - scientific literature management made simple.
|
|
55
|
-
|
|
56
|
-
By default, papers are automatically enriched with:
|
|
57
|
-
- Journal impact factors from impact_factor package (2024 JCR data)
|
|
58
|
-
- Citation counts from Semantic Scholar (via DOI/title matching)
|
|
59
|
-
|
|
60
|
-
Example usage:
|
|
61
|
-
# Basic search with automatic enrichment
|
|
62
|
-
scholar = Scholar()
|
|
63
|
-
papers = scholar.search("deep learning neuroscience")
|
|
64
|
-
# Papers now have impact_factor and citation_count populated
|
|
65
|
-
papers.save("my_papers.bib")
|
|
66
|
-
|
|
67
|
-
# Disable automatic enrichment if needed
|
|
68
|
-
config = ScholarConfig(enable_auto_enrich=False)
|
|
69
|
-
scholar = Scholar(config=config)
|
|
70
|
-
|
|
71
|
-
# Search specific source
|
|
72
|
-
papers = scholar.search("transformer models", sources='arxiv')
|
|
73
|
-
|
|
74
|
-
# Advanced workflow
|
|
75
|
-
papers = scholar.search("transformer models", year_min=2020) \\
|
|
76
|
-
.filter(min_citations=50) \\
|
|
77
|
-
.sort_by("impact_factor") \\
|
|
78
|
-
.save("transformers.bib")
|
|
79
|
-
|
|
80
|
-
# Local library
|
|
81
|
-
scholar._index_local_pdfs("./my_papers")
|
|
82
|
-
local_papers = scholar.search_local("attention mechanism")
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
def __init__(
|
|
86
|
-
self,
|
|
87
|
-
config: Optional[Union[ScholarConfig, str, Path]] = None,
|
|
88
|
-
):
|
|
89
|
-
"""
|
|
90
|
-
Initialize Scholar with configuration.
|
|
91
|
-
|
|
92
|
-
Args:
|
|
93
|
-
config: Can be:
|
|
94
|
-
- ScholarConfig instance
|
|
95
|
-
- Path to YAML config file (str or Path)
|
|
96
|
-
- None (uses ScholarConfig.load() to find config)
|
|
97
|
-
"""
|
|
98
|
-
# Handle different config input types
|
|
99
|
-
if config is None:
|
|
100
|
-
self.config = ScholarConfig.load() # Auto-detect config
|
|
101
|
-
elif isinstance(config, (str, Path)):
|
|
102
|
-
self.config = ScholarConfig.from_yaml(config)
|
|
103
|
-
elif isinstance(config, ScholarConfig):
|
|
104
|
-
self.config = config
|
|
105
|
-
else:
|
|
106
|
-
raise TypeError(f"Invalid config type: {type(config)}")
|
|
107
|
-
|
|
108
|
-
# Set workspace directory using path manager
|
|
109
|
-
self.workspace_dir = self.config.path_manager.workspace_dir
|
|
110
|
-
|
|
111
|
-
# Initialize components with config system
|
|
112
|
-
self._searcher = UnifiedSearcher(config=self.config)
|
|
113
|
-
|
|
114
|
-
self._enricher = MetadataEnricher(config=self.config)
|
|
115
|
-
|
|
116
|
-
# Initialize PDF downloader
|
|
117
|
-
self._initialize_pdf_downloader()
|
|
118
|
-
|
|
119
|
-
# Initialize DOI resolver with config
|
|
120
|
-
self._doi_resolver = SingleDOIResolver(config=self.config)
|
|
121
|
-
|
|
122
|
-
logger.info(f"Scholar initialized (workspace: {self.workspace_dir})")
|
|
123
|
-
|
|
124
|
-
# Print configuration summary
|
|
125
|
-
self._print_config_summary()
|
|
126
|
-
|
|
127
|
-
def search(
|
|
128
|
-
self,
|
|
129
|
-
query: str,
|
|
130
|
-
limit: int = 100,
|
|
131
|
-
sources: Union[str, List[str]] = "pubmed",
|
|
132
|
-
year_min: Optional[int] = None,
|
|
133
|
-
year_max: Optional[int] = None,
|
|
134
|
-
**kwargs,
|
|
135
|
-
) -> Papers:
|
|
136
|
-
"""
|
|
137
|
-
Search for papers from one or more sources.
|
|
138
|
-
|
|
139
|
-
Args:
|
|
140
|
-
query: Search query
|
|
141
|
-
limit: Maximum results (default 100)
|
|
142
|
-
sources: Source(s) to search - can be a string or list of strings
|
|
143
|
-
('pubmed', 'semantic_scholar', 'google_scholar', 'arxiv')
|
|
144
|
-
year_min: Minimum publication year
|
|
145
|
-
year_max: Maximum publication year
|
|
146
|
-
search_mode: Search mode - 'strict' (all terms required) or 'flexible' (any terms)
|
|
147
|
-
**kwargs: Additional search parameters
|
|
148
|
-
|
|
149
|
-
Returns:
|
|
150
|
-
Papers with results
|
|
151
|
-
"""
|
|
152
|
-
print(f"Searching papers...")
|
|
153
|
-
print(f"Query: {query}")
|
|
154
|
-
print(f" Limit: {limit}")
|
|
155
|
-
print(f" Sources: {sources}")
|
|
156
|
-
|
|
157
|
-
if year_min:
|
|
158
|
-
print(f" Year min: {year_min}")
|
|
159
|
-
if year_max:
|
|
160
|
-
print(f" Year max: {year_max}")
|
|
161
|
-
for key, value in kwargs.items():
|
|
162
|
-
print(f" {key}: {value}")
|
|
163
|
-
|
|
164
|
-
# Ensure sources is a list
|
|
165
|
-
if isinstance(sources, str):
|
|
166
|
-
sources = [sources]
|
|
167
|
-
|
|
168
|
-
# Run async search in sync context
|
|
169
|
-
coro = self._searcher.search_async(
|
|
170
|
-
query=query,
|
|
171
|
-
sources=sources,
|
|
172
|
-
limit=limit,
|
|
173
|
-
year_min=year_min,
|
|
174
|
-
year_max=year_max,
|
|
175
|
-
**kwargs,
|
|
176
|
-
)
|
|
177
|
-
logger.debug(f"Searching with sources: {sources}")
|
|
178
|
-
papers = self._run_async(coro)
|
|
179
|
-
logger.debug(f"Search returned {len(papers)} papers")
|
|
180
|
-
|
|
181
|
-
# Create collection (deduplication is automatic)
|
|
182
|
-
# Pass source priority for intelligent deduplication
|
|
183
|
-
collection = Papers(papers, source_priority=sources)
|
|
184
|
-
|
|
185
|
-
# Log search results
|
|
186
|
-
if not papers:
|
|
187
|
-
logger.info(f"No results found for query: '{query}'")
|
|
188
|
-
# Suggest alternative sources if default source was used
|
|
189
|
-
if "semantic_scholar" in sources:
|
|
190
|
-
logger.info(
|
|
191
|
-
"Try searching with different sources or check your internet connection"
|
|
192
|
-
)
|
|
193
|
-
else:
|
|
194
|
-
logger.info(f"Found {len(papers)} papers for query: '{query}'")
|
|
195
|
-
|
|
196
|
-
# Auto-enrich if enabled
|
|
197
|
-
if self.config.resolve("enable_auto_enrich", None, True, bool) and papers:
|
|
198
|
-
logger.info("Auto-enriching papers...")
|
|
199
|
-
# Only try Semantic Scholar for citations if it was in the search sources
|
|
200
|
-
use_semantic_scholar = "semantic_scholar" in (sources or [])
|
|
201
|
-
self._enricher.enrich_all(
|
|
202
|
-
papers,
|
|
203
|
-
enrich_impact_factors=True, # Always enrich with impact factors
|
|
204
|
-
enrich_citations=True,
|
|
205
|
-
enrich_journal_metrics=True, # Always enrich with journal metrics
|
|
206
|
-
use_semantic_scholar_for_citations=use_semantic_scholar,
|
|
207
|
-
)
|
|
208
|
-
collection._enriched = True
|
|
209
|
-
|
|
210
|
-
# Auto-download if enabled
|
|
211
|
-
if self.config.resolve("enable_auto_download", None, False, bool) and papers:
|
|
212
|
-
open_access = [p for p in papers if p.pdf_url]
|
|
213
|
-
if open_access:
|
|
214
|
-
logger.info(f"Auto-downloading {len(open_access)} open-access PDFs...")
|
|
215
|
-
# Download PDFs for open access papers
|
|
216
|
-
dois = [p.doi for p in open_access if p.doi]
|
|
217
|
-
if dois:
|
|
218
|
-
self.download_pdf_asyncs(dois, show_async_progress=False)
|
|
219
|
-
|
|
220
|
-
print(f"\nFound:")
|
|
221
|
-
print(collection.to_dataframe())
|
|
222
|
-
|
|
223
|
-
return collection
|
|
224
|
-
|
|
225
|
-
def search_local(self, query: str, limit: int = 20) -> Papers:
|
|
226
|
-
"""
|
|
227
|
-
Search local PDF library.
|
|
228
|
-
|
|
229
|
-
Args:
|
|
230
|
-
query: Search query
|
|
231
|
-
limit: Maximum results
|
|
232
|
-
|
|
233
|
-
Returns:
|
|
234
|
-
Papers with local results
|
|
235
|
-
"""
|
|
236
|
-
# Use the UnifiedSearcher with 'local' source
|
|
237
|
-
papers = self._run_async(
|
|
238
|
-
self._searcher.search_async(query, sources=["local"], limit=limit)
|
|
239
|
-
)
|
|
240
|
-
return Papers(papers)
|
|
241
|
-
|
|
242
|
-
def _index_local_pdfs(
|
|
243
|
-
self, directory: Union[str, Path], recursive: bool = True
|
|
244
|
-
) -> Dict[str, Any]:
|
|
245
|
-
"""
|
|
246
|
-
Index local PDF files for searching.
|
|
247
|
-
|
|
248
|
-
Args:
|
|
249
|
-
directory: Directory containing PDFs
|
|
250
|
-
recursive: Search subdirectories
|
|
251
|
-
|
|
252
|
-
Returns:
|
|
253
|
-
Indexing statistics
|
|
254
|
-
"""
|
|
255
|
-
# Build local index using the searcher
|
|
256
|
-
return self._searcher.build_local_index([directory])
|
|
257
|
-
|
|
258
|
-
def download_pdf_asyncs(
|
|
259
|
-
self,
|
|
260
|
-
items: Union[List[str], List[Paper], Papers, str, Paper],
|
|
261
|
-
download_dir: Optional[Union[str, Path]] = None,
|
|
262
|
-
force: bool = False,
|
|
263
|
-
max_worker: int = 4,
|
|
264
|
-
show_async_progress: bool = True,
|
|
265
|
-
acknowledge_ethical_usage: Optional[bool] = None,
|
|
266
|
-
verify_auth_live: bool = True,
|
|
267
|
-
auto_authenticate_async: bool = False,
|
|
268
|
-
**kwargs,
|
|
269
|
-
) -> Dict[str, Any]:
|
|
270
|
-
"""
|
|
271
|
-
Download PDFs for DOIs or papers.
|
|
272
|
-
|
|
273
|
-
This is the main entry point for downloading PDFs. It accepts various input types
|
|
274
|
-
and delegates to the appropriate downloader.
|
|
275
|
-
|
|
276
|
-
Args:
|
|
277
|
-
items: Can be:
|
|
278
|
-
- List of DOI strings
|
|
279
|
-
- Single DOI string
|
|
280
|
-
- List of Paper objects
|
|
281
|
-
- Single Paper object
|
|
282
|
-
- Papers collection
|
|
283
|
-
download_dir: Directory to save PDFs (default: workspace_dir/pdfs)
|
|
284
|
-
force: Force re-download even if files exist
|
|
285
|
-
max_worker: Maximum concurrent downloads
|
|
286
|
-
show_async_progress: Show download progress
|
|
287
|
-
acknowledge_ethical_usage: Acknowledge ethical usage terms for Sci-Hub (default: from config)
|
|
288
|
-
verify_auth_live: If True, performs live verification of OpenAthens authentication
|
|
289
|
-
(adds ~2-3s but ensures session is valid). Default: True.
|
|
290
|
-
auto_authenticate_async: If True, automatically opens browser for authentication without prompting.
|
|
291
|
-
If False, prompts user before opening browser. Default: False.
|
|
292
|
-
**kwargs: Additional arguments passed to downloader
|
|
293
|
-
|
|
294
|
-
Returns:
|
|
295
|
-
Dictionary with download results:
|
|
296
|
-
- 'successful': Number of successful downloads
|
|
297
|
-
- 'failed': Number of failed downloads
|
|
298
|
-
- 'results': List of detailed results
|
|
299
|
-
- 'download_files': Dict mapping DOIs to file paths
|
|
300
|
-
|
|
301
|
-
Examples:
|
|
302
|
-
>>> # Download from DOIs
|
|
303
|
-
>>> scholar.download_pdf_asyncs(["10.1234/doi1", "10.5678/doi2"])
|
|
304
|
-
|
|
305
|
-
>>> # Download from Papers collection
|
|
306
|
-
>>> papers = scholar.search("deep learning")
|
|
307
|
-
>>> scholar.download_pdf_asyncs(papers)
|
|
308
|
-
|
|
309
|
-
>>> # Download single DOI
|
|
310
|
-
>>> scholar.download_pdf_asyncs("10.1234/example")
|
|
311
|
-
"""
|
|
312
|
-
# Use the integrated ScholarPDFDownloader instead of standalone SciHubDownloader
|
|
313
|
-
|
|
314
|
-
# Set default download directory
|
|
315
|
-
if download_dir is None:
|
|
316
|
-
download_dir = self.workspace_dir / "pdfs"
|
|
317
|
-
|
|
318
|
-
# Normalize input to list
|
|
319
|
-
if isinstance(items, str):
|
|
320
|
-
# Single DOI string
|
|
321
|
-
items = [items]
|
|
322
|
-
elif isinstance(items, Paper):
|
|
323
|
-
# Single Paper object
|
|
324
|
-
items = [items]
|
|
325
|
-
elif isinstance(items, Papers):
|
|
326
|
-
# Papers collection
|
|
327
|
-
items = items.papers
|
|
328
|
-
|
|
329
|
-
# Determine if we have DOIs or Papers
|
|
330
|
-
if items and isinstance(items[0], str):
|
|
331
|
-
# List of DOI strings
|
|
332
|
-
dois = items
|
|
333
|
-
else:
|
|
334
|
-
# List of Paper objects - extract DOIs
|
|
335
|
-
dois = []
|
|
336
|
-
for paper in items:
|
|
337
|
-
if paper.doi:
|
|
338
|
-
dois.append(paper)
|
|
339
|
-
else:
|
|
340
|
-
logger.warning(
|
|
341
|
-
f"Paper '{paper.title}' has no DOI, skipping download"
|
|
342
|
-
)
|
|
343
|
-
|
|
344
|
-
if not dois:
|
|
345
|
-
return {
|
|
346
|
-
"successful": 0,
|
|
347
|
-
"failed": 0,
|
|
348
|
-
"results": [],
|
|
349
|
-
"download_files": {},
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
# Update ScholarPDFDownloader settings
|
|
353
|
-
self._pdf_downloader.acknowledge_ethical_usage = acknowledge_ethical_usage
|
|
354
|
-
self._pdf_downloader.max_concurrent = max_worker
|
|
355
|
-
|
|
356
|
-
# Check OpenAthens authentication first if enabled
|
|
357
|
-
if self.config.resolve("openathens_enabled", None, True, bool):
|
|
358
|
-
logger.info("Checking OpenAthens authentication status...")
|
|
359
|
-
try:
|
|
360
|
-
# First try a quick local check
|
|
361
|
-
is_authenticate_async = self._run_async(
|
|
362
|
-
self._pdf_downloader.openathens_authenticator.is_authenticate_async(
|
|
363
|
-
verify_live=False
|
|
364
|
-
)
|
|
365
|
-
)
|
|
366
|
-
|
|
367
|
-
if is_authenticate_async:
|
|
368
|
-
logger.info("Using existing OpenAthens session")
|
|
369
|
-
else:
|
|
370
|
-
# If not authenticate_async locally, try to authenticate_async
|
|
371
|
-
# This will load cached sessions if available
|
|
372
|
-
auth_success = self.authenticate_async_openathens(force=False)
|
|
373
|
-
|
|
374
|
-
if not auth_success:
|
|
375
|
-
# Only show_async the authentication UI if we really need to authenticate_async
|
|
376
|
-
print("\n" + "=" * 60)
|
|
377
|
-
print("🔒 OpenAthens Authentication Required")
|
|
378
|
-
print("=" * 60)
|
|
379
|
-
print(
|
|
380
|
-
"\nAuthentication is required to download PDFs from your institution."
|
|
381
|
-
)
|
|
382
|
-
print("Opening browser for login...")
|
|
383
|
-
print("\n• You'll need your institutional credentials")
|
|
384
|
-
print("• You may need to complete 2FA")
|
|
385
|
-
print("\n🌐 Opening browser for authentication...")
|
|
386
|
-
|
|
387
|
-
# Now try with UI
|
|
388
|
-
auth_success = self.authenticate_async_openathens(force=False)
|
|
389
|
-
|
|
390
|
-
if auth_success:
|
|
391
|
-
print(
|
|
392
|
-
"\n✅ Authentication successful! Proceeding with downloads...\n"
|
|
393
|
-
)
|
|
394
|
-
# Continue with download after successful auth
|
|
395
|
-
else:
|
|
396
|
-
print("\n❌ Authentication failed or was cancelled.")
|
|
397
|
-
return {
|
|
398
|
-
"successful": 0,
|
|
399
|
-
"failed": len(dois),
|
|
400
|
-
"results": [
|
|
401
|
-
{
|
|
402
|
-
"doi": (
|
|
403
|
-
doi if isinstance(doi, str) else doi.doi
|
|
404
|
-
),
|
|
405
|
-
"success": False,
|
|
406
|
-
"error": "OpenAthens authentication failed",
|
|
407
|
-
"method": None,
|
|
408
|
-
}
|
|
409
|
-
for doi in dois
|
|
410
|
-
],
|
|
411
|
-
"summary": {"auth_failed": True},
|
|
412
|
-
}
|
|
413
|
-
except KeyboardInterrupt:
|
|
414
|
-
print("\n\n❌ Authentication cancelled by user.")
|
|
415
|
-
return {
|
|
416
|
-
"successful": 0,
|
|
417
|
-
"failed": len(dois),
|
|
418
|
-
"results": [
|
|
419
|
-
{
|
|
420
|
-
"doi": doi if isinstance(doi, str) else doi.doi,
|
|
421
|
-
"success": False,
|
|
422
|
-
"error": "Authentication cancelled by user",
|
|
423
|
-
"method": None,
|
|
424
|
-
}
|
|
425
|
-
for doi in dois
|
|
426
|
-
],
|
|
427
|
-
"summary": {"cancelled": True},
|
|
428
|
-
}
|
|
429
|
-
except Exception as e:
|
|
430
|
-
logger.warning(f"OpenAthens authentication check failed: {e}")
|
|
431
|
-
# Continue anyway - maybe cookies work even if check fails
|
|
432
|
-
|
|
433
|
-
# Download PDFs using the integrated downloader
|
|
434
|
-
async def download_batch_async():
|
|
435
|
-
# Extract DOIs and metadata
|
|
436
|
-
identifiers = []
|
|
437
|
-
metadata_list = []
|
|
438
|
-
|
|
439
|
-
for item in dois:
|
|
440
|
-
if isinstance(item, str):
|
|
441
|
-
identifiers.append(item)
|
|
442
|
-
metadata_list.append(None)
|
|
443
|
-
elif isinstance(item, Paper):
|
|
444
|
-
identifiers.append(item.doi)
|
|
445
|
-
metadata_list.append(
|
|
446
|
-
{
|
|
447
|
-
"title": item.title,
|
|
448
|
-
"authors": item.authors,
|
|
449
|
-
"year": item.year,
|
|
450
|
-
}
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
return await self._pdf_downloader.batch_download(
|
|
454
|
-
identifiers=identifiers,
|
|
455
|
-
output_dir=download_dir,
|
|
456
|
-
metadata_list=metadata_list,
|
|
457
|
-
show_async_progress=show_async_progress,
|
|
458
|
-
return_detailed=True, # Get method information
|
|
459
|
-
)
|
|
460
|
-
|
|
461
|
-
# Run async function
|
|
462
|
-
try:
|
|
463
|
-
import asyncio
|
|
464
|
-
|
|
465
|
-
loop = asyncio.get_event_loop()
|
|
466
|
-
if loop.is_running():
|
|
467
|
-
# If already in async context
|
|
468
|
-
import concurrent.futures
|
|
469
|
-
|
|
470
|
-
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
471
|
-
future = executor.submit(asyncio.run, download_batch_async())
|
|
472
|
-
results = future.result()
|
|
473
|
-
else:
|
|
474
|
-
results = loop.run_until_complete(download_batch_async())
|
|
475
|
-
except RuntimeError:
|
|
476
|
-
# No event loop
|
|
477
|
-
results = asyncio.run(download_batch_async())
|
|
478
|
-
|
|
479
|
-
# Create Papers instance with successfully download papers
|
|
480
|
-
download_papers = []
|
|
481
|
-
|
|
482
|
-
# Map identifiers back to papers
|
|
483
|
-
identifier_to_paper = {}
|
|
484
|
-
for item in items:
|
|
485
|
-
if isinstance(item, Paper):
|
|
486
|
-
identifier = item.doi or item.get_identifier()
|
|
487
|
-
if identifier:
|
|
488
|
-
identifier_to_paper[identifier] = item
|
|
489
|
-
|
|
490
|
-
# If we have DOI strings, we need to create Paper objects for successful downloads
|
|
491
|
-
if not identifier_to_paper:
|
|
492
|
-
# We were given DOI strings, not Paper objects
|
|
493
|
-
for identifier, result in results.items():
|
|
494
|
-
if result:
|
|
495
|
-
# Extract path and method from detailed result
|
|
496
|
-
path = result["path"]
|
|
497
|
-
method = result["method"]
|
|
498
|
-
|
|
499
|
-
# Create a minimal Paper object with the DOI and PDF path
|
|
500
|
-
paper = Paper(
|
|
501
|
-
title=f"Paper with DOI: {identifier}",
|
|
502
|
-
authors=[],
|
|
503
|
-
abstract="", # Empty abstract for DOI-only downloads
|
|
504
|
-
year=None,
|
|
505
|
-
journal=None,
|
|
506
|
-
doi=identifier,
|
|
507
|
-
)
|
|
508
|
-
paper.pdf_path = path
|
|
509
|
-
paper.pdf_source = method # Actual method used
|
|
510
|
-
download_papers.append(paper)
|
|
511
|
-
else:
|
|
512
|
-
# Collect successfully download papers from existing Paper objects
|
|
513
|
-
for identifier, result in results.items():
|
|
514
|
-
if result and identifier in identifier_to_paper:
|
|
515
|
-
# Extract path and method from detailed result
|
|
516
|
-
path = result["path"]
|
|
517
|
-
method = result["method"]
|
|
518
|
-
|
|
519
|
-
paper = identifier_to_paper[identifier]
|
|
520
|
-
paper.pdf_path = path # Update PDF path
|
|
521
|
-
paper.pdf_source = method # Actual method used
|
|
522
|
-
download_papers.append(paper)
|
|
523
|
-
|
|
524
|
-
# Create Papers instance
|
|
525
|
-
return Papers(download_papers)
|
|
526
|
-
|
|
527
|
-
def _enrich_papers(
|
|
528
|
-
self,
|
|
529
|
-
papers: Union[List[Paper], Papers],
|
|
530
|
-
impact_factors: bool = True,
|
|
531
|
-
citations: bool = True,
|
|
532
|
-
journal_metrics: bool = True,
|
|
533
|
-
) -> Union[List[Paper], Papers]:
|
|
534
|
-
"""
|
|
535
|
-
Enrich papers with all available metadata.
|
|
536
|
-
|
|
537
|
-
Args:
|
|
538
|
-
papers: Papers to enrich
|
|
539
|
-
impact_factors: Add journal impact factors
|
|
540
|
-
citations: Add citation counts
|
|
541
|
-
journal_metrics: Add quartiles, rankings
|
|
542
|
-
|
|
543
|
-
Returns:
|
|
544
|
-
Enriched papers (same type as input)
|
|
545
|
-
"""
|
|
546
|
-
if isinstance(papers, Papers):
|
|
547
|
-
self._enricher.enrich_all(
|
|
548
|
-
papers.papers,
|
|
549
|
-
enrich_impact_factors=impact_factors,
|
|
550
|
-
enrich_citations=citations,
|
|
551
|
-
enrich_journal_metrics=journal_metrics,
|
|
552
|
-
)
|
|
553
|
-
papers._enriched = True
|
|
554
|
-
return papers
|
|
555
|
-
else:
|
|
556
|
-
return self._enricher.enrich_all(
|
|
557
|
-
papers,
|
|
558
|
-
enrich_impact_factors=impact_factors,
|
|
559
|
-
enrich_citations=citations,
|
|
560
|
-
enrich_journal_metrics=journal_metrics,
|
|
561
|
-
)
|
|
562
|
-
|
|
563
|
-
def enrich_bibtex(
|
|
564
|
-
self,
|
|
565
|
-
bibtex_path: Union[str, Path],
|
|
566
|
-
output_path: Optional[Union[str, Path]] = None,
|
|
567
|
-
backup: bool = True,
|
|
568
|
-
preserve_original_fields: bool = True,
|
|
569
|
-
add_missing_abstracts: bool = True,
|
|
570
|
-
add_missing_urls: bool = True,
|
|
571
|
-
) -> Papers:
|
|
572
|
-
"""
|
|
573
|
-
Enrich an existing BibTeX file with impact factors, citations, and missing fields.
|
|
574
|
-
|
|
575
|
-
Args:
|
|
576
|
-
bibtex_path: Path to input BibTeX file
|
|
577
|
-
output_path: Path for enriched output (defaults to input path)
|
|
578
|
-
backup: Create backup of original file before overwriting
|
|
579
|
-
preserve_original_fields: Keep all original BibTeX fields
|
|
580
|
-
add_missing_abstracts: Fetch abstracts for entries without them
|
|
581
|
-
add_missing_urls: Fetch URLs for entries without them
|
|
582
|
-
|
|
583
|
-
Returns:
|
|
584
|
-
Papers with enriched papers
|
|
585
|
-
"""
|
|
586
|
-
bibtex_path = Path(bibtex_path)
|
|
587
|
-
if not bibtex_path.exists():
|
|
588
|
-
from scitex.errors import PathNotFoundError
|
|
589
|
-
|
|
590
|
-
raise PathNotFoundError(str(bibtex_path))
|
|
591
|
-
|
|
592
|
-
# Set output path
|
|
593
|
-
if output_path is None:
|
|
594
|
-
output_path = bibtex_path
|
|
595
|
-
else:
|
|
596
|
-
output_path = Path(output_path)
|
|
597
|
-
|
|
598
|
-
# Create backup if needed
|
|
599
|
-
if backup and output_path == bibtex_path:
|
|
600
|
-
backup_path = bibtex_path.with_suffix(".bib.bak")
|
|
601
|
-
import shutil
|
|
602
|
-
|
|
603
|
-
shutil.copy2(bibtex_path, backup_path)
|
|
604
|
-
logger.info(f"Created backup: {backup_path}")
|
|
605
|
-
|
|
606
|
-
# Load existing BibTeX entries
|
|
607
|
-
logger.info(f"Loading BibTeX file: {bibtex_path}")
|
|
608
|
-
try:
|
|
609
|
-
entries = load(str(bibtex_path))
|
|
610
|
-
except Exception as e:
|
|
611
|
-
raise BibTeXEnrichmentError(
|
|
612
|
-
str(bibtex_path), f"Failed to load BibTeX file: {str(e)}"
|
|
613
|
-
)
|
|
614
|
-
|
|
615
|
-
# Convert BibTeX entries to Paper objects
|
|
616
|
-
papers = []
|
|
617
|
-
original_fields_map = {}
|
|
618
|
-
|
|
619
|
-
for entry in entries:
|
|
620
|
-
paper = self._bibtex_entry_to_paper(entry)
|
|
621
|
-
if paper:
|
|
622
|
-
papers.append(paper)
|
|
623
|
-
# Store original fields for preservation
|
|
624
|
-
if preserve_original_fields:
|
|
625
|
-
original_fields_map[paper.get_identifier()] = entry["fields"]
|
|
626
|
-
|
|
627
|
-
logger.info(f"Parsed {len(papers)} papers from BibTeX file")
|
|
628
|
-
|
|
629
|
-
# Create collection
|
|
630
|
-
collection = Papers(papers)
|
|
631
|
-
|
|
632
|
-
# Enrich papers with impact factors and citations
|
|
633
|
-
if papers:
|
|
634
|
-
logger.info("Enriching papers with impact factors and citations...")
|
|
635
|
-
self._enricher.enrich_all(
|
|
636
|
-
papers,
|
|
637
|
-
enrich_impact_factors=True, # Always enrich with impact factors
|
|
638
|
-
enrich_citations=True,
|
|
639
|
-
enrich_journal_metrics=True, # Always enrich with journal metrics
|
|
640
|
-
)
|
|
641
|
-
|
|
642
|
-
# Always fetch missing DOIs, and optionally abstracts/URLs
|
|
643
|
-
logger.info(
|
|
644
|
-
"Fetching missing DOIs and other information from online sources..."
|
|
645
|
-
)
|
|
646
|
-
self._fetch_missing_fields(papers, add_missing_abstracts, add_missing_urls)
|
|
647
|
-
|
|
648
|
-
# Merge original fields if preserving
|
|
649
|
-
if preserve_original_fields:
|
|
650
|
-
for paper in papers:
|
|
651
|
-
paper_id = paper.get_identifier()
|
|
652
|
-
if paper_id in original_fields_map:
|
|
653
|
-
paper._original_bibtex_fields = original_fields_map[paper_id]
|
|
654
|
-
|
|
655
|
-
# Save enriched BibTeX
|
|
656
|
-
collection.save(str(output_path))
|
|
657
|
-
logger.info(f"Saved enriched BibTeX to: {output_path}")
|
|
658
|
-
|
|
659
|
-
return collection
|
|
660
|
-
|
|
661
|
-
def _bibtex_entry_to_paper(self, entry: Dict[str, Any]) -> Optional[Paper]:
|
|
662
|
-
"""
|
|
663
|
-
Convert a parsed BibTeX entry to a Paper object.
|
|
664
|
-
|
|
665
|
-
Args:
|
|
666
|
-
entry: Parsed BibTeX entry dictionary
|
|
667
|
-
|
|
668
|
-
Returns:
|
|
669
|
-
Paper object or None if conversion fails
|
|
670
|
-
"""
|
|
671
|
-
try:
|
|
672
|
-
fields = entry.get("fields", {})
|
|
673
|
-
|
|
674
|
-
# Extract authors
|
|
675
|
-
authors_str = fields.get("author", "")
|
|
676
|
-
authors = self._parse_authors(authors_str)
|
|
677
|
-
|
|
678
|
-
# Extract Semantic Scholar Corpus ID if URL is from api.semanticscholar.org
|
|
679
|
-
url = fields.get("url", "")
|
|
680
|
-
semantic_scholar_id = None
|
|
681
|
-
if "api.semanticscholar.org/CorpusId:" in url:
|
|
682
|
-
# Extract corpus ID from URL
|
|
683
|
-
match = re.search(r"CorpusId:(\d+)", url)
|
|
684
|
-
if match:
|
|
685
|
-
semantic_scholar_id = match.group(1)
|
|
686
|
-
|
|
687
|
-
# Create Paper object with available fields
|
|
688
|
-
paper = Paper(
|
|
689
|
-
title=fields.get("title", "").strip(),
|
|
690
|
-
authors=authors,
|
|
691
|
-
year=(
|
|
692
|
-
int(fields.get("year", 0))
|
|
693
|
-
if fields.get("year", "").isdigit()
|
|
694
|
-
else None
|
|
695
|
-
),
|
|
696
|
-
journal=fields.get("journal", fields.get("booktitle", "")),
|
|
697
|
-
doi=fields.get("doi", ""),
|
|
698
|
-
pmid=fields.get("pmid", ""),
|
|
699
|
-
arxiv_id=fields.get("arxiv", ""),
|
|
700
|
-
abstract=fields.get("abstract", ""),
|
|
701
|
-
pdf_url=fields.get("url", ""),
|
|
702
|
-
keywords=self._parse_bibtex_keywords(fields.get("keywords", "")),
|
|
703
|
-
source=f"bibtex:{entry.get('key', 'unknown')}",
|
|
704
|
-
)
|
|
705
|
-
|
|
706
|
-
# Store Semantic Scholar ID for later use
|
|
707
|
-
if semantic_scholar_id:
|
|
708
|
-
paper._semantic_scholar_corpus_id = semantic_scholar_id
|
|
709
|
-
|
|
710
|
-
# Add volume, pages if available
|
|
711
|
-
if "volume" in fields:
|
|
712
|
-
paper.volume = fields["volume"]
|
|
713
|
-
if "pages" in fields:
|
|
714
|
-
paper.pages = fields["pages"]
|
|
715
|
-
|
|
716
|
-
# Store entry type and key
|
|
717
|
-
paper._bibtex_entry_type = entry.get("entry_type", "article")
|
|
718
|
-
paper._bibtex_key = entry.get("key", "")
|
|
719
|
-
|
|
720
|
-
return paper
|
|
721
|
-
|
|
722
|
-
except Exception as e:
|
|
723
|
-
logger.warning(f"Failed to convert BibTeX entry: {e}")
|
|
724
|
-
return None
|
|
725
|
-
|
|
726
|
-
def _parse_authors(self, authors_str: str) -> List[str]:
|
|
727
|
-
"""Parse BibTeX author string into list of author names."""
|
|
728
|
-
if not authors_str:
|
|
729
|
-
return []
|
|
730
|
-
|
|
731
|
-
# Split by 'and'
|
|
732
|
-
authors = []
|
|
733
|
-
for author in authors_str.split(" and "):
|
|
734
|
-
author = author.strip()
|
|
735
|
-
if author:
|
|
736
|
-
# Handle "Last, First" format
|
|
737
|
-
if "," in author:
|
|
738
|
-
parts = author.split(",", 1)
|
|
739
|
-
author = f"{parts[1].strip()} {parts[0].strip()}"
|
|
740
|
-
authors.append(author)
|
|
741
|
-
|
|
742
|
-
return authors
|
|
743
|
-
|
|
744
|
-
def _parse_bibtex_keywords(self, keywords_str: str) -> List[str]:
|
|
745
|
-
"""Parse BibTeX keywords string into list."""
|
|
746
|
-
if not keywords_str:
|
|
747
|
-
return []
|
|
748
|
-
|
|
749
|
-
# Split by comma or semicolon
|
|
750
|
-
keywords = []
|
|
751
|
-
for kw in re.split(r"[,;]", keywords_str):
|
|
752
|
-
kw = kw.strip()
|
|
753
|
-
if kw:
|
|
754
|
-
keywords.append(kw)
|
|
755
|
-
|
|
756
|
-
return keywords
|
|
757
|
-
|
|
758
|
-
def _fetch_missing_fields(
|
|
759
|
-
self, papers: List[Paper], fetch_abstracts: bool, fetch_urls: bool
|
|
760
|
-
):
|
|
761
|
-
"""
|
|
762
|
-
Fetch missing DOIs, abstracts and URLs from online sources.
|
|
763
|
-
Uses batch processing for efficiency when handling multiple papers.
|
|
764
|
-
|
|
765
|
-
Args:
|
|
766
|
-
papers: List of Paper objects
|
|
767
|
-
fetch_abstracts: Whether to fetch missing abstracts
|
|
768
|
-
fetch_urls: Whether to fetch missing URLs
|
|
769
|
-
"""
|
|
770
|
-
papers_to_update = []
|
|
771
|
-
|
|
772
|
-
for paper in papers:
|
|
773
|
-
needs_update = False
|
|
774
|
-
|
|
775
|
-
# Always try to get DOI if missing
|
|
776
|
-
if not paper.doi:
|
|
777
|
-
needs_update = True
|
|
778
|
-
if fetch_abstracts and not paper.abstract:
|
|
779
|
-
needs_update = True
|
|
780
|
-
if fetch_urls and not paper.pdf_url:
|
|
781
|
-
needs_update = True
|
|
782
|
-
|
|
783
|
-
if needs_update:
|
|
784
|
-
papers_to_update.append(paper)
|
|
785
|
-
|
|
786
|
-
if not papers_to_update:
|
|
787
|
-
return
|
|
788
|
-
|
|
789
|
-
logger.info(f"Fetching missing fields for {len(papers_to_update)} papers...")
|
|
790
|
-
|
|
791
|
-
# Use batch processing for efficiency
|
|
792
|
-
if len(papers_to_update) > 1:
|
|
793
|
-
logger.info("Using batch processing for efficient DOI resolution...")
|
|
794
|
-
|
|
795
|
-
# Extract titles and years for batch resolution
|
|
796
|
-
titles = []
|
|
797
|
-
years = []
|
|
798
|
-
for paper in papers_to_update:
|
|
799
|
-
if not paper.doi: # Only resolve if DOI is missing
|
|
800
|
-
titles.append(paper.title)
|
|
801
|
-
years.append(paper.year)
|
|
802
|
-
|
|
803
|
-
# Batch resolve DOIs
|
|
804
|
-
if titles:
|
|
805
|
-
doi_results = self._doi_resolver.batch_resolve(
|
|
806
|
-
titles=titles, years=years, show_async_progress=True
|
|
807
|
-
)
|
|
808
|
-
|
|
809
|
-
# Update papers with resolved DOIs
|
|
810
|
-
for paper in papers_to_update:
|
|
811
|
-
if not paper.doi and paper.title in doi_results:
|
|
812
|
-
resolved_doi = doi_results[paper.title]
|
|
813
|
-
if resolved_doi:
|
|
814
|
-
paper.doi = resolved_doi
|
|
815
|
-
logger.info(
|
|
816
|
-
f" ✓ Found DOI for: {paper.title[:50]}... -> {resolved_doi}"
|
|
817
|
-
)
|
|
818
|
-
|
|
819
|
-
# Update URLs if needed
|
|
820
|
-
for paper in papers_to_update:
|
|
821
|
-
if (
|
|
822
|
-
paper.doi
|
|
823
|
-
and fetch_urls
|
|
824
|
-
and "api.semanticscholar.org" in (paper.pdf_url or "")
|
|
825
|
-
):
|
|
826
|
-
paper.pdf_url = f"https://doi.org/{paper.doi}"
|
|
827
|
-
logger.info(
|
|
828
|
-
f" ✓ Updated URL to DOI link for: {paper.title[:50]}..."
|
|
829
|
-
)
|
|
830
|
-
|
|
831
|
-
# Fetch abstracts if needed
|
|
832
|
-
if paper.doi and fetch_abstracts and not paper.abstract:
|
|
833
|
-
abstract = self._doi_resolver.get_abstract(paper.doi)
|
|
834
|
-
if abstract:
|
|
835
|
-
paper.abstract = abstract
|
|
836
|
-
logger.info(f" ✓ Found abstract for: {paper.title[:50]}...")
|
|
837
|
-
|
|
838
|
-
else:
|
|
839
|
-
# Single paper - use regular resolver
|
|
840
|
-
paper = papers_to_update[0]
|
|
841
|
-
logger.debug(f"Processing single paper: {paper.title[:50]}...")
|
|
842
|
-
|
|
843
|
-
# Try to get DOI
|
|
844
|
-
if not paper.doi:
|
|
845
|
-
# First try URL resolution if available
|
|
846
|
-
if paper.pdf_url:
|
|
847
|
-
doi = self._doi_resolver.resolve_from_url(paper.pdf_url)
|
|
848
|
-
if doi:
|
|
849
|
-
paper.doi = doi
|
|
850
|
-
logger.info(f" ✓ Found DOI from URL: {doi}")
|
|
851
|
-
|
|
852
|
-
# If still no DOI, try title-based search
|
|
853
|
-
if not paper.doi:
|
|
854
|
-
authors_tuple = tuple(paper.authors) if paper.authors else None
|
|
855
|
-
|
|
856
|
-
doi = self._doi_resolver.resolve(
|
|
857
|
-
title=paper.title,
|
|
858
|
-
year=paper.year,
|
|
859
|
-
authors=authors_tuple,
|
|
860
|
-
)
|
|
861
|
-
|
|
862
|
-
if doi:
|
|
863
|
-
paper.doi = doi
|
|
864
|
-
logger.info(f" ✓ Found DOI from title: {doi}")
|
|
865
|
-
|
|
866
|
-
# Update URL if needed
|
|
867
|
-
if (
|
|
868
|
-
paper.doi
|
|
869
|
-
and fetch_urls
|
|
870
|
-
and "api.semanticscholar.org" in (paper.pdf_url or "")
|
|
871
|
-
):
|
|
872
|
-
paper.pdf_url = f"https://doi.org/{paper.doi}"
|
|
873
|
-
logger.info(f" ✓ Updated URL to DOI link")
|
|
874
|
-
|
|
875
|
-
# Get abstract if needed
|
|
876
|
-
if paper.doi and fetch_abstracts and not paper.abstract:
|
|
877
|
-
abstract = self._doi_resolver.get_abstract(paper.doi)
|
|
878
|
-
if abstract:
|
|
879
|
-
paper.abstract = abstract
|
|
880
|
-
logger.info(f" ✓ Found abstract")
|
|
881
|
-
|
|
882
|
-
def resolve_doi_async(
|
|
883
|
-
self,
|
|
884
|
-
title: str,
|
|
885
|
-
year: Optional[int] = None,
|
|
886
|
-
authors: Optional[List[str]] = None,
|
|
887
|
-
) -> Optional[str]:
|
|
888
|
-
"""
|
|
889
|
-
Resolve DOI from paper title using multiple sources.
|
|
890
|
-
|
|
891
|
-
This method uses CrossRef, PubMed, and OpenAlex to find DOIs,
|
|
892
|
-
avoiding rate-limited services like Semantic Scholar.
|
|
893
|
-
|
|
894
|
-
Args:
|
|
895
|
-
title: Paper title
|
|
896
|
-
year: Publication year (optional but improves accuracy)
|
|
897
|
-
authors: List of author names (optional but improves accuracy)
|
|
898
|
-
|
|
899
|
-
Returns:
|
|
900
|
-
DOI string if found, None otherwise
|
|
901
|
-
|
|
902
|
-
Example:
|
|
903
|
-
doi = scholar.resolve_doi_async(
|
|
904
|
-
"The functional role of cross-frequency coupling",
|
|
905
|
-
year=2010
|
|
906
|
-
)
|
|
907
|
-
# Returns: "10.1016/j.tins.2010.09.001"
|
|
908
|
-
"""
|
|
909
|
-
# Convert authors to tuple for caching if provided
|
|
910
|
-
authors_tuple = tuple(authors) if authors else None
|
|
911
|
-
return self._doi_resolver.resolve(title, year, authors_tuple)
|
|
912
|
-
|
|
913
|
-
def _search_crossref_by_title(
|
|
914
|
-
self, title: str, authors: List[str] = None
|
|
915
|
-
) -> List[Dict[str, Any]]:
|
|
916
|
-
"""
|
|
917
|
-
Search CrossRef API by title to find DOI.
|
|
918
|
-
|
|
919
|
-
Args:
|
|
920
|
-
title: Paper title
|
|
921
|
-
authors: List of author names (optional)
|
|
922
|
-
|
|
923
|
-
Returns:
|
|
924
|
-
List of matching papers from CrossRef
|
|
925
|
-
"""
|
|
926
|
-
try:
|
|
927
|
-
from urllib.parse import quote
|
|
928
|
-
|
|
929
|
-
import requests
|
|
930
|
-
|
|
931
|
-
# Build query
|
|
932
|
-
query = quote(title)
|
|
933
|
-
|
|
934
|
-
# Add author to query if available
|
|
935
|
-
if authors and len(authors) > 0:
|
|
936
|
-
first_author = authors[0]
|
|
937
|
-
# Extract last name
|
|
938
|
-
last_name = first_author.split()[-1] if first_author else ""
|
|
939
|
-
if last_name:
|
|
940
|
-
query += f"+{quote(last_name)}"
|
|
941
|
-
|
|
942
|
-
# CrossRef API URL
|
|
943
|
-
url = f"https://api.crossref.org/works"
|
|
944
|
-
params = {
|
|
945
|
-
"query": title, # Use unquoted title for query parameter
|
|
946
|
-
"rows": 5,
|
|
947
|
-
"select": "DOI,title,author,abstract,published-print,type",
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
# Add email if configured for polite access
|
|
951
|
-
if self._email_crossref:
|
|
952
|
-
params["mailto"] = self._email_crossref
|
|
953
|
-
|
|
954
|
-
response = requests.get(url, params=params, timeout=10)
|
|
955
|
-
|
|
956
|
-
if response.status_code == 200:
|
|
957
|
-
data = response.json()
|
|
958
|
-
items = data.get("message", {}).get("items", [])
|
|
959
|
-
|
|
960
|
-
# Filter results by title similarity
|
|
961
|
-
results = []
|
|
962
|
-
for item in items:
|
|
963
|
-
crossref_title = item.get("title", [""])[0]
|
|
964
|
-
# Simple similarity check
|
|
965
|
-
if (
|
|
966
|
-
crossref_title
|
|
967
|
-
and self._title_similarity(title, crossref_title) > 0.8
|
|
968
|
-
):
|
|
969
|
-
results.append(item)
|
|
970
|
-
|
|
971
|
-
return results
|
|
972
|
-
else:
|
|
973
|
-
logger.debug(f"CrossRef API returned {response.status_code}")
|
|
974
|
-
return []
|
|
975
|
-
|
|
976
|
-
except Exception as e:
|
|
977
|
-
logger.debug(f"CrossRef search error: {e}")
|
|
978
|
-
return []
|
|
979
|
-
|
|
980
|
-
def _title_similarity(self, title1: str, title2: str) -> float:
|
|
981
|
-
"""
|
|
982
|
-
Calculate similarity between two titles (simple approach).
|
|
983
|
-
|
|
984
|
-
Args:
|
|
985
|
-
title1: First title
|
|
986
|
-
title2: Second title
|
|
987
|
-
|
|
988
|
-
Returns:
|
|
989
|
-
Similarity score between 0 and 1
|
|
990
|
-
"""
|
|
991
|
-
# Normalize titles
|
|
992
|
-
t1 = title1.lower().strip()
|
|
993
|
-
t2 = title2.lower().strip()
|
|
994
|
-
|
|
995
|
-
# Remove punctuation
|
|
996
|
-
import string
|
|
997
|
-
|
|
998
|
-
translator = str.maketrans("", "", string.punctuation)
|
|
999
|
-
t1 = t1.translate(translator)
|
|
1000
|
-
t2 = t2.translate(translator)
|
|
1001
|
-
|
|
1002
|
-
# Split into words
|
|
1003
|
-
words1 = set(t1.split())
|
|
1004
|
-
words2 = set(t2.split())
|
|
1005
|
-
|
|
1006
|
-
# Calculate Jaccard similarity
|
|
1007
|
-
if not words1 or not words2:
|
|
1008
|
-
return 0.0
|
|
1009
|
-
|
|
1010
|
-
intersection = len(words1 & words2)
|
|
1011
|
-
union = len(words1 | words2)
|
|
1012
|
-
|
|
1013
|
-
return intersection / union if union > 0 else 0.0
|
|
1014
|
-
|
|
1015
|
-
def configure_openathens(
|
|
1016
|
-
self, email: Optional[str] = None, save_to_env: bool = False
|
|
1017
|
-
):
|
|
1018
|
-
"""
|
|
1019
|
-
Configure OpenAthens authentication.
|
|
1020
|
-
|
|
1021
|
-
Args:
|
|
1022
|
-
email: Institutional email address (e.g., 'user@institution.edu')
|
|
1023
|
-
save_to_env: Save configuration to environment variables
|
|
1024
|
-
|
|
1025
|
-
Note:
|
|
1026
|
-
Uses the unified MyAthens interface. Authentication is done
|
|
1027
|
-
manually in the browser when you call authenticate_async_openathens().
|
|
1028
|
-
"""
|
|
1029
|
-
import getpass
|
|
1030
|
-
|
|
1031
|
-
# Update configuration
|
|
1032
|
-
# OpenAthens is enabled via config resolution
|
|
1033
|
-
if email:
|
|
1034
|
-
# OpenAthens email is configured via config resolution
|
|
1035
|
-
pass
|
|
1036
|
-
|
|
1037
|
-
# Save to environment if requested
|
|
1038
|
-
if save_to_env:
|
|
1039
|
-
import os
|
|
1040
|
-
|
|
1041
|
-
os.environ["SCITEX_SCHOLAR_OPENATHENS_ENABLED"] = "true"
|
|
1042
|
-
if email:
|
|
1043
|
-
os.environ["SCITEX_SCHOLAR_OPENATHENS_EMAIL"] = email
|
|
1044
|
-
|
|
1045
|
-
# Reinitialize PDF downloader with OpenAthens
|
|
1046
|
-
openathens_config = {
|
|
1047
|
-
"email": self.config.resolve("openathens_email", None, None, str),
|
|
1048
|
-
"debug_mode": self.config.resolve("debug_mode", None, False, bool),
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
# Update to use ScholarPDFDownloader with new configuration
|
|
1052
|
-
self._pdf_downloader = ScholarPDFDownloader(
|
|
1053
|
-
download_dir=(
|
|
1054
|
-
Path(self.config.resolve("pdf_dir", None, None, str)).expanduser()
|
|
1055
|
-
if self.config.resolve("pdf_dir", None, None, str)
|
|
1056
|
-
else None
|
|
1057
|
-
),
|
|
1058
|
-
use_translators=True,
|
|
1059
|
-
use_playwright=True,
|
|
1060
|
-
use_openathens=True, # OpenAthens is now configured
|
|
1061
|
-
openathens_config=openathens_config,
|
|
1062
|
-
use_lean_library=self.config.resolve("use_lean_library", None, True, bool),
|
|
1063
|
-
timeout=30,
|
|
1064
|
-
max_retries=3,
|
|
1065
|
-
max_concurrent=self.config.resolve("max_parallel_requests", None, 3, int),
|
|
1066
|
-
debug_mode=self.config.resolve("debug_mode", None, False, bool),
|
|
1067
|
-
)
|
|
1068
|
-
|
|
1069
|
-
logger.info("OpenAthens configured")
|
|
1070
|
-
|
|
1071
|
-
def authenticate_async_openathens(self, force: bool = False) -> bool:
|
|
1072
|
-
"""
|
|
1073
|
-
Manually trigger OpenAthens authentication (sync version).
|
|
1074
|
-
|
|
1075
|
-
Args:
|
|
1076
|
-
force: Force re-authentication even if session exists
|
|
1077
|
-
|
|
1078
|
-
Returns:
|
|
1079
|
-
True if authentication successful
|
|
1080
|
-
"""
|
|
1081
|
-
return self._run_async(self.authenticate_async_openathens_async(force))
|
|
1082
|
-
|
|
1083
|
-
async def authenticate_async_openathens_async(self, force: bool = False) -> bool:
|
|
1084
|
-
"""
|
|
1085
|
-
Manually trigger OpenAthens authentication (async version).
|
|
1086
|
-
|
|
1087
|
-
Args:
|
|
1088
|
-
force: Force re-authentication even if session exists
|
|
1089
|
-
|
|
1090
|
-
Returns:
|
|
1091
|
-
True if authentication successful
|
|
1092
|
-
"""
|
|
1093
|
-
if not self.config.resolve("openathens_enabled", None, True, bool):
|
|
1094
|
-
raise ScholarError(
|
|
1095
|
-
"OpenAthens not configured. Call configure_openathens() first."
|
|
1096
|
-
)
|
|
1097
|
-
|
|
1098
|
-
if not self._pdf_downloader.openathens_authenticator:
|
|
1099
|
-
raise ScholarError("OpenAthens authenticator not initialized")
|
|
1100
|
-
|
|
1101
|
-
return await self._pdf_downloader.openathens_authenticator.authenticate_async(
|
|
1102
|
-
force=force
|
|
1103
|
-
)
|
|
1104
|
-
|
|
1105
|
-
def is_openathens_authenticate_async(self) -> bool:
|
|
1106
|
-
"""
|
|
1107
|
-
Check if OpenAthens is authenticate_async (sync version).
|
|
1108
|
-
|
|
1109
|
-
Returns:
|
|
1110
|
-
True if authenticate_async and session is valid
|
|
1111
|
-
"""
|
|
1112
|
-
return self._run_async(self.is_openathens_authenticate_async_async())
|
|
1113
|
-
|
|
1114
|
-
async def is_openathens_authenticate_async_async(self) -> bool:
|
|
1115
|
-
"""
|
|
1116
|
-
Check if OpenAthens is authenticate_async (async version).
|
|
1117
|
-
|
|
1118
|
-
Returns:
|
|
1119
|
-
True if authenticate_async and session is valid
|
|
1120
|
-
"""
|
|
1121
|
-
if not self.config.resolve("openathens_enabled", None, True, bool):
|
|
1122
|
-
return False
|
|
1123
|
-
|
|
1124
|
-
if not self._pdf_downloader.openathens_authenticator:
|
|
1125
|
-
return False
|
|
1126
|
-
|
|
1127
|
-
return await self._pdf_downloader.openathens_authenticator.is_authenticate_async_async()
|
|
1128
|
-
|
|
1129
|
-
def ensure_authenticate_async(self, force: bool = False) -> bool:
|
|
1130
|
-
"""
|
|
1131
|
-
Ensure OpenAthens is authenticate_async, opening browser if needed.
|
|
1132
|
-
|
|
1133
|
-
This is a convenience method that:
|
|
1134
|
-
1. Checks if already authenticate_async
|
|
1135
|
-
2. If not, automatically opens browser for authentication
|
|
1136
|
-
3. Returns True if authenticate_async (either already or after login)
|
|
1137
|
-
|
|
1138
|
-
Args:
|
|
1139
|
-
force: Force re-authentication even if already logged in
|
|
1140
|
-
|
|
1141
|
-
Returns:
|
|
1142
|
-
True if authenticate_async successfully
|
|
1143
|
-
|
|
1144
|
-
Example:
|
|
1145
|
-
>>> scholar = Scholar(openathens_enabled=True)
|
|
1146
|
-
>>> if scholar.ensure_authenticate_async():
|
|
1147
|
-
... papers = scholar.search("quantum")
|
|
1148
|
-
... scholar.download_pdf_asyncs(papers)
|
|
1149
|
-
"""
|
|
1150
|
-
if not self.config.resolve("openathens_enabled", None, True, bool):
|
|
1151
|
-
return True # No auth needed
|
|
1152
|
-
|
|
1153
|
-
# Check current status
|
|
1154
|
-
if not force and self.is_openathens_authenticate_async():
|
|
1155
|
-
logger.info("Already authenticate_async with OpenAthens")
|
|
1156
|
-
return True
|
|
1157
|
-
|
|
1158
|
-
# Need to authenticate_async
|
|
1159
|
-
print("\n" + "=" * 60)
|
|
1160
|
-
print("🔐 OpenAthens Authentication Required")
|
|
1161
|
-
print("=" * 60)
|
|
1162
|
-
print("\nOpening browser for authentication...")
|
|
1163
|
-
print("Please log in with your institutional credentials.\n")
|
|
1164
|
-
|
|
1165
|
-
# Authenticate
|
|
1166
|
-
success = self.authenticate_async_openathens(force=force)
|
|
1167
|
-
|
|
1168
|
-
if success:
|
|
1169
|
-
print("\n✅ Authentication successful!")
|
|
1170
|
-
else:
|
|
1171
|
-
print("\n❌ Authentication failed!")
|
|
1172
|
-
|
|
1173
|
-
return success
|
|
1174
|
-
|
|
1175
|
-
def get_library_stats(self) -> Dict[str, Any]:
|
|
1176
|
-
"""Get statistics about local PDF library."""
|
|
1177
|
-
# Get stats from the local search engine
|
|
1178
|
-
pdf_dir = self.workspace_dir / "pdfs"
|
|
1179
|
-
if not pdf_dir.exists():
|
|
1180
|
-
return {"total_pdfs": 0, "indexed": 0}
|
|
1181
|
-
|
|
1182
|
-
# Count PDF files
|
|
1183
|
-
pdf_files = list(pdf_dir.rglob("*.pdf"))
|
|
1184
|
-
return {
|
|
1185
|
-
"total_pdfs": len(pdf_files),
|
|
1186
|
-
"pdf_directory": str(pdf_dir),
|
|
1187
|
-
"indexed": len(pdf_files), # Assume all PDFs are indexed
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
def search_quick(self, query: str, top_n: int = 5) -> List[str]:
|
|
1191
|
-
"""
|
|
1192
|
-
Quick search returning just paper titles.
|
|
1193
|
-
|
|
1194
|
-
Args:
|
|
1195
|
-
query: Search query
|
|
1196
|
-
top_n: Number of results
|
|
1197
|
-
|
|
1198
|
-
Returns:
|
|
1199
|
-
List of paper titles
|
|
1200
|
-
"""
|
|
1201
|
-
papers = self.search(query, limit=top_n)
|
|
1202
|
-
return [p.title for p in papers]
|
|
1203
|
-
|
|
1204
|
-
def find_similar(self, paper_title: str, limit: int = 10) -> Papers:
|
|
1205
|
-
"""
|
|
1206
|
-
Find papers similar to a given paper.
|
|
1207
|
-
|
|
1208
|
-
Args:
|
|
1209
|
-
paper_title: Title of reference paper
|
|
1210
|
-
limit: Number of similar papers
|
|
1211
|
-
|
|
1212
|
-
Returns:
|
|
1213
|
-
Papers with similar papers
|
|
1214
|
-
"""
|
|
1215
|
-
# First find the paper
|
|
1216
|
-
reference = self.search(paper_title, limit=1)
|
|
1217
|
-
if not reference:
|
|
1218
|
-
logger.warning(f"Could not find paper: {paper_title}")
|
|
1219
|
-
return Papers([])
|
|
1220
|
-
|
|
1221
|
-
# Search for similar topics
|
|
1222
|
-
ref_paper = reference[0]
|
|
1223
|
-
|
|
1224
|
-
# Build query from title and keywords
|
|
1225
|
-
query_parts = [ref_paper.title]
|
|
1226
|
-
if ref_paper.keywords:
|
|
1227
|
-
query_parts.extend(ref_paper.keywords[:3])
|
|
1228
|
-
|
|
1229
|
-
query = " ".join(query_parts)
|
|
1230
|
-
|
|
1231
|
-
# Search and filter out the reference paper
|
|
1232
|
-
similar = self.search(query, limit=limit + 1)
|
|
1233
|
-
similar_papers = [
|
|
1234
|
-
p
|
|
1235
|
-
for p in similar.papers
|
|
1236
|
-
if p.get_identifier() != ref_paper.get_identifier()
|
|
1237
|
-
]
|
|
1238
|
-
|
|
1239
|
-
return Papers(similar_papers[:limit])
|
|
1240
|
-
|
|
1241
|
-
def _extract_text(self, pdf_path: Union[str, Path]) -> str:
|
|
1242
|
-
"""
|
|
1243
|
-
Extract text from PDF file for downstream AI processing.
|
|
1244
|
-
|
|
1245
|
-
Args:
|
|
1246
|
-
pdf_path: Path to PDF file
|
|
1247
|
-
|
|
1248
|
-
Returns:
|
|
1249
|
-
Extracted text as string
|
|
1250
|
-
"""
|
|
1251
|
-
# Use scitex.io for PDF text extraction
|
|
1252
|
-
from ..io import load
|
|
1253
|
-
|
|
1254
|
-
return load(str(pdf_path), mode="text")
|
|
1255
|
-
|
|
1256
|
-
def _extract_sections(self, pdf_path: Union[str, Path]) -> Dict[str, str]:
|
|
1257
|
-
"""
|
|
1258
|
-
Extract text organized by sections.
|
|
1259
|
-
|
|
1260
|
-
Args:
|
|
1261
|
-
pdf_path: Path to PDF file
|
|
1262
|
-
|
|
1263
|
-
Returns:
|
|
1264
|
-
Dictionary mapping section names to text
|
|
1265
|
-
"""
|
|
1266
|
-
# Use scitex.io for section extraction
|
|
1267
|
-
from ..io import load
|
|
1268
|
-
|
|
1269
|
-
return load(str(pdf_path), mode="sections")
|
|
1270
|
-
|
|
1271
|
-
def _extract_for_ai(self, pdf_path: Union[str, Path]) -> Dict[str, Any]:
|
|
1272
|
-
"""
|
|
1273
|
-
Extract comprehensive data from PDF for AI processing.
|
|
1274
|
-
|
|
1275
|
-
Args:
|
|
1276
|
-
pdf_path: Path to PDF file
|
|
1277
|
-
|
|
1278
|
-
Returns:
|
|
1279
|
-
Dictionary with:
|
|
1280
|
-
- full_text: Complete text
|
|
1281
|
-
- sections: Text by section
|
|
1282
|
-
- metadata: PDF metadata
|
|
1283
|
-
- stats: Word count, page count, etc.
|
|
1284
|
-
"""
|
|
1285
|
-
# Use scitex.io for comprehensive extraction
|
|
1286
|
-
from ..io import load
|
|
1287
|
-
|
|
1288
|
-
return load(str(pdf_path), mode="full")
|
|
1289
|
-
|
|
1290
|
-
def extract_text_from_papers(
|
|
1291
|
-
self, papers: Union[List[Paper], Papers]
|
|
1292
|
-
) -> List[Dict[str, Any]]:
|
|
1293
|
-
"""
|
|
1294
|
-
Extract text from multiple papers for AI processing.
|
|
1295
|
-
|
|
1296
|
-
Args:
|
|
1297
|
-
papers: Papers to extract text from
|
|
1298
|
-
|
|
1299
|
-
Returns:
|
|
1300
|
-
List of extraction results with paper metadata
|
|
1301
|
-
"""
|
|
1302
|
-
if isinstance(papers, Papers):
|
|
1303
|
-
papers = papers.papers
|
|
1304
|
-
|
|
1305
|
-
results = []
|
|
1306
|
-
for paper in papers:
|
|
1307
|
-
if paper.pdf_path and paper.pdf_path.exists():
|
|
1308
|
-
extraction = self._extract_for_ai(paper.pdf_path)
|
|
1309
|
-
extraction["paper"] = {
|
|
1310
|
-
"title": paper.title,
|
|
1311
|
-
"authors": paper.authors,
|
|
1312
|
-
"year": paper.year,
|
|
1313
|
-
"doi": paper.doi,
|
|
1314
|
-
"journal": paper.journal,
|
|
1315
|
-
}
|
|
1316
|
-
results.append(extraction)
|
|
1317
|
-
else:
|
|
1318
|
-
# Include paper even without PDF
|
|
1319
|
-
results.append(
|
|
1320
|
-
{
|
|
1321
|
-
"paper": {
|
|
1322
|
-
"title": paper.title,
|
|
1323
|
-
"authors": paper.authors,
|
|
1324
|
-
"year": paper.year,
|
|
1325
|
-
"doi": paper.doi,
|
|
1326
|
-
"journal": paper.journal,
|
|
1327
|
-
},
|
|
1328
|
-
"full_text": paper.abstract or "",
|
|
1329
|
-
"error": "No PDF available",
|
|
1330
|
-
}
|
|
1331
|
-
)
|
|
1332
|
-
|
|
1333
|
-
return results
|
|
1334
|
-
|
|
1335
|
-
def _initialize_pdf_downloader(self):
|
|
1336
|
-
"""Initialize or reinitialize the PDF downloader with current configuration."""
|
|
1337
|
-
# Prepare OpenAthens config if enabled
|
|
1338
|
-
openathens_config = None
|
|
1339
|
-
if self.config.resolve("openathens_enabled", None, True, bool):
|
|
1340
|
-
openathens_config = {
|
|
1341
|
-
"email": self.config.resolve("openathens_email", None, None, str),
|
|
1342
|
-
"debug_mode": self.config.resolve("debug_mode", None, False, bool),
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
|
-
# Initialize ScholarPDFDownloader with config
|
|
1346
|
-
self._pdf_downloader = ScholarPDFDownloader(
|
|
1347
|
-
download_dir=(
|
|
1348
|
-
Path(self.config.resolve("pdf_dir", None, None, str)).expanduser()
|
|
1349
|
-
if self.config.resolve("pdf_dir", None, None, str)
|
|
1350
|
-
else None
|
|
1351
|
-
),
|
|
1352
|
-
use_translators=True,
|
|
1353
|
-
use_playwright=True,
|
|
1354
|
-
use_openathens=self.config.resolve("openathens_enabled", None, True, bool),
|
|
1355
|
-
openathens_config=openathens_config,
|
|
1356
|
-
use_lean_library=self.config.resolve("use_lean_library", None, True, bool),
|
|
1357
|
-
zenrows_api_key=self.config.resolve(
|
|
1358
|
-
"zenrows_api_key", None, None, str
|
|
1359
|
-
), # Auto-enables if present
|
|
1360
|
-
timeout=30,
|
|
1361
|
-
max_retries=3,
|
|
1362
|
-
max_concurrent=self.config.resolve("max_parallel_requests", None, 3, int),
|
|
1363
|
-
debug_mode=self.config.resolve("debug_mode", None, False, bool),
|
|
1364
|
-
)
|
|
1365
|
-
|
|
1366
|
-
# Pass config to downloader for EZProxy support
|
|
1367
|
-
self._pdf_downloader.config = self.config
|
|
1368
|
-
|
|
1369
|
-
def _print_config_summary(self):
|
|
1370
|
-
"""Print configuration summary on initialization."""
|
|
1371
|
-
print("\n" + "=" * 60)
|
|
1372
|
-
print("SciTeX Scholar - Configuration Summary")
|
|
1373
|
-
print("=" * 60)
|
|
1374
|
-
|
|
1375
|
-
# Helper function to mask sensitive data
|
|
1376
|
-
def mask_sensitive(value, show_async_first=4):
|
|
1377
|
-
"""Mask sensitive data show_asyncing only first few characters."""
|
|
1378
|
-
if not value:
|
|
1379
|
-
return None
|
|
1380
|
-
if len(str(value)) > show_async_first + 3:
|
|
1381
|
-
return f"{str(value)[:show_async_first]}{'*' * (len(str(value)) - show_async_first)}"
|
|
1382
|
-
else:
|
|
1383
|
-
return "*" * len(str(value))
|
|
1384
|
-
|
|
1385
|
-
# API Keys status
|
|
1386
|
-
print("\n📚 API Keys:")
|
|
1387
|
-
|
|
1388
|
-
# Semantic Scholar API
|
|
1389
|
-
semantic_key = self.config.resolve("semantic_scholar_api_key", None, None, str)
|
|
1390
|
-
if semantic_key:
|
|
1391
|
-
masked_key = mask_sensitive(semantic_key)
|
|
1392
|
-
print(f" • Semantic Scholar: ✓ Configured ({masked_key})")
|
|
1393
|
-
else:
|
|
1394
|
-
print(" • Semantic Scholar: ✗ Not set (citations via CrossRef only)")
|
|
1395
|
-
|
|
1396
|
-
# CrossRef API
|
|
1397
|
-
crossref_key = self.config.resolve("crossref_api_key", None, None, str)
|
|
1398
|
-
if crossref_key:
|
|
1399
|
-
masked_key = mask_sensitive(crossref_key)
|
|
1400
|
-
print(f" • CrossRef: ✓ Configured ({masked_key})")
|
|
1401
|
-
else:
|
|
1402
|
-
print(" • CrossRef: ✗ Not set (works without key)")
|
|
1403
|
-
|
|
1404
|
-
# PubMed Email
|
|
1405
|
-
pubmed_email = self.config.resolve("pubmed_email", None, None, str)
|
|
1406
|
-
if pubmed_email:
|
|
1407
|
-
# Mask email but show_async domain
|
|
1408
|
-
parts = pubmed_email.split("@")
|
|
1409
|
-
if len(parts) == 2:
|
|
1410
|
-
masked_email = f"{mask_sensitive(parts[0], 2)}@{parts[1]}"
|
|
1411
|
-
else:
|
|
1412
|
-
masked_email = mask_sensitive(pubmed_email)
|
|
1413
|
-
print(f" • PubMed Email: ✓ Set ({masked_email})")
|
|
1414
|
-
else:
|
|
1415
|
-
print(" • PubMed Email: ✗ Not set (required for PubMed)")
|
|
1416
|
-
|
|
1417
|
-
# Features
|
|
1418
|
-
print("\n⚙️ Features:")
|
|
1419
|
-
|
|
1420
|
-
# Auto-enrichment
|
|
1421
|
-
auto_enrich = self.config.resolve("enable_auto_enrich", None, True, bool)
|
|
1422
|
-
print(f" • Auto-enrichment: {'✓ Enabled' if auto_enrich else '✗ Disabled'}")
|
|
1423
|
-
|
|
1424
|
-
print(" • Impact factors: ✓ Using JCR package (2024 data)")
|
|
1425
|
-
|
|
1426
|
-
# Auto-download
|
|
1427
|
-
auto_download = self.config.resolve("enable_auto_download", None, False, bool)
|
|
1428
|
-
print(
|
|
1429
|
-
f" • Auto-download PDFs: {'✓ Enabled' if auto_download else '✗ Disabled'}"
|
|
1430
|
-
)
|
|
1431
|
-
|
|
1432
|
-
# OpenAthens status
|
|
1433
|
-
openathens_enabled = self.config.resolve("openathens_enabled", None, True, bool)
|
|
1434
|
-
if openathens_enabled:
|
|
1435
|
-
openathens_email = self.config.resolve("openathens_email", None, None, str)
|
|
1436
|
-
if openathens_email:
|
|
1437
|
-
# Mask email but show_async domain
|
|
1438
|
-
parts = openathens_email.split("@")
|
|
1439
|
-
if len(parts) == 2:
|
|
1440
|
-
masked_email = f"{mask_sensitive(parts[0], 2)}@{parts[1]}"
|
|
1441
|
-
print(f" • OpenAthens: ✓ Enabled ({masked_email})")
|
|
1442
|
-
else:
|
|
1443
|
-
print(" • OpenAthens: ✓ Enabled")
|
|
1444
|
-
else:
|
|
1445
|
-
print(" • OpenAthens: ✓ Enabled (no email set)")
|
|
1446
|
-
else:
|
|
1447
|
-
print(" • OpenAthens: ✗ Disabled")
|
|
1448
|
-
|
|
1449
|
-
# Settings
|
|
1450
|
-
print("\n📁 Settings:")
|
|
1451
|
-
print(f" • Workspace: {self.workspace_dir}")
|
|
1452
|
-
|
|
1453
|
-
default_limit = self.config.resolve("default_search_limit", None, 20, int)
|
|
1454
|
-
print(f" • Default search limit: {default_limit}")
|
|
1455
|
-
|
|
1456
|
-
default_sources = self.config.resolve("default_search_sources", None, [], list)
|
|
1457
|
-
if default_sources:
|
|
1458
|
-
print(f" • Default sources: {', '.join(default_sources)}")
|
|
1459
|
-
else:
|
|
1460
|
-
print(" • Default sources: None configured")
|
|
1461
|
-
|
|
1462
|
-
print("\n💡 Tip: Configure with environment variables or YAML file")
|
|
1463
|
-
print(" See: Scholar configuration documentation")
|
|
1464
|
-
print("=" * 60 + "\n")
|
|
1465
|
-
|
|
1466
|
-
def configure_ezproxy(
|
|
1467
|
-
self,
|
|
1468
|
-
proxy_url: Optional[str] = None,
|
|
1469
|
-
username: Optional[str] = None,
|
|
1470
|
-
password: Optional[str] = None,
|
|
1471
|
-
institution: Optional[str] = None,
|
|
1472
|
-
save_to_env: bool = False,
|
|
1473
|
-
):
|
|
1474
|
-
"""
|
|
1475
|
-
Configure EZProxy authentication.
|
|
1476
|
-
|
|
1477
|
-
Args:
|
|
1478
|
-
proxy_url: EZProxy server URL (e.g., 'https://ezproxy.library.edu')
|
|
1479
|
-
username: Username for authentication
|
|
1480
|
-
password: Password for authentication
|
|
1481
|
-
institution: Institution name
|
|
1482
|
-
save_to_env: Save configuration to environment variables
|
|
1483
|
-
|
|
1484
|
-
Example:
|
|
1485
|
-
scholar.configure_ezproxy(
|
|
1486
|
-
proxy_url="https://ezproxy.myuni.edu",
|
|
1487
|
-
username="johndoe",
|
|
1488
|
-
institution="My University"
|
|
1489
|
-
)
|
|
1490
|
-
"""
|
|
1491
|
-
import getpass
|
|
1492
|
-
|
|
1493
|
-
# Update configuration
|
|
1494
|
-
self.config.ezproxy_enabled = True
|
|
1495
|
-
|
|
1496
|
-
if proxy_url:
|
|
1497
|
-
self.config.ezproxy_url = proxy_url
|
|
1498
|
-
elif not self.config.ezproxy_url:
|
|
1499
|
-
self.config.ezproxy_url = input("EZProxy URL: ")
|
|
1500
|
-
|
|
1501
|
-
if username:
|
|
1502
|
-
self.config.ezproxy_username = username
|
|
1503
|
-
elif not self.config.ezproxy_username:
|
|
1504
|
-
self.config.ezproxy_username = input("EZProxy username: ")
|
|
1505
|
-
|
|
1506
|
-
if password:
|
|
1507
|
-
self.config.ezproxy_password = password
|
|
1508
|
-
|
|
1509
|
-
if institution:
|
|
1510
|
-
self.config.ezproxy_institution = institution
|
|
1511
|
-
|
|
1512
|
-
# Save to environment if requested
|
|
1513
|
-
if save_to_env:
|
|
1514
|
-
env_vars = {
|
|
1515
|
-
"SCITEX_SCHOLAR_EZPROXY_ENABLED": "true",
|
|
1516
|
-
"SCITEX_SCHOLAR_EZPROXY_URL": self.config.ezproxy_url,
|
|
1517
|
-
"SCITEX_SCHOLAR_EZPROXY_USERNAME": self.config.ezproxy_username,
|
|
1518
|
-
}
|
|
1519
|
-
if self.config.ezproxy_institution:
|
|
1520
|
-
env_vars["SCITEX_SCHOLAR_EZPROXY_INSTITUTION"] = (
|
|
1521
|
-
self.config.ezproxy_institution
|
|
1522
|
-
)
|
|
1523
|
-
|
|
1524
|
-
print("\nAdd these to your environment:")
|
|
1525
|
-
for key, value in env_vars.items():
|
|
1526
|
-
if value:
|
|
1527
|
-
print(f'export {key}="{value}"')
|
|
1528
|
-
|
|
1529
|
-
# Reinitialize PDF downloader with EZProxy
|
|
1530
|
-
self._initialize_pdf_downloader()
|
|
1531
|
-
|
|
1532
|
-
logger.info(f"EZProxy configured for {self.config.ezproxy_url}")
|
|
1533
|
-
|
|
1534
|
-
async def authenticate_async_ezproxy_async(self, force: bool = False) -> bool:
|
|
1535
|
-
"""
|
|
1536
|
-
Authenticate with EZProxy (async).
|
|
1537
|
-
|
|
1538
|
-
Args:
|
|
1539
|
-
force: Force re-authentication even if session exists
|
|
1540
|
-
|
|
1541
|
-
Returns:
|
|
1542
|
-
True if authentication successful
|
|
1543
|
-
"""
|
|
1544
|
-
if not self.config.ezproxy_enabled:
|
|
1545
|
-
raise ScholarError(
|
|
1546
|
-
"EZProxy not configured. Call configure_ezproxy() first."
|
|
1547
|
-
)
|
|
1548
|
-
|
|
1549
|
-
if not self._pdf_downloader.ezproxy_authenticator:
|
|
1550
|
-
raise ScholarError("EZProxy authenticator not initialized")
|
|
1551
|
-
|
|
1552
|
-
result = await self._pdf_downloader.ezproxy_authenticator.authenticate_async(
|
|
1553
|
-
force=force
|
|
1554
|
-
)
|
|
1555
|
-
return bool(result)
|
|
1556
|
-
|
|
1557
|
-
def authenticate_async_ezproxy(self, force: bool = False) -> bool:
|
|
1558
|
-
"""
|
|
1559
|
-
Authenticate with EZProxy (sync).
|
|
1560
|
-
|
|
1561
|
-
Args:
|
|
1562
|
-
force: Force re-authentication even if session exists
|
|
1563
|
-
|
|
1564
|
-
Returns:
|
|
1565
|
-
True if authentication successful
|
|
1566
|
-
"""
|
|
1567
|
-
return self._run_async(self.authenticate_async_ezproxy_async(force))
|
|
1568
|
-
|
|
1569
|
-
async def is_ezproxy_authenticate_async_async(self) -> bool:
|
|
1570
|
-
"""
|
|
1571
|
-
Check if EZProxy is authenticate_async (async).
|
|
1572
|
-
|
|
1573
|
-
Returns:
|
|
1574
|
-
True if authenticate_async and session is valid
|
|
1575
|
-
"""
|
|
1576
|
-
if not self._pdf_downloader.ezproxy_authenticator:
|
|
1577
|
-
return False
|
|
1578
|
-
return await self._pdf_downloader.ezproxy_authenticator.is_authenticate_async()
|
|
1579
|
-
|
|
1580
|
-
def is_ezproxy_authenticate_async(self) -> bool:
|
|
1581
|
-
"""
|
|
1582
|
-
Check if EZProxy is authenticate_async (sync).
|
|
1583
|
-
|
|
1584
|
-
Returns:
|
|
1585
|
-
True if authenticate_async and session is valid
|
|
1586
|
-
"""
|
|
1587
|
-
return self._run_async(self.is_ezproxy_authenticate_async_async())
|
|
1588
|
-
|
|
1589
|
-
def configure_shibboleth(
|
|
1590
|
-
self,
|
|
1591
|
-
institution: Optional[str] = None,
|
|
1592
|
-
idp_url: Optional[str] = None,
|
|
1593
|
-
username: Optional[str] = None,
|
|
1594
|
-
password: Optional[str] = None,
|
|
1595
|
-
entity_id: Optional[str] = None,
|
|
1596
|
-
) -> None:
|
|
1597
|
-
"""
|
|
1598
|
-
Configure Shibboleth authentication.
|
|
1599
|
-
|
|
1600
|
-
Args:
|
|
1601
|
-
institution: Institution name (e.g., 'University of Example')
|
|
1602
|
-
idp_url: Identity Provider URL
|
|
1603
|
-
username: Username for authentication
|
|
1604
|
-
password: Password for authentication
|
|
1605
|
-
entity_id: Entity ID for the institution
|
|
1606
|
-
"""
|
|
1607
|
-
# Update config with provided values
|
|
1608
|
-
if institution:
|
|
1609
|
-
self.config.shibboleth_institution = institution
|
|
1610
|
-
if idp_url:
|
|
1611
|
-
self.config.shibboleth_idp_url = idp_url
|
|
1612
|
-
if username:
|
|
1613
|
-
self.config.shibboleth_username = username
|
|
1614
|
-
if password:
|
|
1615
|
-
self.config.shibboleth_password = password
|
|
1616
|
-
if entity_id:
|
|
1617
|
-
self.config.shibboleth_entity_id = entity_id
|
|
1618
|
-
|
|
1619
|
-
# Enable Shibboleth
|
|
1620
|
-
self.config.shibboleth_enabled = True
|
|
1621
|
-
|
|
1622
|
-
# Reinitialize downloader with new config
|
|
1623
|
-
self._initialize_pdf_downloader()
|
|
1624
|
-
|
|
1625
|
-
# Initialize Shibboleth in downloader
|
|
1626
|
-
if hasattr(self._pdf_downloader, "_init_shibboleth"):
|
|
1627
|
-
self._pdf_downloader._init_shibboleth()
|
|
1628
|
-
|
|
1629
|
-
async def authenticate_async_shibboleth_async(self, force: bool = False) -> bool:
|
|
1630
|
-
"""
|
|
1631
|
-
Authenticate with Shibboleth (async).
|
|
1632
|
-
|
|
1633
|
-
Args:
|
|
1634
|
-
force: Force re-authentication even if session exists
|
|
1635
|
-
|
|
1636
|
-
Returns:
|
|
1637
|
-
True if authentication successful
|
|
1638
|
-
"""
|
|
1639
|
-
if not self._pdf_downloader.shibboleth_authenticator:
|
|
1640
|
-
# Initialize Shibboleth if not already done
|
|
1641
|
-
if hasattr(self._pdf_downloader, "_init_shibboleth"):
|
|
1642
|
-
self._pdf_downloader._init_shibboleth()
|
|
1643
|
-
|
|
1644
|
-
if not self._pdf_downloader.shibboleth_authenticator:
|
|
1645
|
-
raise ValueError(
|
|
1646
|
-
"Shibboleth not configured. Call configure_shibboleth() first."
|
|
1647
|
-
)
|
|
1648
|
-
|
|
1649
|
-
result = await self._pdf_downloader.shibboleth_authenticator.authenticate_async(
|
|
1650
|
-
force=force
|
|
1651
|
-
)
|
|
1652
|
-
return bool(result.get("cookies"))
|
|
1653
|
-
|
|
1654
|
-
def authenticate_async_shibboleth(self, force: bool = False) -> bool:
|
|
1655
|
-
"""
|
|
1656
|
-
Authenticate with Shibboleth (sync).
|
|
1657
|
-
|
|
1658
|
-
Args:
|
|
1659
|
-
force: Force re-authentication even if session exists
|
|
1660
|
-
|
|
1661
|
-
Returns:
|
|
1662
|
-
True if authentication successful
|
|
1663
|
-
"""
|
|
1664
|
-
return self._run_async(self.authenticate_async_shibboleth_async(force))
|
|
1665
|
-
|
|
1666
|
-
async def is_shibboleth_authenticate_async_async(self) -> bool:
|
|
1667
|
-
"""
|
|
1668
|
-
Check if Shibboleth is authenticate_async (async).
|
|
1669
|
-
|
|
1670
|
-
Returns:
|
|
1671
|
-
True if authenticate_async and session is valid
|
|
1672
|
-
"""
|
|
1673
|
-
if not self._pdf_downloader.shibboleth_authenticator:
|
|
1674
|
-
return False
|
|
1675
|
-
return (
|
|
1676
|
-
await self._pdf_downloader.shibboleth_authenticator.is_authenticate_async()
|
|
1677
|
-
)
|
|
1678
|
-
|
|
1679
|
-
def is_shibboleth_authenticate_async(self) -> bool:
|
|
1680
|
-
"""
|
|
1681
|
-
Check if Shibboleth is authenticate_async (sync).
|
|
1682
|
-
|
|
1683
|
-
Returns:
|
|
1684
|
-
True if authenticate_async and session is valid
|
|
1685
|
-
"""
|
|
1686
|
-
return self._run_async(self.is_shibboleth_authenticate_async_async())
|
|
1687
|
-
|
|
1688
|
-
def _run_async(self, coro):
|
|
1689
|
-
"""Run async coroutine in sync context."""
|
|
1690
|
-
try:
|
|
1691
|
-
# Check if we're already in an async context
|
|
1692
|
-
loop = asyncio.get_running_loop()
|
|
1693
|
-
# We're in an async context, create a task
|
|
1694
|
-
import concurrent.futures
|
|
1695
|
-
|
|
1696
|
-
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
1697
|
-
future = executor.submit(asyncio.run, coro)
|
|
1698
|
-
return future.result()
|
|
1699
|
-
except RuntimeError:
|
|
1700
|
-
# No event loop running, we can use asyncio.run
|
|
1701
|
-
return asyncio.run(coro)
|
|
1702
|
-
|
|
1703
|
-
# Context manager support
|
|
1704
|
-
def __enter__(self):
|
|
1705
|
-
return self
|
|
1706
|
-
|
|
1707
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
1708
|
-
pass
|
|
1709
|
-
|
|
1710
|
-
# Async context manager support
|
|
1711
|
-
async def __aenter__(self):
|
|
1712
|
-
return self
|
|
1713
|
-
|
|
1714
|
-
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
1715
|
-
pass
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
# Convenience functions for quick use
|
|
1719
|
-
def search(query: str, **kwargs) -> Papers:
|
|
1720
|
-
"""Quick search without creating Scholar instance."""
|
|
1721
|
-
scholar = Scholar()
|
|
1722
|
-
return scholar.search(query, **kwargs)
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
def search_quick(query: str, top_n: int = 5) -> List[str]:
|
|
1726
|
-
"""Quick search returning just titles."""
|
|
1727
|
-
scholar = Scholar()
|
|
1728
|
-
return scholar.search_quick(query, top_n)
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
def enrich_bibtex(
|
|
1732
|
-
bibtex_path: Union[str, Path],
|
|
1733
|
-
output_path: Optional[Union[str, Path]] = None,
|
|
1734
|
-
) -> Papers:
|
|
1735
|
-
"""
|
|
1736
|
-
Quick function to enrich a BibTeX file with impact factors and citations.
|
|
1737
|
-
|
|
1738
|
-
This is the easiest way to enrich your bibliography with:
|
|
1739
|
-
- Journal impact factors (2024 JCR data)
|
|
1740
|
-
- Citation counts from CrossRef and Semantic Scholar
|
|
1741
|
-
- Missing DOIs
|
|
1742
|
-
|
|
1743
|
-
Args:
|
|
1744
|
-
bibtex_path: Path to BibTeX file to enrich
|
|
1745
|
-
output_path: Optional output path (defaults to overwriting input with backup)
|
|
1746
|
-
|
|
1747
|
-
Returns:
|
|
1748
|
-
Papers collection with enriched data
|
|
1749
|
-
|
|
1750
|
-
Example:
|
|
1751
|
-
>>> from scitex.scholar import enrich_bibtex
|
|
1752
|
-
>>> enrich_bibtex("my_papers.bib")
|
|
1753
|
-
>>> # Or save to new file:
|
|
1754
|
-
>>> enrich_bibtex("my_papers.bib", "my_papers_enriched.bib")
|
|
1755
|
-
"""
|
|
1756
|
-
scholar = Scholar()
|
|
1757
|
-
return scholar.enrich_bibtex(bibtex_path, output_path)
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
# Export main class and convenience functions
|
|
1761
|
-
__all__ = ["Scholar", "search", "search_quick", "enrich_bibtex"]
|
|
1762
|
-
|
|
1763
|
-
# EOF
|