scitex 2.15.3__py3-none-any.whl → 2.15.4__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.
@@ -8,11 +8,12 @@ scitex/_optional_deps.py,sha256=ouMy8bw7cxl-AONRNi8xQoxwacR8irKxbcTAI18Hkzw,1014
8
8
  scitex/errors.py,sha256=Pxk8TKpGRk_QBFVB46H7k1Uxetja0OEdYjJjV_lrxRM,2874
9
9
  scitex/mcp_server.py,sha256=VNjs3N21x3_yAzfR8HhuFJJOvYOBHgvJo4tKDQdQsLE,6081
10
10
  scitex/units.py,sha256=lm2SH4PGXz-22tjUoBQhvKJDKmPD01ykSFWoCaFC384,10356
11
- scitex/_mcp_resources/__init__.py,sha256=IJlMdffFQIn7V7UDHYPxXfPchQilNCM1QEFq9tL5ZOg,1283
11
+ scitex/_mcp_resources/__init__.py,sha256=RomYv2wi1PYC8Z3ymAv46q0HygVErrSlViigLTWEuLY,1368
12
12
  scitex/_mcp_resources/_cheatsheet.py,sha256=pdwzAB3IEr7UHkFv0D0-TJGeHF6ENtuq6NHeneLgKo8,3883
13
13
  scitex/_mcp_resources/_figrecipe.py,sha256=A8oK3FwDqSNYyYI4jwfNJ2yiH_8XVnfFjoGJtuvdDLU,3581
14
14
  scitex/_mcp_resources/_formats.py,sha256=EyNZKtmX6dg6vK1Gk0EmrSSKH5d9yc3RMqZtSP-Op0I,2923
15
15
  scitex/_mcp_resources/_modules.py,sha256=17LZpOPSmr9XwgGJg2vRgEK596S5FoSYb320vgm9x-k,8702
16
+ scitex/_mcp_resources/_scholar.py,sha256=RSYt7j6bcbKtR-tOtvCtdE6J3IS8C925_c34t0Z1Es8,4689
16
17
  scitex/_mcp_resources/_session.py,sha256=lbe9W3cfPOyoq6bPOeN-jB8MwI4DnRWMpxHmpfn97SM,4590
17
18
  scitex/_mcp_tools/__init__.py,sha256=6krJPLr6ReVAkGoZR7vQHQrszr8AGW4dwWsY2EcmPkc,1229
18
19
  scitex/_mcp_tools/audio.py,sha256=LBX9YQZkNGAXfoIEFljnHRk39gTyJfdaVPCRrS6F8qE,6245
@@ -21,7 +22,7 @@ scitex/_mcp_tools/capture.py,sha256=k7pwuB1vdP-VCYjutajEZEsvVAKY-8_mEYrYGWXgOo8,
21
22
  scitex/_mcp_tools/diagram.py,sha256=pZNq0UTRlg7piq0YDD40qY5M2mqFYoRdFwmWeRCBieA,585
22
23
  scitex/_mcp_tools/introspect.py,sha256=GY9j9EUAs-CKegzfPHubPT3OGpOjcY5Rb09M3OHEIwA,6562
23
24
  scitex/_mcp_tools/plt.py,sha256=CuI6uOsyDGrLCWHWwnEKru-KCA532GVzt6rcRlxXHt8,9248
24
- scitex/_mcp_tools/scholar.py,sha256=oIo1QSyoF48pEHgaQ1PWt-N_KNf8rJCKdlmiG-8WVQ8,15243
25
+ scitex/_mcp_tools/scholar.py,sha256=Tp8PlcHraLvHMrQWgFgq2jdjAIM4Vsps92mVgZu9NcY,13374
25
26
  scitex/_mcp_tools/social.py,sha256=wyyHCybx0tCUfIEGrGYhxj1thlH-dcIeq05TtUP9RFk,816
26
27
  scitex/_mcp_tools/stats.py,sha256=U2pGC0NTfzb0stKGafVNdgZhIYovYi6ti1EoG4f4dn4,6139
27
28
  scitex/_mcp_tools/template.py,sha256=NhfIaVYo7JvssZk_dUvzosvcc-qjnxFr69dV1DmAlgY,3102
