pyalex 0.14__py3-none-any.whl → 0.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.
- pyalex/__init__.py +0 -4
- pyalex/_version.py +2 -2
- pyalex/api.py +46 -50
- {pyalex-0.14.dist-info → pyalex-0.15.1.dist-info}/METADATA +14 -5
- pyalex-0.15.1.dist-info/RECORD +8 -0
- {pyalex-0.14.dist-info → pyalex-0.15.1.dist-info}/WHEEL +1 -1
- pyalex-0.14.dist-info/RECORD +0 -8
- {pyalex-0.14.dist-info → pyalex-0.15.1.dist-info}/LICENSE +0 -0
- {pyalex-0.14.dist-info → pyalex-0.15.1.dist-info}/top_level.txt +0 -0
pyalex/__init__.py
CHANGED
|
@@ -27,8 +27,6 @@ from pyalex.api import Subfield
|
|
|
27
27
|
from pyalex.api import Subfields
|
|
28
28
|
from pyalex.api import Topic
|
|
29
29
|
from pyalex.api import Topics
|
|
30
|
-
from pyalex.api import Venue
|
|
31
|
-
from pyalex.api import Venues
|
|
32
30
|
from pyalex.api import Work
|
|
33
31
|
from pyalex.api import Works
|
|
34
32
|
from pyalex.api import autocomplete
|
|
@@ -46,8 +44,6 @@ __all__ = [
|
|
|
46
44
|
"Funders",
|
|
47
45
|
"Publishers",
|
|
48
46
|
"Publisher",
|
|
49
|
-
"Venues",
|
|
50
|
-
"Venue",
|
|
51
47
|
"Institutions",
|
|
52
48
|
"Institution",
|
|
53
49
|
"Concepts",
|
pyalex/_version.py
CHANGED
pyalex/api.py
CHANGED
|
@@ -23,7 +23,7 @@ class AlexConfig(dict):
|
|
|
23
23
|
config = AlexConfig(
|
|
24
24
|
email=None,
|
|
25
25
|
api_key=None,
|
|
26
|
-
user_agent="pyalex/"
|
|
26
|
+
user_agent=f"pyalex/{__version__}",
|
|
27
27
|
openalex_url="https://api.openalex.org",
|
|
28
28
|
max_retries=0,
|
|
29
29
|
retry_backoff_factor=0.1,
|
|
@@ -31,12 +31,28 @@ config = AlexConfig(
|
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
def _quote_oa_value(v):
|
|
35
|
+
"""Prepare a value for the OpenAlex API.
|
|
36
|
+
|
|
37
|
+
Applies URL encoding to strings and converts booleans to lowercase strings.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
# workaround for bug https://groups.google.com/u/1/g/openalex-users/c/t46RWnzZaXc
|
|
41
|
+
if isinstance(v, bool):
|
|
42
|
+
return str(v).lower()
|
|
43
|
+
|
|
44
|
+
if isinstance(v, str):
|
|
45
|
+
return quote_plus(v)
|
|
46
|
+
|
|
47
|
+
return v
|
|
48
|
+
|
|
49
|
+
|
|
34
50
|
def _flatten_kv(d, prefix=""):
|
|
35
51
|
if isinstance(d, dict):
|
|
36
52
|
t = []
|
|
37
53
|
for k, v in d.items():
|
|
38
54
|
if isinstance(v, list):
|
|
39
|
-
t.extend([f"{prefix}.{k}:{i}" for i in v])
|
|
55
|
+
t.extend([f"{prefix}.{k}:{_quote_oa_value(i)}" for i in v])
|
|
40
56
|
else:
|
|
41
57
|
new_prefix = f"{prefix}.{k}" if prefix else f"{k}"
|
|
42
58
|
x = _flatten_kv(v, prefix=new_prefix)
|
|
@@ -44,10 +60,7 @@ def _flatten_kv(d, prefix=""):
|
|
|
44
60
|
|
|
45
61
|
return ",".join(t)
|
|
46
62
|
else:
|
|
47
|
-
|
|
48
|
-
d = str(d).lower() if isinstance(d, bool) else d
|
|
49
|
-
|
|
50
|
-
return f"{prefix}:{d}"
|
|
63
|
+
return f"{prefix}:{_quote_oa_value(d)}"
|
|
51
64
|
|
|
52
65
|
|
|
53
66
|
def _params_merge(params, add_params):
|
|
@@ -199,10 +212,11 @@ class BaseOpenAlex:
|
|
|
199
212
|
|
|
200
213
|
def _full_collection_name(self):
|
|
201
214
|
if self.params is not None and "q" in self.params.keys():
|
|
202
|
-
|
|
203
|
-
|
|
215
|
+
return (
|
|
216
|
+
f"{config.openalex_url}/autocomplete/{self.__class__.__name__.lower()}"
|
|
217
|
+
)
|
|
204
218
|
else:
|
|
205
|
-
return config.openalex_url
|
|
219
|
+
return f"{config.openalex_url}/{self.__class__.__name__.lower()}"
|
|
206
220
|
|
|
207
221
|
def __getattr__(self, key):
|
|
208
222
|
if key == "groupby":
|
|
@@ -223,7 +237,7 @@ class BaseOpenAlex:
|
|
|
223
237
|
return self._get_multi_items(record_id)
|
|
224
238
|
|
|
225
239
|
return self._get_from_url(
|
|
226
|
-
self._full_collection_name()
|
|
240
|
+
f"{self._full_collection_name()}/{record_id}", return_meta=False
|
|
227
241
|
)
|
|
228
242
|
|
|
229
243
|
@property
|
|
@@ -236,15 +250,14 @@ class BaseOpenAlex:
|
|
|
236
250
|
if v is None:
|
|
237
251
|
pass
|
|
238
252
|
elif isinstance(v, list):
|
|
239
|
-
|
|
240
|
-
l_params.append(k + "=" + ",".join(v_quote))
|
|
253
|
+
l_params.append("{}={}".format(k, ",".join(map(_quote_oa_value, v))))
|
|
241
254
|
elif k in ["filter", "sort"]:
|
|
242
|
-
l_params.append(k
|
|
255
|
+
l_params.append(f"{k}={_flatten_kv(v)}")
|
|
243
256
|
else:
|
|
244
|
-
l_params.append(k
|
|
257
|
+
l_params.append(f"{k}={_quote_oa_value(v)}")
|
|
245
258
|
|
|
246
259
|
if l_params:
|
|
247
|
-
return self._full_collection_name()
|
|
260
|
+
return "{}?{}".format(self._full_collection_name(), "&".join(l_params))
|
|
248
261
|
|
|
249
262
|
return self._full_collection_name()
|
|
250
263
|
|
|
@@ -294,6 +307,8 @@ class BaseOpenAlex:
|
|
|
294
307
|
|
|
295
308
|
def paginate(self, method="cursor", page=1, per_page=None, cursor="*", n_max=10000):
|
|
296
309
|
if method == "cursor":
|
|
310
|
+
if self.params.get("sample"):
|
|
311
|
+
raise ValueError("method should be 'page' when using sample")
|
|
297
312
|
value = cursor
|
|
298
313
|
elif method == "page":
|
|
299
314
|
value = page
|
|
@@ -464,50 +479,31 @@ class autocompletes(BaseOpenAlex):
|
|
|
464
479
|
|
|
465
480
|
def __getitem__(self, key):
|
|
466
481
|
return self._get_from_url(
|
|
467
|
-
config.openalex_url
|
|
482
|
+
f"{config.openalex_url}/autocomplete?q={key}", return_meta=False
|
|
468
483
|
)
|
|
469
484
|
|
|
470
485
|
|
|
471
|
-
def Venue(*args, **kwargs): # deprecated
|
|
472
|
-
# warn about deprecation
|
|
473
|
-
warnings.warn(
|
|
474
|
-
"Venue is deprecated. Use Sources instead.",
|
|
475
|
-
DeprecationWarning,
|
|
476
|
-
stacklevel=2,
|
|
477
|
-
)
|
|
478
|
-
|
|
479
|
-
return Source(*args, **kwargs)
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
def Venues(*args, **kwargs): # deprecated
|
|
483
|
-
# warn about deprecation
|
|
484
|
-
warnings.warn(
|
|
485
|
-
"Venues is deprecated. Use Sources instead.",
|
|
486
|
-
DeprecationWarning,
|
|
487
|
-
stacklevel=2,
|
|
488
|
-
)
|
|
489
|
-
|
|
490
|
-
return Sources(*args, **kwargs)
|
|
491
|
-
|
|
492
|
-
|
|
493
486
|
class Concept(OpenAlexEntity):
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
487
|
+
def __init__(self, *args, **kwargs):
|
|
488
|
+
warnings.warn(
|
|
489
|
+
"Concept is deprecated by OpenAlex and replaced by topics.",
|
|
490
|
+
DeprecationWarning,
|
|
491
|
+
stacklevel=2,
|
|
492
|
+
)
|
|
493
|
+
super().__init__(*args, **kwargs)
|
|
500
494
|
|
|
501
495
|
|
|
502
496
|
class Concepts(BaseOpenAlex):
|
|
503
|
-
# warn about deprecation
|
|
504
|
-
warnings.warn(
|
|
505
|
-
"Concepts is deprecated by OpenAlex and replaced by topics.",
|
|
506
|
-
DeprecationWarning,
|
|
507
|
-
stacklevel=2,
|
|
508
|
-
)
|
|
509
497
|
resource_class = Concept
|
|
510
498
|
|
|
499
|
+
def __init__(self, *args, **kwargs):
|
|
500
|
+
warnings.warn(
|
|
501
|
+
"Concepts is deprecated by OpenAlex and replaced by topics.",
|
|
502
|
+
DeprecationWarning,
|
|
503
|
+
stacklevel=2,
|
|
504
|
+
)
|
|
505
|
+
super().__init__(*args, **kwargs)
|
|
506
|
+
|
|
511
507
|
|
|
512
508
|
def autocomplete(s):
|
|
513
509
|
"""autocomplete with any type of entity"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyalex
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.1
|
|
4
4
|
Summary: Python interface to the OpenAlex database
|
|
5
5
|
Author-email: Jonathan de Bruin <jonathandebruinos@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -123,7 +123,7 @@ Works()["W2741809807"]["open_access"]
|
|
|
123
123
|
{'is_oa': True, 'oa_status': 'gold', 'oa_url': 'https://doi.org/10.7717/peerj.4375'}
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
The previous works also for Authors,
|
|
126
|
+
The previous works also for Authors, Sources, Institutions, Concepts and Topics
|
|
127
127
|
|
|
128
128
|
```python
|
|
129
129
|
Authors()["A2887243803"]
|
|
@@ -378,6 +378,18 @@ Works()["W2023271753"].ngrams()
|
|
|
378
378
|
```
|
|
379
379
|
|
|
380
380
|
|
|
381
|
+
### Serialize
|
|
382
|
+
|
|
383
|
+
All results from PyAlex can be serialized. For example, save the results to a JSON file:
|
|
384
|
+
|
|
385
|
+
```python
|
|
386
|
+
with open(Path("works.json"), "w") as f:
|
|
387
|
+
json.dump(Works().get(), f)
|
|
388
|
+
|
|
389
|
+
with open(Path("works.json")) as f:
|
|
390
|
+
works = [Work(w) for w in json.load(f)]
|
|
391
|
+
```
|
|
392
|
+
|
|
381
393
|
## Code snippets
|
|
382
394
|
|
|
383
395
|
A list of awesome use cases of the OpenAlex dataset.
|
|
@@ -441,9 +453,6 @@ pyalex.config.api_key = "<MY_KEY>"
|
|
|
441
453
|
|
|
442
454
|
## Alternatives
|
|
443
455
|
|
|
444
|
-
[Diophila](https://github.com/smierz/diophila) is a nice Python wrapper for OpenAlex. It takes a slightly
|
|
445
|
-
different approach, especially interesting to those who don't like the pipe operations.
|
|
446
|
-
|
|
447
456
|
R users can use the excellent [OpenAlexR](https://github.com/ropensci/openalexR) library.
|
|
448
457
|
|
|
449
458
|
## License
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
pyalex/__init__.py,sha256=52XK8om6IVD1Yiq_HYOCR6PUY56sPRHutGM03NOrGMQ,1467
|
|
2
|
+
pyalex/_version.py,sha256=po5_rvCFTU8xU9IC56wyK0-zfBgz_U4xX6CO2mv9Mzs,413
|
|
3
|
+
pyalex/api.py,sha256=JTOx0P037IOhhYVAigQO5uPsd1HMQC-SM3wny0_52uU,13236
|
|
4
|
+
pyalex-0.15.1.dist-info/LICENSE,sha256=Mhf5MImRYP06a1EPVJCpkpTstOOEfGajN3T_Fz4izMg,1074
|
|
5
|
+
pyalex-0.15.1.dist-info/METADATA,sha256=JSa8cKcjZUZ-lDo28WyuFN1GHEEWUHWLvSLaKh3IP10,13859
|
|
6
|
+
pyalex-0.15.1.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
|
7
|
+
pyalex-0.15.1.dist-info/top_level.txt,sha256=D0An8hWy9e0xPhTaT6K-yuJKVeVV3bYGxZ6Y-v2WXSU,7
|
|
8
|
+
pyalex-0.15.1.dist-info/RECORD,,
|
pyalex-0.14.dist-info/RECORD
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
pyalex/__init__.py,sha256=EL6oh0vQdSNyvsrxFFgmDn-P_Dgev1IYpP-WiLBxjS8,1553
|
|
2
|
-
pyalex/_version.py,sha256=lmFPHiet63Bn9h104yd9q0T6i7C2c0WCbizqrpAtSuk,408
|
|
3
|
-
pyalex/api.py,sha256=whUv8TbnW968wlR8U4O-lWsaFHRgW0Ham0cznbR3Zlc,13212
|
|
4
|
-
pyalex-0.14.dist-info/LICENSE,sha256=Mhf5MImRYP06a1EPVJCpkpTstOOEfGajN3T_Fz4izMg,1074
|
|
5
|
-
pyalex-0.14.dist-info/METADATA,sha256=3bjn78df3VlosFCcseDGs5tfTUIAgCStI_uGjqHT69w,13777
|
|
6
|
-
pyalex-0.14.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
7
|
-
pyalex-0.14.dist-info/top_level.txt,sha256=D0An8hWy9e0xPhTaT6K-yuJKVeVV3bYGxZ6Y-v2WXSU,7
|
|
8
|
-
pyalex-0.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|