sxs 2024.0.1__py3-none-any.whl → 2024.0.3__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.
- sxs/__version__.py +1 -1
- sxs/juliapkg.json +1 -1
- sxs/utilities/__init__.py +1 -0
- sxs/utilities/inspire.py +126 -202
- {sxs-2024.0.1.dist-info → sxs-2024.0.3.dist-info}/METADATA +1 -1
- {sxs-2024.0.1.dist-info → sxs-2024.0.3.dist-info}/RECORD +8 -8
- {sxs-2024.0.1.dist-info → sxs-2024.0.3.dist-info}/WHEEL +0 -0
- {sxs-2024.0.1.dist-info → sxs-2024.0.3.dist-info}/licenses/LICENSE +0 -0
sxs/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2024.0.
|
|
1
|
+
__version__ = "2024.0.3"
|
sxs/juliapkg.json
CHANGED
sxs/utilities/__init__.py
CHANGED
sxs/utilities/inspire.py
CHANGED
|
@@ -1,229 +1,153 @@
|
|
|
1
1
|
"""Search the INSPIRE database
|
|
2
2
|
|
|
3
|
-
Documentation can be found here: <https://
|
|
3
|
+
Documentation can be found here: <https://github.com/inspirehep/rest-api-doc>
|
|
4
4
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
import warnings
|
|
8
8
|
|
|
9
|
-
api_url = "https://inspirehep.net/
|
|
9
|
+
api_url = "https://inspirehep.net/api/{record_type}"
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
def inspire2doi(inspire_bibtex_key, raise_exceptions=False):
|
|
13
|
+
try:
|
|
14
|
+
result = query(inspire_bibtex_key, fields="dois.value,arxiv_eprints")
|
|
15
|
+
except KeyboardInterrupt:
|
|
16
|
+
raise
|
|
17
|
+
except Exception as e:
|
|
18
|
+
warnings.warn(f"Error querying for INSPIRE key {inspire_bibtex_key}")
|
|
19
|
+
if raise_exceptions:
|
|
20
|
+
raise e
|
|
21
|
+
else:
|
|
22
|
+
if not result:
|
|
23
|
+
warnings.warn(f"No entry found for INSPIRE key {inspire_bibtex_key}")
|
|
24
|
+
if raise_exceptions:
|
|
25
|
+
raise ValueError(f"No entry found for INSPIRE key {inspire_bibtex_key}")
|
|
26
|
+
else:
|
|
27
|
+
try:
|
|
28
|
+
return result[0]["metadata"]["dois"][0]["value"]
|
|
29
|
+
except Exception as e:
|
|
30
|
+
# DOI not present; INSPIRE only has an arXiv number, so we'll convert to an arXiv DOI
|
|
31
|
+
try:
|
|
32
|
+
eprint_value = result[0]["metadata"]["arxiv_eprints"][0]["value"]
|
|
33
|
+
# https://info-arxiv-org.proxy.library.cornell.edu/help/arxiv_identifier.html
|
|
34
|
+
# says that identifiers starting with 9107 to 0703 need their category included
|
|
35
|
+
if eprint_value.startswith("9") or int(eprint_value[:4])<704:
|
|
36
|
+
category = result[0]["metadata"]["arxiv_eprints"][0]["categories"][0]
|
|
37
|
+
return f"10.48550/arXiv.{category}/{eprint_value}"
|
|
38
|
+
else:
|
|
39
|
+
return f"10.48550/arXiv.{eprint_value}"
|
|
40
|
+
except Exception as e:
|
|
41
|
+
warnings.warn(f"Unexpected result format for INSPIRE key {inspire_bibtex_key}: \n{result}")
|
|
42
|
+
if raise_exceptions:
|
|
43
|
+
raise e
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def query(
|
|
47
|
+
query,
|
|
48
|
+
sort="mostrecent",
|
|
49
|
+
page=1,
|
|
50
|
+
size=1000,
|
|
51
|
+
fields=None,
|
|
52
|
+
page_limit=10,
|
|
53
|
+
record_type="literature"
|
|
54
|
+
):
|
|
55
|
+
"""Fetch records from the INSPIRE API.
|
|
18
56
|
|
|
19
57
|
Parameters
|
|
20
58
|
----------
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Long responses are split into several chunks. To access subsequent chunks
|
|
47
|
-
specify the record offset with this parameter.
|
|
48
|
-
|
|
59
|
+
query : str
|
|
60
|
+
The search query. For details, see
|
|
61
|
+
https://github.com/inspirehep/rest-api-doc/tree/master#search-query
|
|
62
|
+
fields : str, optional
|
|
63
|
+
The fields to retrieve from INSPIRE. This can be a
|
|
64
|
+
comma-separated list of field names. For example, to
|
|
65
|
+
retrieve the list of DOIs: "dois.value". Other options at
|
|
66
|
+
https://inspire-schemas.readthedocs.io/en/latest/schemas/elements/reference.html
|
|
67
|
+
Note that other fields will also be returned for each record,
|
|
68
|
+
even when you just ask for one — including "id", "links",
|
|
69
|
+
"metadata", "created", and "updated". The default value of
|
|
70
|
+
None will return all fields.
|
|
71
|
+
sort : str, optional
|
|
72
|
+
The sorting order. Default is "mostrecent".
|
|
73
|
+
size : int, optional
|
|
74
|
+
The number of records per page. Default is 1000.
|
|
75
|
+
page : int, optional
|
|
76
|
+
The starting page number. Default is 1.
|
|
77
|
+
page_limit : int, optional
|
|
78
|
+
Optional limit to the number of pages to collect.
|
|
79
|
+
record_type : str, optional
|
|
80
|
+
The type of record to fetch (e.g., "literature"). Default is
|
|
81
|
+
"literature". Other options can be found here:
|
|
82
|
+
https://github.com/inspirehep/rest-api-doc/tree/master#obtaining-a-record
|
|
83
|
+
|
|
49
84
|
Returns
|
|
50
85
|
-------
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
is only one. Each result will be a dictionary mapping the requested
|
|
54
|
-
'output_tags' to their corresponding values.
|
|
86
|
+
list
|
|
87
|
+
The JSON response from the API.
|
|
55
88
|
|
|
56
89
|
Raises
|
|
57
90
|
------
|
|
58
91
|
requests.exceptions.HTTPError :
|
|
59
|
-
If the HTTP request to INSPIRE failed
|
|
92
|
+
If the HTTP request to INSPIRE failed
|
|
60
93
|
|
|
61
94
|
"""
|
|
62
95
|
import sys
|
|
63
96
|
import requests
|
|
64
|
-
|
|
97
|
+
from requests.adapters import HTTPAdapter
|
|
98
|
+
from urllib3.util.retry import Retry
|
|
99
|
+
|
|
100
|
+
session = requests.Session()
|
|
101
|
+
collected_results = []
|
|
102
|
+
|
|
103
|
+
## Retry automatically on certain types of errors
|
|
104
|
+
retry = Retry(
|
|
105
|
+
total=10,
|
|
106
|
+
backoff_factor=0.1,
|
|
107
|
+
status_forcelist=[
|
|
108
|
+
413, # Request Entity Too Large
|
|
109
|
+
429, # Too Many Requests
|
|
110
|
+
500, # Internal Server Error
|
|
111
|
+
502, # Bad Gateway
|
|
112
|
+
503, # Service Unavailable
|
|
113
|
+
504, # Gateway Timeout
|
|
114
|
+
],
|
|
115
|
+
)
|
|
116
|
+
adapter = HTTPAdapter(max_retries=retry)
|
|
117
|
+
session.mount("https://", adapter)
|
|
118
|
+
|
|
119
|
+
url = api_url.format(record_type=record_type)
|
|
65
120
|
params = {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
params['ot'] = output_tags
|
|
71
|
-
if records_in_groups_of is not None:
|
|
72
|
-
params['rg'] = records_in_groups_of
|
|
73
|
-
if jump_to_records is not None:
|
|
74
|
-
params['jrec'] = jump_to_records
|
|
75
|
-
|
|
76
|
-
r = requests.get(api_url, params=params)
|
|
77
|
-
if r.status_code != 200:
|
|
78
|
-
print('An error occurred when trying to access <{0}>.'.format(api_url), file=sys.stderr)
|
|
79
|
-
try:
|
|
80
|
-
print(r.json(), file=sys.stderr)
|
|
81
|
-
except:
|
|
82
|
-
pass
|
|
83
|
-
r.raise_for_status()
|
|
84
|
-
raise RuntimeError() # Will only happen if the response was not strictly an error
|
|
85
|
-
return r.json()
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def extract_bibtex_key(system_control_numbers):
|
|
89
|
-
"""Get bibtex key from 'system_control_numbers' field
|
|
90
|
-
|
|
91
|
-
Unfortunately, this seems to be the only way to get the bibtex key. I have
|
|
92
|
-
seen suggestions around the github issues for inspirehep/invenio that this
|
|
93
|
-
should always be present
|
|
94
|
-
|
|
95
|
-
"""
|
|
96
|
-
if isinstance(system_control_numbers, dict):
|
|
97
|
-
system_control_numbers = [system_control_numbers,]
|
|
98
|
-
bibtex_keys = [number.get('value', '') for number in system_control_numbers
|
|
99
|
-
if number.get('institute', '') in ['INSPIRETeX', 'SPIRESTeX']]
|
|
100
|
-
bibtex_keys = [key for key in bibtex_keys if key]
|
|
101
|
-
if not bibtex_keys:
|
|
102
|
-
return ''
|
|
103
|
-
return bibtex_keys[0]
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def extract_doi(doi):
|
|
107
|
-
"""Ensure that 'doi' is a single string
|
|
108
|
-
|
|
109
|
-
Occasionally, INSPIRE returns a list of identical DOIs. This just extracts the
|
|
110
|
-
first element if it is such a list, or returns the input otherwise.
|
|
111
|
-
|
|
112
|
-
"""
|
|
113
|
-
if isinstance(doi, list) and len(doi)>0:
|
|
114
|
-
return doi[0]
|
|
115
|
-
return doi
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def extract_doi_url(doi):
|
|
119
|
-
"""Ensure that 'doi' is a single string
|
|
120
|
-
|
|
121
|
-
Occasionally, INSPIRE returns a list of identical DOIs. This just extracts the
|
|
122
|
-
first element if it is such a list, or returns the input otherwise.
|
|
123
|
-
|
|
124
|
-
"""
|
|
125
|
-
doi = extract_doi(doi)
|
|
126
|
-
if doi:
|
|
127
|
-
return 'https://dx.doi.org/' + doi
|
|
128
|
-
else:
|
|
129
|
-
return doi
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def extract_arxiv_url(system_control_numbers):
|
|
133
|
-
"""Extract any arxiv URLs from the system_control_number field
|
|
134
|
-
|
|
135
|
-
"""
|
|
136
|
-
if isinstance(system_control_numbers, dict):
|
|
137
|
-
system_control_numbers = [system_control_numbers,]
|
|
138
|
-
arxiv_urls = [
|
|
139
|
-
number['value'].replace('oai:arXiv.org:', 'https://arxiv.org/abs/')
|
|
140
|
-
for number in system_control_numbers if number.get('institute', '') == 'arXiv' and 'value' in number
|
|
141
|
-
]
|
|
142
|
-
if not arxiv_urls:
|
|
143
|
-
return ''
|
|
144
|
-
return arxiv_urls[0]
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def map_bibtex_keys_to_doi(bibtex_keys):
|
|
148
|
-
"""Map a list of INSPIRE bibtex keys to DOIs
|
|
149
|
-
|
|
150
|
-
This function queries the INSPIRE database, searching for each of the input
|
|
151
|
-
bibtex keys, and extracting the corresponding DOIs (if present on INSPIRE).
|
|
152
|
-
|
|
153
|
-
Parameter
|
|
154
|
-
---------
|
|
155
|
-
bibtex_keys : str, or list of str
|
|
156
|
-
Each string should be precisely one bibtex key from INSPIRE. Note that any
|
|
157
|
-
bibtex keys that are not found by INSPIRE are simply ignored.
|
|
158
|
-
|
|
159
|
-
Returns
|
|
160
|
-
-------
|
|
161
|
-
key_to_doi : dict
|
|
162
|
-
The output is a dictionary mapping each input bibtex key itself to the
|
|
163
|
-
corresponding DOI. These are raw DOIs; to get a URL, just append the DOI
|
|
164
|
-
to 'https://dx.doi.org/', which will resolve to the appropriate web page
|
|
165
|
-
for that DOI. Note that any record that is found by its bibtex key but
|
|
166
|
-
does not have a DOI will simply be absent from this dictionary.
|
|
167
|
-
|
|
168
|
-
Raises
|
|
169
|
-
------
|
|
170
|
-
requests.exceptions.HTTPError
|
|
171
|
-
If the HTTP request to INSPIRE failed for any reason.
|
|
172
|
-
|
|
173
|
-
"""
|
|
174
|
-
if not isinstance(bibtex_keys, list):
|
|
175
|
-
bibtex_keys = [bibtex_keys,]
|
|
176
|
-
pattern = 'find texkey ' + ' or texkey '.join(bibtex_keys)
|
|
177
|
-
output_tags = 'system_control_number,doi'
|
|
178
|
-
results = query(pattern, output_tags=output_tags)
|
|
179
|
-
mapping = {
|
|
180
|
-
bibtex_key: doi
|
|
181
|
-
for result in results
|
|
182
|
-
for bibtex_key in [extract_bibtex_key(result['system_control_number']),]
|
|
183
|
-
for doi in [extract_doi(result['doi']),]
|
|
184
|
-
if bibtex_key and doi
|
|
121
|
+
"q": query,
|
|
122
|
+
"sort": sort,
|
|
123
|
+
"size": size,
|
|
124
|
+
"page": page,
|
|
185
125
|
}
|
|
186
|
-
|
|
187
|
-
|
|
126
|
+
if fields:
|
|
127
|
+
params["fields"] = fields
|
|
128
|
+
|
|
129
|
+
while params["page"] - page <= page_limit:
|
|
130
|
+
response = session.get(url, params=params)
|
|
131
|
+
if response.status_code != 200:
|
|
132
|
+
print(f"An error occurred when trying to access <{api_url}>.", file=sys.stderr)
|
|
133
|
+
try:
|
|
134
|
+
print(response.json(), file=sys.stderr)
|
|
135
|
+
except:
|
|
136
|
+
pass
|
|
137
|
+
response.raise_for_status()
|
|
138
|
+
raise RuntimeError() # Will only happen if the response was not strictly an error
|
|
188
139
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
Failing that
|
|
195
|
-
|
|
196
|
-
Parameter
|
|
197
|
-
---------
|
|
198
|
-
bibtex_keys : str, or list of str
|
|
199
|
-
Each string should be precisely one bibtex key from INSPIRE. Note that any
|
|
200
|
-
bibtex keys that are not found by INSPIRE are simply ignored.
|
|
140
|
+
try:
|
|
141
|
+
json_response = response.json()
|
|
142
|
+
except ValueError:
|
|
143
|
+
print(f"Response from {url} does not contain valid JSON; returning early.")
|
|
144
|
+
return collected_results
|
|
201
145
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
corresponding DOI URL, arxiv URL, or other URL.
|
|
146
|
+
new_hits = json_response.get("hits", {}).get("hits", [])
|
|
147
|
+
if not new_hits:
|
|
148
|
+
break
|
|
149
|
+
collected_results.extend(new_hits)
|
|
207
150
|
|
|
208
|
-
|
|
209
|
-
------
|
|
210
|
-
requests.exceptions.HTTPError
|
|
211
|
-
If the HTTP request to INSPIRE failed for any reason.
|
|
151
|
+
params["page"] += 1
|
|
212
152
|
|
|
213
|
-
|
|
214
|
-
if not bibtex_keys:
|
|
215
|
-
return {}
|
|
216
|
-
if not isinstance(bibtex_keys, list):
|
|
217
|
-
bibtex_keys = [bibtex_keys,]
|
|
218
|
-
pattern = 'find texkey ' + ' or texkey '.join(bibtex_keys)
|
|
219
|
-
output_tags = 'system_control_number,doi'
|
|
220
|
-
results = query(pattern, output_tags=output_tags)
|
|
221
|
-
mapping = {
|
|
222
|
-
bibtex_key: (doi if doi else arxiv)
|
|
223
|
-
for result in results
|
|
224
|
-
for bibtex_key in [extract_bibtex_key(result['system_control_number']),]
|
|
225
|
-
for doi in [extract_doi_url(result['doi']),]
|
|
226
|
-
for arxiv in [extract_arxiv_url(result['system_control_number']),]
|
|
227
|
-
if bibtex_key and (bool(doi) or bool(arxiv))
|
|
228
|
-
}
|
|
229
|
-
return mapping
|
|
153
|
+
return collected_results
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sxs
|
|
3
|
-
Version: 2024.0.
|
|
3
|
+
Version: 2024.0.3
|
|
4
4
|
Summary: Interface to data produced by the Simulating eXtreme Spacetimes collaboration
|
|
5
5
|
Project-URL: Homepage, https://github.com/sxs-collaboration/sxs
|
|
6
6
|
Project-URL: Documentation, https://sxs.readthedocs.io/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
sxs/__init__.py,sha256=51_F8xiD6cdE2kIq9dPyHxNQVsp4oCvtR1wQQQ0VS2A,2577
|
|
2
|
-
sxs/__version__.py,sha256=
|
|
2
|
+
sxs/__version__.py,sha256=u5HEtv0zd-O6N1ResGvCK68T1NvJnKchyG62fEdDY5Q,25
|
|
3
3
|
sxs/handlers.py,sha256=F9XmIhjZm8df1g49fUHemc-9wWstwFUZMacY2RXCWhE,24814
|
|
4
|
-
sxs/juliapkg.json,sha256=
|
|
4
|
+
sxs/juliapkg.json,sha256=higH1UDu30K_PN6-o7lAz0j1xjgYEiCCYBAc-Iaw1Iw,178
|
|
5
5
|
sxs/time_series.py,sha256=OKaLg8tFyrtKcef7900ri-a0C6A8wKxA68KovZXvH6I,41081
|
|
6
6
|
sxs/caltechdata/__init__.py,sha256=s-RXyBiImKsQenqJIU6NAjlsjOX7f1MkIIW9rPtWYyg,14761
|
|
7
7
|
sxs/caltechdata/catalog.py,sha256=E2nystCaMZLKxTlLgfbfpGkckfkLyIzhn3YeEI3nQYc,4914
|
|
@@ -20,13 +20,13 @@ sxs/metadata/metadata.py,sha256=_vGqMUbeiN0fecJj9f9f9ex56WgSZuwwBXykUuj1_ZI,2767
|
|
|
20
20
|
sxs/simulations/__init__.py,sha256=sl-sDI5N2A03lAfzMig8Jm_Beri_v65qjlIOeGGX9XM,72
|
|
21
21
|
sxs/simulations/simulation.py,sha256=TaW1wMxbbNjyU9-DrYr65DjlAbtPLPAEoxYtIG6gSkM,21410
|
|
22
22
|
sxs/simulations/simulations.py,sha256=V1cE966NLCJ2tyowh6S1LrVTGj5KzfLx7RVaUZ5zr_I,16905
|
|
23
|
-
sxs/utilities/__init__.py,sha256=
|
|
23
|
+
sxs/utilities/__init__.py,sha256=YTyrKYkiDZV4EoT4IHXGBsc_j6RU0aK1c3HERyshVq0,4760
|
|
24
24
|
sxs/utilities/bitwise.py,sha256=G9ZNYgwDQRhq5wbDf-p2HcUqkEP_IRDiQoXW4KyU17k,13205
|
|
25
25
|
sxs/utilities/dicts.py,sha256=CCpm3upG_9SRj9gjawukSUfaJ5asF-XRG2ausEXhYyg,695
|
|
26
26
|
sxs/utilities/downloads.py,sha256=iBceWfahHKxslUuI3p2-jRDoqGhP7q2A-La9g6XtMGg,4488
|
|
27
27
|
sxs/utilities/files.py,sha256=l7SNOg0ikgqXV3bmPJdXZQMQ_XPGXVUsIJIOjDVp3Mg,4517
|
|
28
28
|
sxs/utilities/formats.py,sha256=EekLcSi-fhFdkPT7R9h10d9_0gZH4EomH5-RVQp-sg8,3867
|
|
29
|
-
sxs/utilities/inspire.py,sha256=
|
|
29
|
+
sxs/utilities/inspire.py,sha256=5F4KJ2D9qaEArl7dlhMv-K3Dym5S5oQI5RTwZXKhXRw,5298
|
|
30
30
|
sxs/utilities/monotonicity.py,sha256=YVwj3Tjew8dkpJJ9TReyuISD2ul5HJfkEJgCoiLru5Q,812
|
|
31
31
|
sxs/utilities/pretty_print.py,sha256=ZDHR3uvkzQ3Whk_eIp3BB7Abh796nqyrVsQRa68zgGc,1473
|
|
32
32
|
sxs/utilities/select.py,sha256=UgoEQIvkm8NBe6sD5O2gK0g9Pep-xvWoYQ3b7RxI-Ww,6727
|
|
@@ -78,7 +78,7 @@ sxs/zenodo/api/__init__.py,sha256=EM_eh4Q8R5E0vIfMhyIR1IYFfOBu6vA0UTasgX9gHys,21
|
|
|
78
78
|
sxs/zenodo/api/deposit.py,sha256=J4RGvGjh0cEOrN4bBZWEDcPAhNscqB2fzLlvRZ5HTHM,36948
|
|
79
79
|
sxs/zenodo/api/login.py,sha256=Yz0ytgi81_5BpDzhrS0WPMXlvU2qUaCK8yn8zxfEbko,18007
|
|
80
80
|
sxs/zenodo/api/records.py,sha256=nKkhoHZ95CTztHF9Zzaug5p7IiUCJG4Em1i-l-WqH6U,3689
|
|
81
|
-
sxs-2024.0.
|
|
82
|
-
sxs-2024.0.
|
|
83
|
-
sxs-2024.0.
|
|
84
|
-
sxs-2024.0.
|
|
81
|
+
sxs-2024.0.3.dist-info/METADATA,sha256=SfqRh4qE3Aa6DGh_MDuVXtaO6Fci0U6hVfC-XeCQsTE,9301
|
|
82
|
+
sxs-2024.0.3.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
83
|
+
sxs-2024.0.3.dist-info/licenses/LICENSE,sha256=ptVOd5m7LDM5ZF0x32cxb8c2Nd5NDmAhy6DX7xt_7VA,1080
|
|
84
|
+
sxs-2024.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|