@@ -242,7 +243,7 @@ scitex/browser/stealth/__init__.py,sha256=KVbyLjm8KnM5YwyB84A3pwLdUGkANNgwpA7YL2
242
243
  scitex/canvas/README.md,sha256=jRwasTPNrmQsCyv67ul7qUIgv5xKIab1u2hi8tvlbAg,9142
243
244
  scitex/canvas/__init__.py,sha256=k_1mqbodRgy6phbhLDqRenEEnOLvueWwj0xNNYrCyd0,9380
244
245
  scitex/canvas/canvas.py,sha256=1aUjIqCzwKhGXukCQsHc-h-kqLNA9VqzIMazimqm2mA,12968
245
- scitex/canvas/mcp_server.py,sha256=Q-f8kzW-97wfrDmOo0LTYd8zXTBiiSOdJH3e4vjDDoo,4379
246
+ scitex/canvas/mcp_server.py,sha256=fBTmtXOhO60wG-e6j-Y-WE_aWykAMsajWkidZRQ6lcU,4754
246
247
  scitex/canvas/_mcp/__init__.py,sha256=FJRAr90vUCg4PJ8Sv-WzsKuM7aY93m6UR87fhk843MU,73
247
248
  scitex/canvas/_mcp/handlers.py,sha256=oVZcYfEyDBl6lEKJ7vTWnrueBO-CWOiAbGNrKVFQOww,8528
248
249
  scitex/canvas/_mcp/tool_schemas.py,sha256=Tl6CIpuW_J0QppShjZPo0DJ8wiNgLk6oHBoR74ASC7Y,8046
@@ -364,7 +365,7 @@ scitex/capture/capture.py,sha256=vDVaY2mTNxTsWbg8he78jh0NPhVULLzanREkE9EtQHE,287
364
365
  scitex/capture/cli.py,sha256=bNal0BXlAM34q9OLv1ydV9lHq95pckY0XaaxsiQTkts,7201
365
366
  scitex/capture/gif.py,sha256=Rbx-9u6zGAjImhFWp5yLm3MXCW1oaUq8OusWdPnzJAY,11278
366
367
  scitex/capture/grid.py,sha256=LQKNyP5I1UN50rCnxi0tCf7vurLLp3mwRzCoYDa10ZQ,14189
367
- scitex/capture/mcp_server.py,sha256=my57OABAsS2A5sOcCUn1PkNS8SR0MFeqP3SEHPvOzFg,37664
368
+ scitex/capture/mcp_server.py,sha256=jIRAHW48jEvhhk2NYVZifkI42s-XzkGmt7UKwmJ0xDw,38059
368
369
  scitex/capture/session.py,sha256=N-8mY6A6QmJHRCJYW4dQhrK7iVmJhYBRDt8vYyeBNYE,1972
369
370
  scitex/capture/utils.py,sha256=WyMr8aGmWqOneT4BFTvWNY-PrMPxmKLHtUEgSk59URY,21881
370
371
  scitex/capture/_mcp/__init__.py,sha256=MhQoN-oXeeZ-P34rJDluwSi45hf3sC4pVi8MfTW6LBc,286
@@ -397,11 +398,12 @@ scitex/cli/template.py,sha256=omoT2qzWtyqJYqrIqJ74uyDgoQTL667ONSbwSQU4sb8,12015
397
398
  scitex/cli/tex.py,sha256=d_Fh9PXObuyjMgQ_Ap60aXwAztJbY3Pd2SvfV92toBg,9222
398
399
  scitex/cli/web.py,sha256=_XwnlsOm2MD1eyJVycfsdki4IcDnglXTO5IkZ-eb3xA,13482
399
400
  scitex/cli/writer.py,sha256=lApUnUQrclbufEMwD4m4MKMDg3ZkCBe0kTS9WuH4hsM,1953
