pyalex 0.13__py3-none-any.whl → 0.15__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 +18 -4
- pyalex/_version.py +2 -2
- pyalex/api.py +100 -33
- {pyalex-0.13.dist-info → pyalex-0.15.dist-info}/METADATA +47 -13
- pyalex-0.15.dist-info/RECORD +8 -0
- {pyalex-0.13.dist-info → pyalex-0.15.dist-info}/WHEEL +1 -1
- pyalex-0.13.dist-info/RECORD +0 -8
- {pyalex-0.13.dist-info → pyalex-0.15.dist-info}/LICENSE +0 -0
- {pyalex-0.13.dist-info → pyalex-0.15.dist-info}/top_level.txt +0 -0
pyalex/__init__.py
CHANGED
|
@@ -9,6 +9,10 @@ from pyalex.api import Author
|
|
|
9
9
|
from pyalex.api import Authors
|
|
10
10
|
from pyalex.api import Concept
|
|
11
11
|
from pyalex.api import Concepts
|
|
12
|
+
from pyalex.api import Domain
|
|
13
|
+
from pyalex.api import Domains
|
|
14
|
+
from pyalex.api import Field
|
|
15
|
+
from pyalex.api import Fields
|
|
12
16
|
from pyalex.api import Funder
|
|
13
17
|
from pyalex.api import Funders
|
|
14
18
|
from pyalex.api import Institution
|
|
@@ -19,10 +23,13 @@ from pyalex.api import Publisher
|
|
|
19
23
|
from pyalex.api import Publishers
|
|
20
24
|
from pyalex.api import Source
|
|
21
25
|
from pyalex.api import Sources
|
|
22
|
-
from pyalex.api import
|
|
23
|
-
from pyalex.api import
|
|
26
|
+
from pyalex.api import Subfield
|
|
27
|
+
from pyalex.api import Subfields
|
|
28
|
+
from pyalex.api import Topic
|
|
29
|
+
from pyalex.api import Topics
|
|
24
30
|
from pyalex.api import Work
|
|
25
31
|
from pyalex.api import Works
|
|
32
|
+
from pyalex.api import autocomplete
|
|
26
33
|
from pyalex.api import config
|
|
27
34
|
from pyalex.api import invert_abstract
|
|
28
35
|
|
|
@@ -37,14 +44,21 @@ __all__ = [
|
|
|
37
44
|
"Funders",
|
|
38
45
|
"Publishers",
|
|
39
46
|
"Publisher",
|
|
40
|
-
"Venues",
|
|
41
|
-
"Venue",
|
|
42
47
|
"Institutions",
|
|
43
48
|
"Institution",
|
|
44
49
|
"Concepts",
|
|
45
50
|
"Concept",
|
|
51
|
+
"Domains",
|
|
52
|
+
"Domain",
|
|
53
|
+
"Fields",
|
|
54
|
+
"Field",
|
|
55
|
+
"Subfields",
|
|
56
|
+
"Subfield",
|
|
57
|
+
"Topics",
|
|
58
|
+
"Topic",
|
|
46
59
|
"People",
|
|
47
60
|
"Journals",
|
|
61
|
+
"autocomplete",
|
|
48
62
|
"config",
|
|
49
63
|
"invert_abstract",
|
|
50
64
|
]
|
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="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):
|
|
@@ -198,7 +211,12 @@ class BaseOpenAlex:
|
|
|
198
211
|
return self.filter(openalex_id="|".join(record_list)).get()
|
|
199
212
|
|
|
200
213
|
def _full_collection_name(self):
|
|
201
|
-
|
|
214
|
+
if self.params is not None and "q" in self.params.keys():
|
|
215
|
+
return (
|
|
216
|
+
f"{config.openalex_url}/autocomplete/{self.__class__.__name__.lower()}"
|
|
217
|
+
)
|
|
218
|
+
else:
|
|
219
|
+
return f"{config.openalex_url}/{self.__class__.__name__.lower()}"
|
|
202
220
|
|
|
203
221
|
def __getattr__(self, key):
|
|
204
222
|
if key == "groupby":
|
|
@@ -219,7 +237,7 @@ class BaseOpenAlex:
|
|
|
219
237
|
return self._get_multi_items(record_id)
|
|
220
238
|
|
|
221
239
|
return self._get_from_url(
|
|
222
|
-
self._full_collection_name()
|
|
240
|
+
f"{self._full_collection_name()}/{record_id}", return_meta=False
|
|
223
241
|
)
|
|
224
242
|
|
|
225
243
|
@property
|
|
@@ -232,15 +250,14 @@ class BaseOpenAlex:
|
|
|
232
250
|
if v is None:
|
|
233
251
|
pass
|
|
234
252
|
elif isinstance(v, list):
|
|
235
|
-
|
|
236
|
-
l_params.append(k + "=" + ",".join(v_quote))
|
|
253
|
+
l_params.append("{}={}".format(k, ",".join(map(_quote_oa_value, v))))
|
|
237
254
|
elif k in ["filter", "sort"]:
|
|
238
|
-
l_params.append(k
|
|
255
|
+
l_params.append(f"{k}={_flatten_kv(v)}")
|
|
239
256
|
else:
|
|
240
|
-
l_params.append(k
|
|
257
|
+
l_params.append(f"{k}={_quote_oa_value(v)}")
|
|
241
258
|
|
|
242
259
|
if l_params:
|
|
243
|
-
return self._full_collection_name()
|
|
260
|
+
return "{}?{}".format(self._full_collection_name(), "&".join(l_params))
|
|
244
261
|
|
|
245
262
|
return self._full_collection_name()
|
|
246
263
|
|
|
@@ -286,11 +303,12 @@ class BaseOpenAlex:
|
|
|
286
303
|
self._add_params("per-page", per_page)
|
|
287
304
|
self._add_params("page", page)
|
|
288
305
|
self._add_params("cursor", cursor)
|
|
289
|
-
|
|
290
306
|
return self._get_from_url(self.url, return_meta=return_meta)
|
|
291
307
|
|
|
292
308
|
def paginate(self, method="cursor", page=1, per_page=None, cursor="*", n_max=10000):
|
|
293
309
|
if method == "cursor":
|
|
310
|
+
if self.params.get("sample"):
|
|
311
|
+
raise ValueError("method should be 'page' when using sample")
|
|
294
312
|
value = cursor
|
|
295
313
|
elif method == "page":
|
|
296
314
|
value = page
|
|
@@ -343,6 +361,11 @@ class BaseOpenAlex:
|
|
|
343
361
|
self._add_params("select", s)
|
|
344
362
|
return self
|
|
345
363
|
|
|
364
|
+
def autocomplete(self, s, **kwargs):
|
|
365
|
+
"""autocomplete the string s, for a specific type of entity"""
|
|
366
|
+
self._add_params("q", s)
|
|
367
|
+
return self.get(**kwargs)
|
|
368
|
+
|
|
346
369
|
|
|
347
370
|
# The API
|
|
348
371
|
|
|
@@ -397,12 +420,36 @@ class Institutions(BaseOpenAlex):
|
|
|
397
420
|
resource_class = Institution
|
|
398
421
|
|
|
399
422
|
|
|
400
|
-
class
|
|
423
|
+
class Domain(OpenAlexEntity):
|
|
401
424
|
pass
|
|
402
425
|
|
|
403
426
|
|
|
404
|
-
class
|
|
405
|
-
resource_class =
|
|
427
|
+
class Domains(BaseOpenAlex):
|
|
428
|
+
resource_class = Domain
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
class Field(OpenAlexEntity):
|
|
432
|
+
pass
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
class Fields(BaseOpenAlex):
|
|
436
|
+
resource_class = Field
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
class Subfield(OpenAlexEntity):
|
|
440
|
+
pass
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
class Subfields(BaseOpenAlex):
|
|
444
|
+
resource_class = Subfield
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
class Topic(OpenAlexEntity):
|
|
448
|
+
pass
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
class Topics(BaseOpenAlex):
|
|
452
|
+
resource_class = Topic
|
|
406
453
|
|
|
407
454
|
|
|
408
455
|
class Publisher(OpenAlexEntity):
|
|
@@ -421,26 +468,46 @@ class Funders(BaseOpenAlex):
|
|
|
421
468
|
resource_class = Funder
|
|
422
469
|
|
|
423
470
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
warnings.warn(
|
|
427
|
-
"Venue is deprecated. Use Sources instead.",
|
|
428
|
-
DeprecationWarning,
|
|
429
|
-
stacklevel=2,
|
|
430
|
-
)
|
|
471
|
+
class Autocomplete(OpenAlexEntity):
|
|
472
|
+
pass
|
|
431
473
|
|
|
432
|
-
return Source(*args, **kwargs)
|
|
433
474
|
|
|
475
|
+
class autocompletes(BaseOpenAlex):
|
|
476
|
+
"""Class to autocomplete without being based on the type of entity"""
|
|
477
|
+
|
|
478
|
+
resource_class = Autocomplete
|
|
479
|
+
|
|
480
|
+
def __getitem__(self, key):
|
|
481
|
+
return self._get_from_url(
|
|
482
|
+
f"{config.openalex_url}/autocomplete?q={key}", return_meta=False
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class Concept(OpenAlexEntity):
|
|
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)
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
class Concepts(BaseOpenAlex):
|
|
497
|
+
resource_class = Concept
|
|
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)
|
|
434
506
|
|
|
435
|
-
def Venues(*args, **kwargs): # deprecated
|
|
436
|
-
# warn about deprecation
|
|
437
|
-
warnings.warn(
|
|
438
|
-
"Venues is deprecated. Use Sources instead.",
|
|
439
|
-
DeprecationWarning,
|
|
440
|
-
stacklevel=2,
|
|
441
|
-
)
|
|
442
507
|
|
|
443
|
-
|
|
508
|
+
def autocomplete(s):
|
|
509
|
+
"""autocomplete with any type of entity"""
|
|
510
|
+
return autocompletes()[s]
|
|
444
511
|
|
|
445
512
|
|
|
446
513
|
# aliases
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyalex
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15
|
|
4
4
|
Summary: Python interface to the OpenAlex database
|
|
5
5
|
Author-email: Jonathan de Bruin <jonathandebruinos@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -30,8 +30,6 @@ Requires-Dist: pytest-xdist ; extra == 'test'
|
|
|
30
30
|
|
|
31
31
|
 [](https://zenodo.org/badge/latestdoi/557541347)
|
|
32
32
|
|
|
33
|
-
[](https://securityscorecards.dev/viewer/?uri=github.com/J535D165/pyalex)
|
|
34
|
-
|
|
35
33
|
|
|
36
34
|
PyAlex is a Python library for [OpenAlex](https://openalex.org/). OpenAlex is
|
|
37
35
|
an index of hundreds of millions of interconnected scholarly papers, authors,
|
|
@@ -49,7 +47,7 @@ The following features of OpenAlex are currently supported by PyAlex:
|
|
|
49
47
|
- [x] Select fields
|
|
50
48
|
- [x] Sample
|
|
51
49
|
- [x] Pagination
|
|
52
|
-
- [
|
|
50
|
+
- [x] Autocomplete endpoint
|
|
53
51
|
- [x] N-grams
|
|
54
52
|
- [x] Authentication
|
|
55
53
|
|
|
@@ -71,10 +69,10 @@ pip install pyalex
|
|
|
71
69
|
|
|
72
70
|
## Getting started
|
|
73
71
|
|
|
74
|
-
PyAlex offers support for all [Entity Objects](https://docs.openalex.org/api-entities/entities-overview): [Works](https://docs.openalex.org/api-entities/works), [Authors](https://docs.openalex.org/api-entities/authors), [Sources](https://docs.openalex.org/api-entities/sourcese), [Institutions](https://docs.openalex.org/api-entities/institutions), [
|
|
72
|
+
PyAlex offers support for all [Entity Objects](https://docs.openalex.org/api-entities/entities-overview): [Works](https://docs.openalex.org/api-entities/works), [Authors](https://docs.openalex.org/api-entities/authors), [Sources](https://docs.openalex.org/api-entities/sourcese), [Institutions](https://docs.openalex.org/api-entities/institutions), [Topics](https://docs.openalex.org/api-entities/topics), [Publishers](https://docs.openalex.org/api-entities/publishers), and [Funders](https://docs.openalex.org/api-entities/funders).
|
|
75
73
|
|
|
76
74
|
```python
|
|
77
|
-
from pyalex import Works, Authors, Sources, Institutions,
|
|
75
|
+
from pyalex import Works, Authors, Sources, Institutions, Topics, Publishers, Funders
|
|
78
76
|
```
|
|
79
77
|
|
|
80
78
|
### The polite pool
|
|
@@ -89,9 +87,21 @@ import pyalex
|
|
|
89
87
|
pyalex.config.email = "mail@example.com"
|
|
90
88
|
```
|
|
91
89
|
|
|
90
|
+
### Max retries
|
|
91
|
+
|
|
92
|
+
By default, PyAlex will raise an error at the first failure when querying the OpenAlex API. You can set `max_retries` to a number higher than 0 to allow PyAlex to retry when an error occurs. `retry_backoff_factor` is related to the delay between two retry, and `retry_http_codes` are the HTTP error codes that should trigger a retry.
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from pyalex import config
|
|
96
|
+
|
|
97
|
+
config.max_retries = 0
|
|
98
|
+
config.retry_backoff_factor = 0.1
|
|
99
|
+
config.retry_http_codes = [429, 500, 503]
|
|
100
|
+
```
|
|
101
|
+
|
|
92
102
|
### Get single entity
|
|
93
103
|
|
|
94
|
-
Get a single Work, Author, Source, Institution, Concept, Publisher or Funder from OpenAlex by the
|
|
104
|
+
Get a single Work, Author, Source, Institution, Concept, Topic, Publisher or Funder from OpenAlex by the
|
|
95
105
|
OpenAlex ID, or by DOI or ROR.
|
|
96
106
|
|
|
97
107
|
```python
|
|
@@ -113,7 +123,7 @@ Works()["W2741809807"]["open_access"]
|
|
|
113
123
|
{'is_oa': True, 'oa_status': 'gold', 'oa_url': 'https://doi.org/10.7717/peerj.4375'}
|
|
114
124
|
```
|
|
115
125
|
|
|
116
|
-
The previous works also for Authors,
|
|
126
|
+
The previous works also for Authors, Sources, Institutions, Concepts and Topics
|
|
117
127
|
|
|
118
128
|
```python
|
|
119
129
|
Authors()["A2887243803"]
|
|
@@ -122,7 +132,7 @@ Authors()["https://orcid.org/0000-0002-4297-0502"] # same
|
|
|
122
132
|
|
|
123
133
|
#### Get random
|
|
124
134
|
|
|
125
|
-
Get a [random Work, Author, Source, Institution, Concept, Publisher or Funder](https://docs.openalex.org/how-to-use-the-api/get-single-entities/random-result).
|
|
135
|
+
Get a [random Work, Author, Source, Institution, Concept, Topic, Publisher or Funder](https://docs.openalex.org/how-to-use-the-api/get-single-entities/random-result).
|
|
126
136
|
|
|
127
137
|
```python
|
|
128
138
|
Works().random()
|
|
@@ -130,6 +140,7 @@ Authors().random()
|
|
|
130
140
|
Sources().random()
|
|
131
141
|
Institutions().random()
|
|
132
142
|
Concepts().random()
|
|
143
|
+
Topics().random()
|
|
133
144
|
Publishers().random()
|
|
134
145
|
Funders().random()
|
|
135
146
|
```
|
|
@@ -172,7 +183,7 @@ Works().count()
|
|
|
172
183
|
For lists of entities, you can return the result as well as the metadata. By default, only the results are returned.
|
|
173
184
|
|
|
174
185
|
```python
|
|
175
|
-
results, meta =
|
|
186
|
+
results, meta = Topics().get(return_meta=True)
|
|
176
187
|
```
|
|
177
188
|
|
|
178
189
|
```python
|
|
@@ -331,6 +342,32 @@ for page in pager:
|
|
|
331
342
|
```
|
|
332
343
|
|
|
333
344
|
|
|
345
|
+
### Autocomplete
|
|
346
|
+
|
|
347
|
+
OpenAlex reference: [Autocomplete entities](https://docs.openalex.org/how-to-use-the-api/get-lists-of-entities/autocomplete-entities).
|
|
348
|
+
|
|
349
|
+
Autocomplete a string:
|
|
350
|
+
```python
|
|
351
|
+
from pyalex import autocomplete
|
|
352
|
+
|
|
353
|
+
autocomplete("stockholm resilience centre")
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Autocomplete a string to get a specific type of entities:
|
|
357
|
+
```python
|
|
358
|
+
from pyalex import Institutions
|
|
359
|
+
|
|
360
|
+
Institutions().autocomplete("stockholm resilience centre")
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
You can also use the filters to autocomplete:
|
|
364
|
+
```python
|
|
365
|
+
from pyalex import Works
|
|
366
|
+
|
|
367
|
+
r = Works().filter(publication_year=2023).autocomplete("planetary boundaries")
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
|
|
334
371
|
### Get N-grams
|
|
335
372
|
|
|
336
373
|
OpenAlex reference: [Get N-grams](https://docs.openalex.org/api-entities/works/get-n-grams).
|
|
@@ -404,9 +441,6 @@ pyalex.config.api_key = "<MY_KEY>"
|
|
|
404
441
|
|
|
405
442
|
## Alternatives
|
|
406
443
|
|
|
407
|
-
[Diophila](https://github.com/smierz/diophila) is a nice Python wrapper for OpenAlex. It takes a slightly
|
|
408
|
-
different approach, especially interesting to those who don't like the pipe operations.
|
|
409
|
-
|
|
410
444
|
R users can use the excellent [OpenAlexR](https://github.com/ropensci/openalexR) library.
|
|
411
445
|
|
|
412
446
|
## License
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
pyalex/__init__.py,sha256=52XK8om6IVD1Yiq_HYOCR6PUY56sPRHutGM03NOrGMQ,1467
|
|
2
|
+
pyalex/_version.py,sha256=poZz4oZoUd1b8WrBvqHJC0SHzGSqhHsFiUSMJDd_Hcw,408
|
|
3
|
+
pyalex/api.py,sha256=IhqRtjy5LtlYffjaHWxRBmKPSIaaXbGqt8qYhKo9YbE,13235
|
|
4
|
+
pyalex-0.15.dist-info/LICENSE,sha256=Mhf5MImRYP06a1EPVJCpkpTstOOEfGajN3T_Fz4izMg,1074
|
|
5
|
+
pyalex-0.15.dist-info/METADATA,sha256=pkDIkcjUnuqePUCdNdXZeRouKh9p16s5g0N0rcYhXxc,13583
|
|
6
|
+
pyalex-0.15.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
|
|
7
|
+
pyalex-0.15.dist-info/top_level.txt,sha256=D0An8hWy9e0xPhTaT6K-yuJKVeVV3bYGxZ6Y-v2WXSU,7
|
|
8
|
+
pyalex-0.15.dist-info/RECORD,,
|
pyalex-0.13.dist-info/RECORD
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
pyalex/__init__.py,sha256=UrEW9s9NbULtmmnYUUgfbrDujleV8XQLiMRYGdRnm9M,1137
|
|
2
|
-
pyalex/_version.py,sha256=4Ti_UJ2UR2LyAc9zW9aeUVpFeq-DXxy65V2wynOuCi0,408
|
|
3
|
-
pyalex/api.py,sha256=vefNV54OG1daTrKHSDq9Jcy4JhiYi0HSP3GsEzA47uk,11633
|
|
4
|
-
pyalex-0.13.dist-info/LICENSE,sha256=Mhf5MImRYP06a1EPVJCpkpTstOOEfGajN3T_Fz4izMg,1074
|
|
5
|
-
pyalex-0.13.dist-info/METADATA,sha256=vMMbnCUgNUaw99XlqucQZMfZsOZWrXXJOmRpPJsTdSU,12916
|
|
6
|
-
pyalex-0.13.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
|
|
7
|
-
pyalex-0.13.dist-info/top_level.txt,sha256=D0An8hWy9e0xPhTaT6K-yuJKVeVV3bYGxZ6Y-v2WXSU,7
|
|
8
|
-
pyalex-0.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|