idlib 0.0.1.dev22__py2.py3-none-any.whl → 0.0.1.dev23__py2.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.
- idlib/__init__.py +1 -1
- idlib/apis/protocols_io.py +9 -5
- idlib/core.py +54 -15
- idlib/from_oq.py +35 -3
- idlib/streams.py +12 -3
- idlib/systems/ror.py +34 -9
- idlib/systems/rrid.py +44 -0
- idlib/utils.py +6 -1
- {idlib-0.0.1.dev22.dist-info → idlib-0.0.1.dev23.dist-info}/METADATA +15 -2
- {idlib-0.0.1.dev22.dist-info → idlib-0.0.1.dev23.dist-info}/RECORD +13 -13
- {idlib-0.0.1.dev22.dist-info → idlib-0.0.1.dev23.dist-info}/WHEEL +1 -1
- {idlib-0.0.1.dev22.dist-info → idlib-0.0.1.dev23.dist-info/licenses}/LICENSE +0 -0
- {idlib-0.0.1.dev22.dist-info → idlib-0.0.1.dev23.dist-info}/top_level.txt +0 -0
idlib/__init__.py
CHANGED
idlib/apis/protocols_io.py
CHANGED
|
@@ -3,7 +3,6 @@ import sys
|
|
|
3
3
|
import pickle
|
|
4
4
|
from urllib import parse
|
|
5
5
|
from getpass import getpass
|
|
6
|
-
from ..config import auth
|
|
7
6
|
from ..utils import log as _log
|
|
8
7
|
from . import log as _log
|
|
9
8
|
|
|
@@ -68,11 +67,16 @@ def get_auth_code(url):
|
|
|
68
67
|
|
|
69
68
|
|
|
70
69
|
def get_protocols_io_auth(creds_file,
|
|
71
|
-
store_file=
|
|
72
|
-
# yes reading from the store file here at the top level
|
|
73
|
-
# increases startup time, however if it is burried then
|
|
74
|
-
# any config error is deferred until later in runtime
|
|
70
|
+
store_file=None,
|
|
75
71
|
SCOPES='readwrite'):
|
|
72
|
+
if store_file is None:
|
|
73
|
+
# since this file is imported whenever idlib is imported
|
|
74
|
+
# the time cost is prohibitive and we will just have to
|
|
75
|
+
# deal with the configuration value failing later in time
|
|
76
|
+
# by e.g. having a separate check config process
|
|
77
|
+
from ..config import auth
|
|
78
|
+
store_file = auth.get_path('protocols-io-api-store-file')
|
|
79
|
+
|
|
76
80
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
|
77
81
|
from google.auth.transport.requests import Request
|
|
78
82
|
from idlib import exceptions as exc
|
idlib/core.py
CHANGED
|
@@ -3,19 +3,45 @@ from . import exceptions as exc
|
|
|
3
3
|
from .utils import log
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
def resolution_chain(iri):
|
|
7
|
-
for head in resolution_chain_responses(iri):
|
|
6
|
+
def resolution_chain(iri, headers_fun=None):
|
|
7
|
+
for head in resolution_chain_responses(iri, headers_fun=headers_fun):
|
|
8
8
|
yield head.url
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
_user_agent_idiocy = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) Gecko/20100101 Firefox/136.0'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def try_get(s, head, headers_fun=None):
|
|
12
15
|
# see whether the server has a bad/broken support for head requests
|
|
13
16
|
# sometimes they return e.g. 400 instead of 405, and really they should
|
|
14
17
|
# just work because they work correctly with get request ...
|
|
15
18
|
head = s.get(head.url, stream=True)
|
|
19
|
+
|
|
16
20
|
if head.ok:
|
|
17
21
|
log.info(f'bad HEAD implementation {head.url}')
|
|
18
|
-
|
|
22
|
+
elif head.status_code < 500:
|
|
23
|
+
head.close()
|
|
24
|
+
headers = {'User-Agent': _user_agent_idiocy}
|
|
25
|
+
head = s.get(head.url, headers=headers, stream=True)
|
|
26
|
+
if head.ok:
|
|
27
|
+
log.info(f'bad HEAD implementation AND bad User-Agent behavior {head.url}')
|
|
28
|
+
else:
|
|
29
|
+
headers = None
|
|
30
|
+
if headers_fun is not None:
|
|
31
|
+
# headers_fun is used to ensure that e.g. auth headers
|
|
32
|
+
# are only sent to the netloc's they are for
|
|
33
|
+
headers = headers_fun(head.url)
|
|
34
|
+
if headers is not None:
|
|
35
|
+
head = s.get(head.url, headers=headers, stream=True)
|
|
36
|
+
if head.ok:
|
|
37
|
+
# we log a warning because dereferencing a public id
|
|
38
|
+
# and encountering a permission boundary is bad
|
|
39
|
+
# TODO likely need a way to fail on this condition
|
|
40
|
+
# or at least indicate that it happend in band
|
|
41
|
+
msg = f'additional headers were added for {head.url}'
|
|
42
|
+
log.warning(msg)
|
|
43
|
+
|
|
44
|
+
if not head.ok:
|
|
19
45
|
content = head.content
|
|
20
46
|
if content:
|
|
21
47
|
if head.headers['Content-Type'] == 'application/json':
|
|
@@ -29,14 +55,34 @@ def try_get(s, head):
|
|
|
29
55
|
return head
|
|
30
56
|
|
|
31
57
|
|
|
32
|
-
def
|
|
58
|
+
def resolution_raise_logic(head):
|
|
59
|
+
""" broken out into its own function for reuse to avoid re-resolving
|
|
60
|
+
in cases where we need to interpose additional operations between
|
|
61
|
+
a dereference failure and raising the error
|
|
62
|
+
"""
|
|
63
|
+
if not head.ok:
|
|
64
|
+
try:
|
|
65
|
+
head.raise_for_status()
|
|
66
|
+
except Exception as e:
|
|
67
|
+
if head.status_code == 404:
|
|
68
|
+
msg = f'Nothing found due to {head.status_code} at {head.url}\n'
|
|
69
|
+
raise exc.IdDoesNotExistError(msg) from e # often a permissions issue
|
|
70
|
+
elif head.status_code >= 500:
|
|
71
|
+
msg = f'Remote in error due to {head.status_code} at {head.url}\n'
|
|
72
|
+
raise exc.RemoteError(msg) from e
|
|
73
|
+
elif head.status_code >= 400:
|
|
74
|
+
msg = f'Nothing found due to {head.status_code} at {head.url}\n'
|
|
75
|
+
raise exc.ResolutionError(msg) from e
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def resolution_chain_responses(iri, raise_on_final=True, headers_fun=None):
|
|
33
79
|
#doi = doi # TODO
|
|
34
80
|
s = requests.Session()
|
|
35
81
|
head = s.head(iri, allow_redirects=False)
|
|
36
82
|
if head.status_code < 400:
|
|
37
83
|
yield head
|
|
38
84
|
else:
|
|
39
|
-
head = try_get(s, head)
|
|
85
|
+
head = try_get(s, head, headers_fun=headers_fun)
|
|
40
86
|
yield head
|
|
41
87
|
|
|
42
88
|
while head.is_redirect and head.status_code < 400: # FIXME redirect loop issue
|
|
@@ -49,21 +95,14 @@ def resolution_chain_responses(iri, raise_on_final=True):
|
|
|
49
95
|
if head.status_code < 400:
|
|
50
96
|
yield head
|
|
51
97
|
else:
|
|
52
|
-
head = try_get(s, head)
|
|
98
|
+
head = try_get(s, head, headers_fun=headers_fun)
|
|
53
99
|
yield head
|
|
54
100
|
|
|
55
101
|
if not head.is_redirect:
|
|
56
102
|
break
|
|
57
103
|
|
|
58
104
|
if raise_on_final: # we still want the chain ... null pointer error comes later?
|
|
59
|
-
|
|
60
|
-
head.raise_for_status() # probably a permissions issue
|
|
61
|
-
elif head.status_code >= 500:
|
|
62
|
-
msg = f'Remote in error due to {head.status_code} at {head.url}\n'
|
|
63
|
-
raise exc.RemoteError(msg)
|
|
64
|
-
elif head.status_code >= 400:
|
|
65
|
-
msg = f'Nothing found due to {head.status_code} at {head.url}\n'
|
|
66
|
-
raise exc.ResolutionError(msg)
|
|
105
|
+
resolution_raise_logic(head)
|
|
67
106
|
|
|
68
107
|
if head.status_code >= 400:
|
|
69
108
|
# XXX this seems like the "right" thing to do, but it will
|
idlib/from_oq.py
CHANGED
|
@@ -2,6 +2,7 @@ import re
|
|
|
2
2
|
import json
|
|
3
3
|
from time import time, sleep
|
|
4
4
|
from datetime import datetime
|
|
5
|
+
from urllib.parse import urlparse
|
|
5
6
|
import orthauth as oa
|
|
6
7
|
import ontquery as oq # temporary implementation detail
|
|
7
8
|
import idlib
|
|
@@ -20,6 +21,11 @@ from idlib.utils import (log,
|
|
|
20
21
|
from idlib.config import auth
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
def path_older_than_day(path):
|
|
25
|
+
ps = path.stat()
|
|
26
|
+
return time() - ps.st_ctime > (60 * 60 * 24)
|
|
27
|
+
|
|
28
|
+
|
|
23
29
|
# from neurondm.simple
|
|
24
30
|
class OntTerm(oq.OntTerm):
|
|
25
31
|
""" ask things about a term! """
|
|
@@ -345,6 +351,13 @@ def setup(cls, creds_file=None):
|
|
|
345
351
|
log.warning(e)
|
|
346
352
|
cls._pio_header = None
|
|
347
353
|
|
|
354
|
+
def rchf(url):
|
|
355
|
+
purl = urlparse(url)
|
|
356
|
+
if purl.netloc.endswith('protocols.io'):
|
|
357
|
+
return cls._pio_header
|
|
358
|
+
|
|
359
|
+
cls._resolution_chain_headers_fun = staticmethod(rchf)
|
|
360
|
+
|
|
348
361
|
if not hasattr(idlib.Stream, '_requests'):
|
|
349
362
|
idlib.Stream.__new__(cls)
|
|
350
363
|
|
|
@@ -645,7 +658,7 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
645
658
|
return data
|
|
646
659
|
|
|
647
660
|
_apiuri_private_cache = {} # XXX FIXME hack
|
|
648
|
-
def data4(self, fail_ok=False):
|
|
661
|
+
def data4(self, fail_ok=False, try_refresh_cache=False):
|
|
649
662
|
if not hasattr(self, '_data'):
|
|
650
663
|
self._data_in_error = True
|
|
651
664
|
if not isinstance(self._progenitors, dict):
|
|
@@ -661,7 +674,7 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
661
674
|
# however this is not trivial to retrive
|
|
662
675
|
# the /v3/protocols/{id} endpoint returns bad/mangled data and we need
|
|
663
676
|
# the /v1/ data to be able to actually render to org
|
|
664
|
-
blob, path = self._get_data(apiuri)
|
|
677
|
+
blob, path = self._get_data(apiuri, _refresh_cache=try_refresh_cache)
|
|
665
678
|
if 'stream-http' not in self._progenitors:
|
|
666
679
|
self._progenitors['path'] = path
|
|
667
680
|
|
|
@@ -690,6 +703,16 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
690
703
|
if fail_ok: return
|
|
691
704
|
raise exc.IdDoesNotExistError(message)
|
|
692
705
|
elif sc in (250, 205): # access requested, not authorized
|
|
706
|
+
if path_older_than_day(path):
|
|
707
|
+
# there seems to be a case where a protocol is shared
|
|
708
|
+
# with us and there is an old cache, in that case we
|
|
709
|
+
# hit an infinite loop because getting data for the
|
|
710
|
+
# progenitor says we should be able to resolve the
|
|
711
|
+
# final protocol now but it was cached on cooldown, if
|
|
712
|
+
# we can get to the first progenitor then we likely
|
|
713
|
+
# have access to the final url and get will succeed
|
|
714
|
+
return self.data4(fail_ok=fail_ok, try_refresh_cache=True)
|
|
715
|
+
|
|
693
716
|
try:
|
|
694
717
|
# there might be a private id in the progenitor chain
|
|
695
718
|
nself = self.progenitor(type='id-converted-from')
|
|
@@ -811,7 +834,8 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
811
834
|
try:
|
|
812
835
|
return self.data1(fail_ok=fail_ok)
|
|
813
836
|
except Exception as e1:
|
|
814
|
-
|
|
837
|
+
# FIXME error type ...
|
|
838
|
+
raise exc.InbetweenError() from e1
|
|
815
839
|
else:
|
|
816
840
|
return self.data4(fail_ok=fail_ok)
|
|
817
841
|
except (AttributeError, NotImplementedError) as e:
|
|
@@ -2041,6 +2065,14 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
2041
2065
|
if include_private and self.identifier.is_private():
|
|
2042
2066
|
out['uri_private'] = self.identifier # FIXME some way to avoid leaking these if needed?
|
|
2043
2067
|
return out
|
|
2068
|
+
except exc.MalformedIdentifierError as e:
|
|
2069
|
+
out = super().asDict(include_description)
|
|
2070
|
+
out['malformed'] = True
|
|
2071
|
+
if 'errors' not in out:
|
|
2072
|
+
out['errors'] = []
|
|
2073
|
+
|
|
2074
|
+
out['errors'].append({'message': 'malformed'})
|
|
2075
|
+
return out
|
|
2044
2076
|
except exc.RemoteError as e:
|
|
2045
2077
|
# we don't have any metadata but we will return what little info we have
|
|
2046
2078
|
return super().asDict(include_description)
|
idlib/streams.py
CHANGED
|
@@ -41,6 +41,8 @@ class Stream:
|
|
|
41
41
|
|
|
42
42
|
_progenitors = MappingProxyType({}) # this is a dict, but immutable to prevent accidents
|
|
43
43
|
|
|
44
|
+
_resolution_chain_headers_fun = None
|
|
45
|
+
|
|
44
46
|
def __new__(cls, *args, **kwargs):
|
|
45
47
|
return super().__new__(cls)
|
|
46
48
|
|
|
@@ -56,8 +58,9 @@ class Stream:
|
|
|
56
58
|
import requests # resolver dejoure
|
|
57
59
|
Stream._requests = requests
|
|
58
60
|
|
|
59
|
-
from idlib.core import resolution_chain_responses
|
|
61
|
+
from idlib.core import resolution_chain_responses, resolution_raise_logic
|
|
60
62
|
Stream._resolution_chain_responses = staticmethod(resolution_chain_responses)
|
|
63
|
+
Stream._resolution_raise_logic = staticmethod(resolution_raise_logic)
|
|
61
64
|
|
|
62
65
|
@classmethod
|
|
63
66
|
def fromJson(cls, blob):
|
|
@@ -608,8 +611,10 @@ class StreamUri(Stream):
|
|
|
608
611
|
dc[self.identifier_actionable] = tuple(
|
|
609
612
|
resp if resp is None else StringProgenitor(resp.url, progenitor=resp)
|
|
610
613
|
for resp in
|
|
611
|
-
self._resolution_chain_responses(
|
|
612
|
-
|
|
614
|
+
self._resolution_chain_responses(
|
|
615
|
+
self.identifier_actionable,
|
|
616
|
+
raise_on_final=False,
|
|
617
|
+
headers_fun=self._resolution_chain_headers_fun))
|
|
613
618
|
except (exc.ResolutionError, exc.RemoteError) as e:
|
|
614
619
|
# TODO
|
|
615
620
|
# FIXME partial resolution is a complete nightmare
|
|
@@ -626,6 +631,10 @@ class StreamUri(Stream):
|
|
|
626
631
|
def dereference(self, asType=None):
|
|
627
632
|
drc = self.dereference_chain()
|
|
628
633
|
uri = drc[-1]
|
|
634
|
+
if uri is None:
|
|
635
|
+
# null pointer
|
|
636
|
+
self._resolution_raise_logic(drc[-2]._progenitor)
|
|
637
|
+
|
|
629
638
|
if asType:
|
|
630
639
|
nid = asType(uri)
|
|
631
640
|
if isinstance(nid, idlib.Stream):
|
idlib/systems/ror.py
CHANGED
|
@@ -97,7 +97,7 @@ class Ror(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
97
97
|
def _checksum(self, cypher): # FIXME unqualified checksum goes to ... metadata ???
|
|
98
98
|
m = cypher()
|
|
99
99
|
metadata = self.metadata()
|
|
100
|
-
name = metadata
|
|
100
|
+
name = self._name(metadata)
|
|
101
101
|
m.update(self.identifier.checksum(cypher))
|
|
102
102
|
m.update(self.id_bound_metadata.checksum(cypher))
|
|
103
103
|
m.update(name.encode()) # unix epoch -> ??
|
|
@@ -143,9 +143,19 @@ class Ror(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
143
143
|
# or the remote telling us that we are in error
|
|
144
144
|
raise exc.RemoteError(self.identifier) from e
|
|
145
145
|
|
|
146
|
+
@staticmethod
|
|
147
|
+
def _name(m):
|
|
148
|
+
if 'names' in m:
|
|
149
|
+
for name in m['names']:
|
|
150
|
+
if 'ror_display' in name['types']:
|
|
151
|
+
return name['value']
|
|
152
|
+
else:
|
|
153
|
+
return m['name']
|
|
154
|
+
|
|
146
155
|
@property
|
|
147
156
|
def name(self):
|
|
148
|
-
|
|
157
|
+
m = self.metadata()
|
|
158
|
+
return self._name(m)
|
|
149
159
|
|
|
150
160
|
def asExternalId(self, id_class):
|
|
151
161
|
eids = self.data['external_ids']
|
|
@@ -170,6 +180,11 @@ class Ror(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
170
180
|
'Funder': 'Funder', # FIXME funder is a role ...
|
|
171
181
|
'Other': 'Institution',
|
|
172
182
|
}
|
|
183
|
+
for _k, _v in list(_type_map.items()):
|
|
184
|
+
_type_map[_k.lower()] = _v
|
|
185
|
+
del _k
|
|
186
|
+
del _v
|
|
187
|
+
|
|
173
188
|
@property
|
|
174
189
|
def institutionTypes(self):
|
|
175
190
|
metadata = self.metadata()
|
|
@@ -214,19 +229,29 @@ class Ror(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
214
229
|
def synonyms_rdf(self, rdflib): # FIXME annoying
|
|
215
230
|
d = self.metadata()
|
|
216
231
|
# FIXME how to deal with type conversion an a saner way ...
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
232
|
+
if 'names' in d:
|
|
233
|
+
for name in d['names']:
|
|
234
|
+
if 'ror_display' not in name['types']:
|
|
235
|
+
yield rdflib.Literal(name['value'], lang=name['lang'])
|
|
236
|
+
else:
|
|
237
|
+
yield from [rdflib.Literal(s) for s in d['aliases']]
|
|
238
|
+
yield from [rdflib.Literal(s) for s in d['acronyms']]
|
|
239
|
+
yield from [rdflib.Literal(l['label'], lang=l['iso639']) for l in d['labels']]
|
|
220
240
|
|
|
221
241
|
@property
|
|
222
242
|
def synonyms(self):
|
|
223
243
|
out = []
|
|
224
244
|
m = self.metadata()
|
|
225
|
-
|
|
226
|
-
|
|
245
|
+
if 'names' in m:
|
|
246
|
+
for name in m['names']:
|
|
247
|
+
if 'ror_display' not in name['types']:
|
|
248
|
+
out.append(name['value'])
|
|
249
|
+
else:
|
|
250
|
+
for a in m['aliases'] + m['acronyms']:
|
|
251
|
+
out.append(a)
|
|
227
252
|
|
|
228
|
-
|
|
229
|
-
|
|
253
|
+
for l in m['labels']:
|
|
254
|
+
out.append(l['label'])
|
|
230
255
|
|
|
231
256
|
return out
|
|
232
257
|
|
idlib/systems/rrid.py
CHANGED
|
@@ -175,8 +175,52 @@ class Rrid(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
175
175
|
if descs:
|
|
176
176
|
return sorted(descs, key=len, reverse=True)[0]
|
|
177
177
|
|
|
178
|
+
def proper_citation(self):
|
|
179
|
+
ms = self.metadata()
|
|
180
|
+
if ms:
|
|
181
|
+
cites = set(m['rrid']['properCitation'] for m in ms if 'rrid' in m and 'properCitation' in m['rrid'])
|
|
182
|
+
if cites:
|
|
183
|
+
return sorted(cites, key=len, reverse=True)[0]
|
|
184
|
+
|
|
185
|
+
# output streams
|
|
186
|
+
|
|
187
|
+
def _triples_gen(self,
|
|
188
|
+
rdflib=None,
|
|
189
|
+
rdf=None,
|
|
190
|
+
rdfs=None,
|
|
191
|
+
owl=None,
|
|
192
|
+
NIFRID=None,
|
|
193
|
+
TEMP=None,
|
|
194
|
+
**kwargs):
|
|
195
|
+
""" implementation of method to produce a
|
|
196
|
+
triplified version of the record """
|
|
197
|
+
s = self.asUri(rdflib.URIRef)
|
|
198
|
+
yield s, rdf.type, owl.NamedIndividual
|
|
199
|
+
try:
|
|
200
|
+
pc = self.proper_citation()
|
|
201
|
+
if pc:
|
|
202
|
+
yield s, TEMP.properCitation, rdflib.Literal(pc)
|
|
203
|
+
except exc.ResolutionError as e:
|
|
204
|
+
log.exception(e)
|
|
205
|
+
yield s, TEMP.resolutionError, rdflib.Literal(True)
|
|
206
|
+
return
|
|
207
|
+
except exc.RemoteError as e:
|
|
208
|
+
log.exception(e)
|
|
209
|
+
yield s, TEMP.remoteError, rdflib.Literal(True)
|
|
210
|
+
return
|
|
211
|
+
|
|
212
|
+
yield s, rdfs.label, rdflib.Literal(self.label)
|
|
213
|
+
|
|
178
214
|
# alternate representations
|
|
179
215
|
|
|
216
|
+
def asDict(self):
|
|
217
|
+
out = super().asDict()
|
|
218
|
+
pc = self.proper_citation()
|
|
219
|
+
if pc:
|
|
220
|
+
out['proper_citation'] = pc
|
|
221
|
+
|
|
222
|
+
return out
|
|
223
|
+
|
|
180
224
|
def asUri(self, asType=None):
|
|
181
225
|
# TODO n2t, identifiers.org
|
|
182
226
|
# TODO TODO having an explicit model for resolver/metadata services
|
idlib/utils.py
CHANGED
|
@@ -124,7 +124,12 @@ def makeEnc(alphabet):
|
|
|
124
124
|
def decode(chars, *, _index=index, _base=base):
|
|
125
125
|
number = 0
|
|
126
126
|
for c in chars:
|
|
127
|
-
|
|
127
|
+
try:
|
|
128
|
+
cind = _index[c]
|
|
129
|
+
except KeyError as e:
|
|
130
|
+
msg = ''.join(chars)
|
|
131
|
+
raise exc.MalformedIdentifierError(msg) from e
|
|
132
|
+
number = number * _base + cind
|
|
128
133
|
|
|
129
134
|
return number
|
|
130
135
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: idlib
|
|
3
|
-
Version: 0.0.1.
|
|
3
|
+
Version: 0.0.1.dev23
|
|
4
4
|
Summary: A library for working with identifiers of all kinds.
|
|
5
5
|
Home-page: https://github.com/tgbugs/idlib
|
|
6
6
|
Author: Tom Gillespie
|
|
@@ -38,6 +38,19 @@ Provides-Extra: rdf
|
|
|
38
38
|
Requires-Dist: pyontutils>=0.1.28; extra == "rdf"
|
|
39
39
|
Provides-Extra: oauth
|
|
40
40
|
Requires-Dist: google-auth-oauthlib; extra == "oauth"
|
|
41
|
+
Dynamic: author
|
|
42
|
+
Dynamic: author-email
|
|
43
|
+
Dynamic: classifier
|
|
44
|
+
Dynamic: description
|
|
45
|
+
Dynamic: description-content-type
|
|
46
|
+
Dynamic: home-page
|
|
47
|
+
Dynamic: keywords
|
|
48
|
+
Dynamic: license
|
|
49
|
+
Dynamic: license-file
|
|
50
|
+
Dynamic: provides-extra
|
|
51
|
+
Dynamic: requires-dist
|
|
52
|
+
Dynamic: requires-python
|
|
53
|
+
Dynamic: summary
|
|
41
54
|
|
|
42
55
|
# idlib
|
|
43
56
|
[](https://pypi.org/project/idlib/)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
idlib/__init__.py,sha256=
|
|
1
|
+
idlib/__init__.py,sha256=PMFL7ZemlNHqabBZ_MyLbYcaxaGBU1ET-nN9BlflWHE,1696
|
|
2
2
|
idlib/auth-config.py,sha256=tYM2aYCYJFG5NB4Af1dSn6YxhafttOp7W7aSc-QbVV8,460
|
|
3
3
|
idlib/cache.py,sha256=lR1I3iEYvBhNeqoptS-Sj7SpIHt1K65nYlBrTK-ROVQ,3875
|
|
4
4
|
idlib/config.py,sha256=Gli2tZlbKxBos8sXDoDK1g9mngfDw1ZWpBt_7MDZH-g,76
|
|
5
|
-
idlib/core.py,sha256=
|
|
5
|
+
idlib/core.py,sha256=KVhWN6yQfIGA5rG_ydNVC25oMa88lYJwQtAjzzhqziQ,4569
|
|
6
6
|
idlib/edit.py,sha256=s3yRtvNelQUA8fziu_igZeoFsW4xCK_kgfNVv3TS0iE,3635
|
|
7
7
|
idlib/exceptions.py,sha256=QC3Jq98iwezcqB7SmDr-UEOqdNCnvEXVkKB0eJLIwZs,4714
|
|
8
|
-
idlib/from_oq.py,sha256=
|
|
8
|
+
idlib/from_oq.py,sha256=kt4BpbAZgLo1CwxwyR_swnlVMsekV7ePfZivq9V8yns,95599
|
|
9
9
|
idlib/identifiers.py,sha256=s39bAS-fCQrlwAbMtaa7tjSnqKq4YPlfSbfJ6ju2o7I,3861
|
|
10
|
-
idlib/streams.py,sha256=
|
|
11
|
-
idlib/utils.py,sha256=
|
|
10
|
+
idlib/streams.py,sha256=QhOtT3xnp8FGVt7GEYAFAnd7PKYRKBPbOF6XGit63lQ,26765
|
|
11
|
+
idlib/utils.py,sha256=q2hcz0Qtbya1UpPnlGisougg9EuDZkcAKXJQIN4OFQs,5306
|
|
12
12
|
idlib/apis/__init__.py,sha256=q2-iSMUDPlYbjqGWa1mtbe2G95N7wbjWHGj30BUdVDM,88
|
|
13
|
-
idlib/apis/protocols_io.py,sha256=
|
|
13
|
+
idlib/apis/protocols_io.py,sha256=PKcoSbO9AqTfBYKLWJQyO3vHjug9qEL826s7jY4LWWg,4026
|
|
14
14
|
idlib/conventions/__init__.py,sha256=ug6W8eNHuq9JZy5bwrZ6Rjfu8r81Rrnm0nzApmvvMzw,204
|
|
15
15
|
idlib/conventions/core.py,sha256=g0T1VoNpoC9afvUd0wp6Mu7tRxbPDFK59uwVXV-zTtA,940
|
|
16
16
|
idlib/conventions/local.py,sha256=H1WnXTY06aLq0RB_SsTLVhMZiSP9GGvWuWm_zrFUNmQ,129
|
|
@@ -24,12 +24,12 @@ idlib/systems/handle.py,sha256=Gg97IuysdAdCX9j6EhuNfIddb1GDq0CmwW1SmuLkpgM,95
|
|
|
24
24
|
idlib/systems/isni.py,sha256=TgiSTlDcSBLRro3gg_YfQJQkfaJ3saw0Au1OMhE23wU,89
|
|
25
25
|
idlib/systems/orcid.py,sha256=aTVu_Q6fnaQvqmd6jeXdst6yKRTO-BEUMs7_4fdQK5E,7886
|
|
26
26
|
idlib/systems/pmid.py,sha256=Na-4_n7qmJ3VAbG0RUwnNTg7o4Z8OkuL_Hluq_A3IO0,181
|
|
27
|
-
idlib/systems/ror.py,sha256=
|
|
28
|
-
idlib/systems/rrid.py,sha256=
|
|
27
|
+
idlib/systems/ror.py,sha256=3pZ1aLg7NUh-mHQm-qu-hqy5WrJZprtj5lWIWRpP2-M,8894
|
|
28
|
+
idlib/systems/rrid.py,sha256=RcDn3-BRmrKzzxDCypSWRQuivKvWqUqqohY8BeSqRF4,8278
|
|
29
29
|
idlib/systems/urn.py,sha256=p222KjHgfF6y9srCm7kFWuWA9NK4lI-wEQUtSeuBqYk,113
|
|
30
30
|
idlib/systems/web.py,sha256=vrSbQYWnxhe9pSgZcOqwLM3V6XQDLwv1QqWlhWWxbL0,1291
|
|
31
|
-
idlib-0.0.1.
|
|
32
|
-
idlib-0.0.1.
|
|
33
|
-
idlib-0.0.1.
|
|
34
|
-
idlib-0.0.1.
|
|
35
|
-
idlib-0.0.1.
|
|
31
|
+
idlib-0.0.1.dev23.dist-info/licenses/LICENSE,sha256=nEuJBsoHfpXGgf6ZyFGUhQJqxFWwhSYF-45pRAqTSb4,1080
|
|
32
|
+
idlib-0.0.1.dev23.dist-info/METADATA,sha256=leTa1rrRwvU4n5ucULjBXh9zzBHvsjXNE8nj3-qWPog,2330
|
|
33
|
+
idlib-0.0.1.dev23.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
|
|
34
|
+
idlib-0.0.1.dev23.dist-info/top_level.txt,sha256=xIk87gJPbeCKih9BVMP8PlEFdpcsGplenz0VQhx5sP8,6
|
|
35
|
+
idlib-0.0.1.dev23.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|