400
- scitex/cli/scholar/__init__.py,sha256=RXiRs1gwafsLmVpXkvMsM7tSy2rsuvyu-QlO7y98PzY,7055
401
- scitex/cli/scholar/_crossref_scitex.py,sha256=gjJV7lS4H-u7F1dGZpEVsVrKC2cOHC4RcBXEKQEAhOg,9622
401
+ scitex/cli/scholar/__init__.py,sha256=BQyPjd1jAgcHbjGPZx_amrlGOPM3UaKAdi9JyflQ9k8,8326
402
+ scitex/cli/scholar/_crossref_scitex.py,sha256=-ujYGB-KNtMCMoOBNsOl_qTEp6k6l75JeUqmUwjjG5o,1636
402
403
  scitex/cli/scholar/_fetch.py,sha256=tdRXlsTjhfdOddJwWpOZ5scGGXzhesxrXX9Ri9jm7AQ,11226
403
404
  scitex/cli/scholar/_jobs.py,sha256=hx1aoxdHaR800XC7acWE4x_pxJ7cYq6re7Zf8MxLr7E,9058
404
405
  scitex/cli/scholar/_library.py,sha256=GP3JAtfg3zwGD810BygJLN4B0-m-RqRfyt7_JHtOeT8,4468
406
+ scitex/cli/scholar/_openalex_scitex.py,sha256=-KjFYxnehgJtf4Xz35U_SJqC2zXvvkmdV0ZXThxGpQI,1559
405
407
  scitex/cli/scholar/_utils.py,sha256=SC-_wB0UFV89p-4PVdVeREbTOp6oV2ke4QRiiRzShig,770
406
408
  scitex/cloud/__init__.py,sha256=xyzKrQGDpoCMNTLNQmCZjvVQxuPlcj306Kjn3psZCNk,5064
407
409
  scitex/cloud/_matplotlib_hook.py,sha256=B5IEctAF1Rb7jvkZa5Xl8T1FuBcGiRjFxEtW_mmRz2I,3731
@@ -1278,17 +1280,19 @@ scitex/schema/_theme.py,sha256=1AWmJy7vim2lmIJlbjv4BCLxKmNeqw0WGEGr2z_U9Kw,10192
1278
1280
  scitex/schema/_validation.py,sha256=8u4dVVfAhCzdRtcpqFxChumRMyHJQfBQgnyf1TpsQ_s,13747
1279
1281
  scitex/scholar/.gitignore,sha256=oYROO1p7Mia9ftRowaRu3BVNm7jdMY9O4Ro1RSgSC80,381
1280
1282
  scitex/scholar/README.md,sha256=AbE7t0qIKQY11ZSGkeQXNP_qA088q-2t-oQ3W5bDvxI,3799
1281
- scitex/scholar/__init__.py,sha256=DZm8kU5nETTv63M0IR2RHitPucO_3qTMSVrH48yqRGw,10120
1283
+ scitex/scholar/__init__.py,sha256=F7a-OTd8kqZK2vRQVhAGMTqkOGynMc7FRND_SROFTg8,10392
1282
1284
  scitex/scholar/__main__.py,sha256=U7QKol30Vsvw_Xg4tVS5F1iFU4UluKnm1Z0Bs18zgCs,9711
1283
- scitex/scholar/crossref_scitex.py,sha256=cM22iDel6N5QkTkUfx8sSyedHffqsYCYRGf4iePN2sw,8928
1284
- scitex/scholar/mcp_server.py,sha256=m-v1sjU0sJeaL0rHrihQz6alost__Koc7wyEAqP7bIY,12553
1285
+ scitex/scholar/mcp_server.py,sha256=z_b4pD2z1H2bG1B6ATt3B6e8uNBMl-MLz6a3KLnaCiw,14934
1285
1286
  scitex/scholar/_mcp/__init__.py,sha256=FJRAr90vUCg4PJ8Sv-WzsKuM7aY93m6UR87fhk843MU,73
1286
1287
  scitex/scholar/_mcp/all_handlers.py,sha256=yALfZdQhDXWPlqUB1rcncENXyVVFNDnpGqhz5iCc-5Q,1856
1287
1288
  scitex/scholar/_mcp/crossref_handlers.py,sha256=fBN9pVzQLiGT4FWoLGAOdsm-_-gwhMo1EEl0S9MlA0c,7770
1289
+ scitex/scholar/_mcp/crossref_tool_schemas.py,sha256=v1VI3I2r_LWqt4IuEJo_JvXxtdY04eZ3zk6Kvqumou4,4748
1288
1290
  scitex/scholar/_mcp/handlers.py,sha256=gMFBHPdqfWGRUDSu3wlllVBnJSzrkGm9ZUnUBhZXCY0,51088
1289
1291
  scitex/scholar/_mcp/job_handlers.py,sha256=8ZkFRG1TOq20168DIpic3VMAMzTzieg1jnaE7eXQLlU,4970
1290
1292
  scitex/scholar/_mcp/job_tool_schemas.py,sha256=xDTysuf3aLNxLO1O57sal5XcMeEstk0SB77wK9q6yVs,5777
1291
- scitex/scholar/_mcp/tool_schemas.py,sha256=AuedyrT9BOERnG_6zpLx1oVzfRs2JWaYE1RbBtDkW6g,19580
1293
+ scitex/scholar/_mcp/openalex_handlers.py,sha256=r9X1mwMqqwovrbx4pcgHQeISCbGqqW87neP6EW09Pnw,6503
1294
+ scitex/scholar/_mcp/openalex_tool_schemas.py,sha256=zu7--BZ7_aEnaJuEg-Sb1FiKNoeRthat70S9TZ70uL4,3194
1295
+ scitex/scholar/_mcp/tool_schemas.py,sha256=ng_lGqhwa_2BxByASZriDgnZSHTewvqpF6jOzqRxEZ0,19818
1292
1296
  scitex/scholar/auth/README.md,sha256=YYLVVHAgHFjoYXjWJ2SV_3toOJPSnWOs6-EMKbPIu9U,3373
1293
1297
  scitex/scholar/auth/ScholarAuthManager.py,sha256=u1t9FrTbBQyGvNmuuMprSpCLLxG0Fap-oCrm0x0iDSE,10570
1294
1298
  scitex/scholar/auth/__init__.py,sha256=kM_iLBm00U1sVBr1TuAT7dY46kZqcOCUztMykxBlxhQ,470
@@ -1490,6 +1494,9 @@ scitex/scholar/jobs/_JobManager.py,sha256=F06vxOZoYouqgeNVmlwKpDPkWWh-PU2aLp3pqu
1490
1494
  scitex/scholar/jobs/__init__.py,sha256=dXdPmFUWf-Ypl41_Z6qsduYCofygfgq2UjiIZcYiGjQ,1779
1491
1495
  scitex/scholar/jobs/_errors.py,sha256=V7Xv4q0CDBJIQ6NSg-lRb_skFcqT-jIZ_aI5gavjDds,10211
1492
1496
  scitex/scholar/jobs/_executors.py,sha256=kWU9uuN_8cx6oPyGakjcypsiZoUwicrHL29_aF_iZUU,11807
1497
+ scitex/scholar/local_dbs/__init__.py,sha256=sxCiEcOy5pC6VBpEExHgkAlu1st7EUcfw6PRFo67buQ,857
1498
+ scitex/scholar/local_dbs/crossref_scitex.py,sha256=Ib2JluhqyYjDPh0hZqENHNP7_eg21AQnkyWjl5pfXRs,748
1499
+ scitex/scholar/local_dbs/openalex_scitex.py,sha256=mnHHMnk2aJcSfXYWJh2wsbs818oU1fW63i_3VZG7wpI,748
1493
1500
  scitex/scholar/metadata_engines/README.md,sha256=wz1fTeru9sTgkGO5T8VdDBsd4FBaZu2t6-I8MTNGifw,919
1494
1501
  scitex/scholar/metadata_engines/ScholarEngine.py,sha256=WGOEvCiBiMm0aZNtN1AlBDCcN6XQUl76R6zedUhR7gs,20604
1495
1502
  scitex/scholar/metadata_engines/__init__.py,sha256=qjndZBrK2tXOMCRHFeEu2BJ9Ir8nbr7cHsV4xvXUwv4,749
@@ -2408,7 +2415,7 @@ scitex/stats/__init__.py,sha256=ZD8j9RTrlwg_JNV3vcTzaovHM0eWKtsfJa5Uno4iWpE,1003
2408
2415
  scitex/stats/__main__.py,sha256=Jnupr0q90w0ZKbnHSsqXmFWukMGuXzG4bPXInj8Gqmo,7815
2409
2416
  scitex/stats/_figrecipe_integration.py,sha256=_nOD1rcITE3HGEc3-5Bu0Q2VRy3Tizil7H35GJyeOng,3076
2410
2417
  scitex/stats/_schema.py,sha256=d12piS129kDRnHAD3XJ96d3G8ZLeYm1tK4CAlBfdtbg,1105
2411
- scitex/stats/mcp_server.py,sha256=j3Bkf0GeLUBS8Ao2k_-GaiWuostObflkddDXJKwzKps,15136
2418
+ scitex/stats/mcp_server.py,sha256=_tjHu7Gubq8519Q_mfKzGGyPUINjoDpAmlszLVlKHZk,15511
2412
2419
  scitex/stats/run_all.sh,sha256=Q_fw3q_10mlQAUBRggSNrl0gILFvTFUlFztH2Aicfhs,1381
2413
2420
  scitex/stats/_mcp/__init__.py,sha256=FJRAr90vUCg4PJ8Sv-WzsKuM7aY93m6UR87fhk843MU,73
2414
2421
  scitex/stats/_mcp/handlers.py,sha256=zvSep5DdTMMRmFFhSDBy-PGeoGhq7e4QAW_7V2v3_dQ,874
@@ -2500,7 +2507,7 @@ scitex/template/clone_pip_project.py,sha256=cEQkbyD8x-0iVDrL3iCIH2z5e_7mKIXe-uPQ
2500
2507
  scitex/template/clone_research.py,sha256=cWwW6vQp03u19mDlit-P6yMHF30IW6DQf3xXVdd-D1M,3073
2501
2508
  scitex/template/clone_singularity.py,sha256=CYMjaUU1Bf58tKtU5tlTKgjd1EphaZvmMpqmhIyPtyw,3103
2502
2509
  scitex/template/clone_writer_directory.py,sha256=ibAlEkMRLTBYmxgg_LFMtFr3uLTMFhTyYyhoDkwv6xE,3058
2503
- scitex/template/mcp_server.py,sha256=yQBDQpIwcIBzdgHPRXVSVBHrHb3DWd0b5V4DmN6WvY4,5718
2510
+ scitex/template/mcp_server.py,sha256=aqCOdzFOeEBjA4RPlXrPXY9O9nix0fOItENQNwdYv5Y,6096
2504
2511
  scitex/template/_mcp/__init__.py,sha256=FJRAr90vUCg4PJ8Sv-WzsKuM7aY93m6UR87fhk843MU,73
2505
2512
  scitex/template/_mcp/handlers.py,sha256=VqOt8Rjb2d6z0Fhlfui2KgX-coQS-eUZkBZ7z6caOjY,9073
2506
2513
  scitex/template/_mcp/tool_schemas.py,sha256=dAuqmTrdOA8DJOtzRvhvvlLNBLLivOJW-UXiTldzt7Y,6580
@@ -2533,7 +2540,7 @@ scitex/types/__init__.py,sha256=VdI0QzASeZMy_mUCtSfNO8Ngn9PYQ-oGeweo9NfRmrg,301
2533
2540
  scitex/types/_is_listed_X.py,sha256=4lSFyuqKaZytqDGuyGqUJOqkrFo0Ymql3kfWwIva5L0,1867
2534
2541
  scitex/ui/__init__.py,sha256=YTPRgC-eLHgB1Saxml_S5CIRFR0mVTld5f1ZIe8EemI,4882
2535
2542
  scitex/ui/_backends.py,sha256=qChJsy_2WUGfXbPd_-CyYf2kOusr4qsEFCT-rduyJ30,741
2536
- scitex/ui/mcp_server.py,sha256=d0dp3vKeF0-Xp3_DGF37ZrgIVjDhu8f9It-e4xclKeI,4795
2543
+ scitex/ui/mcp_server.py,sha256=HxTJIhsOLGM7ccuH4MvC94ueoZTVdVOv7Jw-HhRiNAs,5166
2537
2544
  scitex/ui/_backends/__init__.py,sha256=n3oNFT7NtXrPPORJ0bYk89d-SkZdBH4-1eMR0vZ-buI,1756
2538
2545
  scitex/ui/_backends/_audio.py,sha256=3Qq2amkGgmkqqTcEWX82aL3iLrOcY1n8zUYgRH7mzK8,2418
2539
2546
  scitex/ui/_backends/_config.py,sha256=Qqzw8U7Ej2kkI4wmVjmixNc7KuIym5klalGiv4TxJUs,8427
@@ -2612,8 +2619,8 @@ scitex/writer/utils/_parse_latex_logs.py,sha256=K05kCJClG86-RovXG9I5e3wHP0mEGiZl
2612
2619
  scitex/writer/utils/_parse_script_args.py,sha256=Fkx1ze_jlKYIpviLuT7z0hpqE4cdtXXA_7sK3sKpVs4,4593
2613
2620
  scitex/writer/utils/_verify_tree_structure.py,sha256=Uk9NUSleR9aMHpAgUGsPZMk4a75l35EkZhQYKIfolVY,5724
2614
2621
  scitex/writer/utils/_watch.py,sha256=nYzPQ-iPAOzbwzAPBtSrrVBLLPMl08e0qxw0mtv0Y8I,2577
2615
- scitex-2.15.3.dist-info/METADATA,sha256=6A_-9ygRskE6_IPk9cckwDNouvioOb1TyKR6wCrmReA,25007
2616
- scitex-2.15.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
2617
- scitex-2.15.3.dist-info/entry_points.txt,sha256=ZtDrHnPNMnsSmAnQoCHNmk0xKotNyR2X_YFDDteupW8,497
2618
- scitex-2.15.3.dist-info/licenses/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
2619
- scitex-2.15.3.dist-info/RECORD,,
2622
+ scitex-2.15.4.dist-info/METADATA,sha256=YhHg4lxfd6DXKl_tGIfOp6ZAXs6HkBzAo3K61emqz7U,25007
2623
+ scitex-2.15.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
2624
+ scitex-2.15.4.dist-info/entry_points.txt,sha256=ZtDrHnPNMnsSmAnQoCHNmk0xKotNyR2X_YFDDteupW8,497
2625
+ scitex-2.15.4.dist-info/licenses/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
2626
+ scitex-2.15.4.dist-info/RECORD,,
@@ -1,367 +0,0 @@
1
- #!/usr/bin/env python3
2
- # Timestamp: 2026-01-24
3
- # File: src/scitex/scholar/crossref_scitex.py
4
- """CrossRef-SciTeX: Local CrossRef database integration for scitex.scholar.
5
-
6
- This module provides access to the local CrossRef database (167M+ papers)
7
- through the crossref-local package. Branded as "crossref-scitex" to distinguish
8
- from the official CrossRef API. Supports both direct database access and HTTP
9
- API mode for remote servers.
10
-
11
- Quick Start
12
- -----------
13
-
14
- Search for papers:
15
- >>> from scitex.scholar import crossref_scitex
16
- >>> results = crossref_scitex.search("hippocampal sharp wave ripples")
17
- >>> print(results.total, "papers found")
18
-
19
- Get paper by DOI:
20
- >>> work = crossref_scitex.get("10.1126/science.aax0758")
21
- >>> print(work.title)
22
-
23
- Configuration
24
- -------------
25
-
26
- The mode is automatically detected:
27
- - If CROSSREF_LOCAL_DB is set, uses direct database access
28
- - If CROSSREF_LOCAL_API_URL is set, uses HTTP API
29
- - Default: tries localhost:31291 (SciTeX port scheme)
30
-
31
- Environment variables (SCITEX_SCHOLAR_CROSSREF_* takes priority):
32
- SCITEX_SCHOLAR_CROSSREF_DB: Path to local database
33
- SCITEX_SCHOLAR_CROSSREF_MODE: 'db' or 'http'
34
- CROSSREF_LOCAL_DB: Path to local database (fallback)
35
- CROSSREF_LOCAL_API_URL: HTTP API URL (fallback)
36
-
37
- SSH tunnel for remote database:
38
- $ ssh -L 31291:127.0.0.1:31291 your-server
39
- """
40
-
41
- from __future__ import annotations
42
-
43
- from typing import TYPE_CHECKING, Any, Optional
44
-
45
- # Set environment variables for crossref-local configuration
46
- # SCITEX_SCHOLAR_CROSSREF_* vars take priority in crossref-local's config.py
47
-
48
- if TYPE_CHECKING:
49
- from crossref_local import SearchResult, Work
50
- from crossref_local.citations import CitationNetwork
51
-
52
- __all__ = [
53
- # Core search/retrieval
54
- "search",
55
- "count",
56
- "get",
57
- "get_many",
58
- "exists",
59
- # Enrichment
60
- "enrich",
61
- "enrich_dois",
62
- # Configuration
63
- "configure",
64
- "configure_http",
65
- "get_mode",
66
- "info",
67
- "is_available",
68
- # Citation functions
69
- "get_citing",
70
- "get_cited",
71
- "get_citation_count",
72
- # Classes (re-exported)
73
- "Work",
74
- "SearchResult",
75
- "CitationNetwork",
76
- # Async API
77
- "aio",
78
- # Cache module
79
- "cache",
80
- ]
81
-
82
-
83
- def _ensure_crossref_local():
84
- """Ensure crossref-local is available."""
85
- try:
86
- import crossref_local
87
-
88
- return crossref_local
89
- except ImportError as e:
90
- raise ImportError(
91
- "crossref-local not installed. Install with: pip install crossref-local"
92
- ) from e
93
-
94
-
95
- def is_available() -> bool:
96
- """Check if crossref-local is available and configured.
97
-
98
- Returns
99
- -------
100
- True if crossref-local can be used (either DB or HTTP mode)
101
- """
102
- try:
103
- crl = _ensure_crossref_local()
104
- info_result = crl.info()
105
- return info_result.get("status") == "ok"
106
- except Exception:
107
- return False
108
-
109
-
110
- # =============================================================================
111
- # Core Search/Retrieval Functions (delegated to crossref-local)
112
- # =============================================================================
113
-
114
-
115
- def search(
116
- query: str,
117
- limit: int = 20,
118
- offset: int = 0,
119
- **kwargs: Any,
120
- ) -> SearchResult:
121
- """Search for papers in the CrossRef database.
122
-
123
- Args:
124
- query: Search query string (full-text search)
125
- limit: Maximum number of results (default: 20)
126
- offset: Number of results to skip for pagination
127
- **kwargs: Additional arguments passed to crossref-local
128
-
129
- Returns
130
- -------
131
- SearchResult containing matching papers
132
-
133
- Examples
134
- --------
135
- >>> from scitex.scholar import crossref
136
- >>> results = crossref.search("deep learning")
137
- >>> for work in results:
138
- ... print(work.title)
139
- """
140
- crl = _ensure_crossref_local()
141
- return crl.search(query, limit=limit, offset=offset, **kwargs)
142
-
143
-
144
- def count(query: str) -> int:
145
- """Count papers matching a search query.
146
-
147
- Args:
148
- query: Search query string
149
-
150
- Returns
151
- -------
152
- Number of matching papers
153
- """
154
- crl = _ensure_crossref_local()
155
- return crl.count(query)
156
-
157
-
158
- def get(doi: str) -> Optional[Work]:
159
- """Get a paper by DOI.
160
-
161
- Args:
162
- doi: DOI of the paper (e.g., "10.1126/science.aax0758")
163
-
164
- Returns
165
- -------
166
- Work object if found, None otherwise
167
-
168
- Examples
169
- --------
170
- >>> work = crossref.get("10.1038/nature12373")
171
- >>> if work:
172
- ... print(work.title, work.year)
173
- """
174
- crl = _ensure_crossref_local()
175
- return crl.get(doi)
176
-
177
-
178
- def get_many(dois: list[str]) -> list[Work]:
179
- """Get multiple papers by DOI.
180
-
181
- Args:
182
- dois: List of DOIs
183
-
184
- Returns
185
- -------
186
- List of Work objects (None for DOIs not found)
187
- """
188
- crl = _ensure_crossref_local()
189
- return crl.get_many(dois)
190
-
191
-
192
- def exists(doi: str) -> bool:
193
- """Check if a DOI exists in the database.
194
-
195
- Args:
196
- doi: DOI to check
197
-
198
- Returns
199
- -------
200
- True if DOI exists
201
- """
202
- crl = _ensure_crossref_local()
203
- return crl.exists(doi)
204
-
205
-
206
- # =============================================================================
207
- # Enrichment Functions
208
- # =============================================================================
209
-
210
-
211
- def enrich(results: SearchResult) -> SearchResult:
212
- """Enrich search results with citation data.
213
-
214
- Args:
215
- results: SearchResult to enrich
216
-
217
- Returns
218
- -------
219
- Enriched SearchResult with citation counts and references
220
- """
221
- crl = _ensure_crossref_local()
222
- return crl.enrich(results)
223
-
224
-
225
- def enrich_dois(dois: list[str]) -> list[Work]:
226
- """Get and enrich papers by DOI with citation data.
227
-
228
- Args:
229
- dois: List of DOIs to enrich
230
-
231
- Returns
232
- -------
233
- List of enriched Work objects
234
- """
235
- crl = _ensure_crossref_local()
236
- return crl.enrich_dois(dois)
237
-
238
-
239
- # =============================================================================
240
- # Citation Functions
241
- # =============================================================================
242
-
243
-
244
- def get_citing(doi: str) -> list[str]:
245
- """Get DOIs of papers that cite this paper.
246
-
247
- Args:
248
- doi: DOI of the paper
249
-
250
- Returns
251
- -------
252
- List of DOIs that cite this paper
253
- """
254
- crl = _ensure_crossref_local()
255
- return crl.get_citing(doi)
256
-
257
-
258
- def get_cited(doi: str) -> list[str]:
259
- """Get DOIs of papers cited by this paper.
260
-
261
- Args:
262
- doi: DOI of the paper
263
-
264
- Returns
265
- -------
266
- List of DOIs cited by this paper (references)
267
- """
268
- crl = _ensure_crossref_local()
269
- return crl.get_cited(doi)
270
-
271
-
272
- def get_citation_count(doi: str) -> int:
273
- """Get the citation count for a paper.
274
-
275
- Args:
276
- doi: DOI of the paper
277
-
278
- Returns
279
- -------
280
- Number of citations
281
- """
282
- crl = _ensure_crossref_local()
283
- return crl.get_citation_count(doi)
284
-
285
-
286
- # =============================================================================
287
- # Configuration Functions
288
- # =============================================================================
289
-
290
-
291
- def configure(db_path: str) -> None:
292
- """Configure direct database access mode.
293
-
294
- Args:
295
- db_path: Path to the crossref.db file
296
- """
297
- crl = _ensure_crossref_local()
298
- crl.configure(db_path)
299
-
300
-
301
- def configure_http(api_url: Optional[str] = None) -> None:
302
- """Configure HTTP API mode.
303
-
304
- Args:
305
- api_url: API URL (default: http://localhost:31291)
306
-
307
- Example:
308
- >>> # After setting up SSH tunnel: ssh -L 31291:127.0.0.1:31291 server
309
- >>> crossref.configure_http()
310
- """
311
- crl = _ensure_crossref_local()
312
- crl.configure_http(api_url)
313
-
314
-
315
- def get_mode() -> str:
316
- """Get the current operating mode.
317
-
318
- Returns
319
- -------
320
- "db" for direct database access, "http" for API mode
321
- """
322
- crl = _ensure_crossref_local()
323
- return crl.get_mode()
324
-
325
-
326
- def info() -> dict:
327
- """Get information about the crossref-local configuration.
328
-
329
- Returns
330
- -------
331
- Dict with status, mode, version, database stats, etc.
332
- """
333
- crl = _ensure_crossref_local()
334
- return crl.info()
335
-
336
-
337
- # =============================================================================
338
- # Re-exported Classes and Modules
339
- # =============================================================================
340
-
341
-
342
- def __getattr__(name: str):
343
- """Lazy import for classes and modules."""
344
- if name == "Work":
345
- from crossref_local import Work
346
-
347
- return Work
348
- elif name == "SearchResult":
349
- from crossref_local import SearchResult
350
-
351
- return SearchResult
352
- elif name == "CitationNetwork":
353
- from crossref_local.citations import CitationNetwork
354
-
355
- return CitationNetwork
356
- elif name == "aio":
357
- from crossref_local import aio
358
-
359
- return aio
360
- elif name == "cache":
361
- from crossref_local import cache
362
-
363
- return cache
364
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
365
-
366
-
367
- # EOF