idlib 0.0.1.dev18__py2.py3-none-any.whl → 0.0.1.dev20__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/from_oq.py +72 -10
- idlib/streams.py +4 -1
- idlib/systems/rrid.py +45 -20
- {idlib-0.0.1.dev18.dist-info → idlib-0.0.1.dev20.dist-info}/METADATA +5 -5
- {idlib-0.0.1.dev18.dist-info → idlib-0.0.1.dev20.dist-info}/RECORD +9 -9
- {idlib-0.0.1.dev18.dist-info → idlib-0.0.1.dev20.dist-info}/WHEEL +1 -1
- {idlib-0.0.1.dev18.dist-info → idlib-0.0.1.dev20.dist-info}/LICENSE +0 -0
- {idlib-0.0.1.dev18.dist-info → idlib-0.0.1.dev20.dist-info}/top_level.txt +0 -0
idlib/__init__.py
CHANGED
idlib/from_oq.py
CHANGED
|
@@ -149,7 +149,9 @@ class PioId(oq.OntId, idlib.Identifier, idlib.Stream):
|
|
|
149
149
|
|
|
150
150
|
@property
|
|
151
151
|
def uri_human(self):
|
|
152
|
-
|
|
152
|
+
pid = self.__class__(prefix='pio.view', suffix=self.slug)
|
|
153
|
+
pid._id_converted_from = self
|
|
154
|
+
return pid
|
|
153
155
|
|
|
154
156
|
@property
|
|
155
157
|
def uri_api(self):
|
|
@@ -157,15 +159,21 @@ class PioId(oq.OntId, idlib.Identifier, idlib.Stream):
|
|
|
157
159
|
#prefix = 'pio.folders.api' # XXX prefix won't work here, requires a suffix /ids SIGH
|
|
158
160
|
#else:
|
|
159
161
|
#prefix = 'pio.api'
|
|
160
|
-
|
|
162
|
+
pid = self.__class__(prefix='pio.api', suffix=self.slug)
|
|
163
|
+
pid._id_converted_from = self
|
|
164
|
+
return pid
|
|
161
165
|
|
|
162
166
|
@property
|
|
163
167
|
def uri_api1(self):
|
|
164
|
-
|
|
168
|
+
pid = self.__class__(prefix='pio.api1', suffix=self.slug)
|
|
169
|
+
pid._id_converted_from = self
|
|
170
|
+
return pid
|
|
165
171
|
|
|
166
172
|
@property
|
|
167
173
|
def uri_api3(self):
|
|
168
|
-
|
|
174
|
+
pid = self.__class__(prefix='pio.api3', suffix=self.slug)
|
|
175
|
+
pid._id_converted_from = self
|
|
176
|
+
return pid
|
|
169
177
|
|
|
170
178
|
def normalize(self):
|
|
171
179
|
return self
|
|
@@ -584,8 +592,11 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
584
592
|
if noh:
|
|
585
593
|
# XXX noh assumes that the originating form was a uri_human use at own risk
|
|
586
594
|
return self._get_direct(self.identifier.uri_api)
|
|
587
|
-
|
|
595
|
+
elif self.uri_human:
|
|
588
596
|
return self.uri_human._get_direct(self.identifier.uri_api)
|
|
597
|
+
else:
|
|
598
|
+
msg = 'no beans'
|
|
599
|
+
raise NotImplementedError(msg)
|
|
589
600
|
|
|
590
601
|
def data1(self, fail_ok=False, noh=False):
|
|
591
602
|
# FIXME this depends on data4 for uri_human and cannot be used alone at the moment
|
|
@@ -595,11 +606,38 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
595
606
|
# because there is no oauth for it
|
|
596
607
|
# get data from the api/v1 endpoint which is is needed for unmangled steps
|
|
597
608
|
resp = self._data_direct(noh=noh)
|
|
609
|
+
# amazingly we get json even on fail ... 500 will not though
|
|
610
|
+
# I'm sure so some day this will break
|
|
598
611
|
j = resp.json()
|
|
599
612
|
if 'protocol' not in j: # FIXME SIGH
|
|
600
|
-
if 'status_code' in j
|
|
601
|
-
|
|
602
|
-
|
|
613
|
+
if 'status_code' in j:
|
|
614
|
+
# FIXME this is not the right way to do it
|
|
615
|
+
# we could be handed an id that was an api
|
|
616
|
+
# id that is clearly using the len 32 private
|
|
617
|
+
# id and we should probably just detect that
|
|
618
|
+
# instead of trying to chase conversion prov
|
|
619
|
+
# which can get broken for any number of reasons
|
|
620
|
+
id_was_private = False
|
|
621
|
+
_id = self.identifier
|
|
622
|
+
while True:
|
|
623
|
+
if _id.is_private():
|
|
624
|
+
id_was_private = True
|
|
625
|
+
break
|
|
626
|
+
elif not hasattr(_id, '_id_converted_from'):
|
|
627
|
+
break
|
|
628
|
+
else:
|
|
629
|
+
_id = _id._id_converted_from
|
|
630
|
+
|
|
631
|
+
if j['status_code'] in (250, 205):
|
|
632
|
+
message = j['status_text'] + ' ' + self.identifier.asStr()
|
|
633
|
+
raise exc.NotAuthorizedError(message)
|
|
634
|
+
elif j['status_code'] == 1 and id_was_private:
|
|
635
|
+
msg = (
|
|
636
|
+
f'{j["status_text"]} private id might have existed before but '
|
|
637
|
+
f'does not exist any more {self.identifier.asStr()}')
|
|
638
|
+
raise exc.IdDoesNotExistError(msg)
|
|
639
|
+
else:
|
|
640
|
+
raise NotImplementedError((resp.url, j))
|
|
603
641
|
|
|
604
642
|
return None
|
|
605
643
|
|
|
@@ -680,6 +718,14 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
680
718
|
# there is nothing wrong with the request ...
|
|
681
719
|
if fail_ok: return
|
|
682
720
|
raise exc.NotAuthorizedError(message)
|
|
721
|
+
elif sc == 1218:
|
|
722
|
+
# Authorization token is not correct
|
|
723
|
+
# please use header Authorization: Bearer <access_token>
|
|
724
|
+
# can happen if/when trying to retrieve a private protocol
|
|
725
|
+
# via api v4 instead of v1
|
|
726
|
+
msg = ('missing acces token or bad header not like '
|
|
727
|
+
'Authorization: Bearer <access_token>')
|
|
728
|
+
raise NotImplementedError(msg)
|
|
683
729
|
elif sc == 1219:
|
|
684
730
|
msg = 'access token expired'
|
|
685
731
|
# TODO need to classify this error, note that
|
|
@@ -756,8 +802,20 @@ class Pio(formats.Rdf, idlib.Stream):
|
|
|
756
802
|
self._progenitors['stream-http'] = uai._progenitors['stream-http']
|
|
757
803
|
|
|
758
804
|
return d4
|
|
805
|
+
elif self.identifier.is_private():
|
|
806
|
+
try:
|
|
807
|
+
return self.data4(fail_ok=fail_ok)
|
|
808
|
+
except exc.IdDoesNotExistError as ene:
|
|
809
|
+
raise ene
|
|
810
|
+
except Exception as e0:
|
|
811
|
+
try:
|
|
812
|
+
return self.data1(fail_ok=fail_ok)
|
|
813
|
+
except Exception as e1:
|
|
814
|
+
raise exc.TransportError() from e1
|
|
759
815
|
else:
|
|
760
816
|
return self.data4(fail_ok=fail_ok)
|
|
817
|
+
except (AttributeError, NotImplementedError) as e:
|
|
818
|
+
raise e
|
|
761
819
|
except Exception as e:
|
|
762
820
|
wait_until = time() + self._wait_time
|
|
763
821
|
self._data_in_error_sigh = wait_until, e
|
|
@@ -2161,7 +2219,9 @@ class PioUser(idlib.HelperNoData, idlib.Stream):
|
|
|
2161
2219
|
|
|
2162
2220
|
@property
|
|
2163
2221
|
def orcid(self):
|
|
2164
|
-
|
|
2222
|
+
md = self.metadata()
|
|
2223
|
+
k = 'orcid'
|
|
2224
|
+
orcid = md[k]if k in md and md[k] else None
|
|
2165
2225
|
if orcid is not None:
|
|
2166
2226
|
return idlib.Orcid.fromIdInit(prefix='orcid', suffix=orcid)
|
|
2167
2227
|
|
|
@@ -2173,7 +2233,9 @@ class PioUser(idlib.HelperNoData, idlib.Stream):
|
|
|
2173
2233
|
|
|
2174
2234
|
@property
|
|
2175
2235
|
def bio(self):
|
|
2176
|
-
|
|
2236
|
+
md = self.metadata()
|
|
2237
|
+
k = 'bio'
|
|
2238
|
+
return md[k]if k in md and md[k] else None
|
|
2177
2239
|
|
|
2178
2240
|
description = bio
|
|
2179
2241
|
|
idlib/streams.py
CHANGED
|
@@ -451,8 +451,10 @@ class HelpTestStreams:
|
|
|
451
451
|
# a separate loop?
|
|
452
452
|
cypher = self._hashlib.blake2b
|
|
453
453
|
bads = []
|
|
454
|
+
ds = []
|
|
454
455
|
for i in self.ids:
|
|
455
456
|
d = self.stream(i)
|
|
457
|
+
ds.append(d)
|
|
456
458
|
d.identifier
|
|
457
459
|
if d.identifier and hasattr(d.identifier, 'prefix'):
|
|
458
460
|
print(d.identifier)
|
|
@@ -547,10 +549,12 @@ class HelpTestStreams:
|
|
|
547
549
|
assert i1.identifier is not i2
|
|
548
550
|
|
|
549
551
|
def test_asDict(self):
|
|
552
|
+
ds = []
|
|
550
553
|
for id in self.ids:
|
|
551
554
|
s = self.stream(id)
|
|
552
555
|
try:
|
|
553
556
|
d = s.asDict()
|
|
557
|
+
ds.append(d)
|
|
554
558
|
except self._requests.exceptions.ConnectionError as e:
|
|
555
559
|
self._pytest.skip('Internet done goofed')
|
|
556
560
|
|
|
@@ -572,7 +576,6 @@ class StreamUri(Stream):
|
|
|
572
576
|
|
|
573
577
|
_id_class = None # NOTE asssigned to idlib.Uri in idlib.__init__
|
|
574
578
|
|
|
575
|
-
|
|
576
579
|
@property
|
|
577
580
|
def identifier(self):
|
|
578
581
|
return self._identifier
|
idlib/systems/rrid.py
CHANGED
|
@@ -57,7 +57,9 @@ class Rrid(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
57
57
|
def id_bound_metadata(self): # FIXME bound_id_metadata bound_id_data
|
|
58
58
|
metadata = self.metadata()
|
|
59
59
|
# wouldn't it be nice if all the metadata schemas had a common field called 'identifier' ?
|
|
60
|
-
|
|
60
|
+
ids = set(m['rrid']['curie'] for m in metadata)
|
|
61
|
+
assert len(ids) == 1, ids
|
|
62
|
+
id = next(iter(ids))
|
|
61
63
|
return self._id_class(id)
|
|
62
64
|
|
|
63
65
|
identifier_bound_metadata = id_bound_metadata
|
|
@@ -78,9 +80,12 @@ class Rrid(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
78
80
|
if metadata is not None:
|
|
79
81
|
self._path_metadata = path
|
|
80
82
|
self._progenitor_metadata_blob = metadata
|
|
81
|
-
|
|
83
|
+
self._total_hits = metadata['hits']['total']
|
|
84
|
+
source = [h['_source'] for h in metadata['hits']['hits']]
|
|
82
85
|
return source
|
|
83
86
|
|
|
87
|
+
return []
|
|
88
|
+
|
|
84
89
|
def _cooldown(self):
|
|
85
90
|
self._COOLDOWN = True
|
|
86
91
|
metadata, path = self._metadata(self.identifier)
|
|
@@ -109,12 +114,11 @@ class Rrid(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
109
114
|
# the identity of the RRID record ...
|
|
110
115
|
m = cypher()
|
|
111
116
|
metadata = self.metadata()
|
|
112
|
-
|
|
117
|
+
proper_citations = sorted([m['rrid']['properCitation'] for m in metadata])
|
|
113
118
|
m.update(self.identifier.checksum(cypher))
|
|
114
119
|
m.update(self.id_bound_metadata.checksum(cypher))
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
m.update(vuri.encode())
|
|
120
|
+
for proper_citation in proper_citations:
|
|
121
|
+
m.update(proper_citation.encode())
|
|
118
122
|
|
|
119
123
|
return m.digest()
|
|
120
124
|
|
|
@@ -122,33 +126,54 @@ class Rrid(formats.Rdf, idlib.HelperNoData, idlib.Stream):
|
|
|
122
126
|
def vendorUris(self):
|
|
123
127
|
metadata = self.metadata()
|
|
124
128
|
if 'vendors' in metadata: # FIXME SCR continues to be a bad citizen >_<
|
|
125
|
-
return [v['uri'] for v in metadata['vendors']]
|
|
129
|
+
return [v['uri'] if 'uri' in v else None for v in metadata['vendors']]
|
|
126
130
|
else:
|
|
127
131
|
return []
|
|
128
132
|
|
|
129
133
|
@property
|
|
130
134
|
def name(self):
|
|
131
|
-
|
|
132
|
-
if
|
|
133
|
-
|
|
135
|
+
ms = self.metadata()
|
|
136
|
+
if ms:
|
|
137
|
+
names = set(m['item']['name'] for m in ms)
|
|
138
|
+
return sorted(names, key=len, reverse=True)[0]
|
|
134
139
|
|
|
135
140
|
label = name
|
|
136
141
|
|
|
137
142
|
@property
|
|
138
143
|
def synonyms(self):
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
ms = self.metadata()
|
|
145
|
+
out = set()
|
|
146
|
+
for m in ms:
|
|
147
|
+
it = m['item']
|
|
148
|
+
fs = 'label', 'name', 'nomenclature', 'synonyms', 'abbreviations'
|
|
149
|
+
for f in fs:
|
|
150
|
+
if f in it:
|
|
151
|
+
thing = it[f]
|
|
152
|
+
if isinstance(thing, list):
|
|
153
|
+
for v in thing:
|
|
154
|
+
if type(v) is dict:
|
|
155
|
+
if 'name' in v:
|
|
156
|
+
for sigh in v['name'].split('. '):
|
|
157
|
+
syn = sigh.strip()
|
|
158
|
+
if syn:
|
|
159
|
+
out.add(syn)
|
|
160
|
+
else:
|
|
161
|
+
breakpoint()
|
|
162
|
+
raise NotImplementedError(f'TODO {v}')
|
|
163
|
+
else:
|
|
164
|
+
out.add(v)
|
|
165
|
+
else:
|
|
166
|
+
out.add(thing)
|
|
167
|
+
|
|
168
|
+
return sorted(out)
|
|
148
169
|
|
|
149
170
|
@property
|
|
150
171
|
def description(self):
|
|
151
|
-
|
|
172
|
+
ms = self.metadata()
|
|
173
|
+
if ms:
|
|
174
|
+
descs = set(m['item']['description'] for m in ms if 'description' in m['item'])
|
|
175
|
+
if descs:
|
|
176
|
+
return sorted(descs, key=len, reverse=True)[0]
|
|
152
177
|
|
|
153
178
|
# alternate representations
|
|
154
179
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: idlib
|
|
3
|
-
Version: 0.0.1.
|
|
3
|
+
Version: 0.0.1.dev20
|
|
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
|
|
@@ -23,19 +23,19 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
23
23
|
Requires-Python: >=3.6
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE
|
|
26
|
-
Requires-Dist: orthauth[sxpr,yaml]
|
|
26
|
+
Requires-Dist: orthauth[sxpr,yaml] >=0.0.13
|
|
27
27
|
Requires-Dist: requests
|
|
28
28
|
Provides-Extra: oauth
|
|
29
29
|
Requires-Dist: google-auth-oauthlib ; extra == 'oauth'
|
|
30
30
|
Provides-Extra: org
|
|
31
31
|
Requires-Dist: beautifulsoup4[html5lib] ; extra == 'org'
|
|
32
32
|
Provides-Extra: rdf
|
|
33
|
-
Requires-Dist: pyontutils
|
|
33
|
+
Requires-Dist: pyontutils >=0.1.28 ; extra == 'rdf'
|
|
34
34
|
Provides-Extra: test
|
|
35
35
|
Requires-Dist: pytest ; extra == 'test'
|
|
36
|
-
Requires-Dist: joblib
|
|
36
|
+
Requires-Dist: joblib >=1.1.0 ; extra == 'test'
|
|
37
37
|
Requires-Dist: beautifulsoup4[html5lib] ; extra == 'test'
|
|
38
|
-
Requires-Dist: pyontutils
|
|
38
|
+
Requires-Dist: pyontutils >=0.1.28 ; extra == 'test'
|
|
39
39
|
Requires-Dist: google-auth-oauthlib ; extra == 'test'
|
|
40
40
|
|
|
41
41
|
# idlib
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
idlib/__init__.py,sha256=
|
|
1
|
+
idlib/__init__.py,sha256=qnrq_qOQKd6AyZuvFQHZzYTLz8YGVe1TBdGtZmt89dM,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
5
|
idlib/core.py,sha256=zLqHrSwtgbQll-04J2B5j8W69AXpWT_Ql5n0eBHp2pk,1055
|
|
6
6
|
idlib/edit.py,sha256=s3yRtvNelQUA8fziu_igZeoFsW4xCK_kgfNVv3TS0iE,3635
|
|
7
7
|
idlib/exceptions.py,sha256=4qUTUrGkCMu2jE0TO4_hUCP-7XDCrk6FE08Ff-c1N94,4242
|
|
8
|
-
idlib/from_oq.py,sha256=
|
|
8
|
+
idlib/from_oq.py,sha256=HlgepGbgSUbOt5R79ALRhgiLOEvU6TSu3evB8zq7N84,94170
|
|
9
9
|
idlib/identifiers.py,sha256=s39bAS-fCQrlwAbMtaa7tjSnqKq4YPlfSbfJ6ju2o7I,3861
|
|
10
|
-
idlib/streams.py,sha256=
|
|
10
|
+
idlib/streams.py,sha256=3L5JnSDzbodHET66Mua4zlfJEZbsXACIsWtVd-iDUZM,26381
|
|
11
11
|
idlib/utils.py,sha256=zItGz-lXovZytSENUZ9q7A7gLr5uK_9VMawokGSskbk,5127
|
|
12
12
|
idlib/apis/__init__.py,sha256=q2-iSMUDPlYbjqGWa1mtbe2G95N7wbjWHGj30BUdVDM,88
|
|
13
13
|
idlib/apis/protocols_io.py,sha256=3PGKBwe9P_DxhScIG-L3ZFtnEHxgHaccLhRGVPZuYHg,3956
|
|
@@ -25,11 +25,11 @@ idlib/systems/isni.py,sha256=TgiSTlDcSBLRro3gg_YfQJQkfaJ3saw0Au1OMhE23wU,89
|
|
|
25
25
|
idlib/systems/orcid.py,sha256=3j17X59Fi-Yk_xhlJ6oPjb8BdzZD6_2BvbkIs1HeCPE,6745
|
|
26
26
|
idlib/systems/pmid.py,sha256=Na-4_n7qmJ3VAbG0RUwnNTg7o4Z8OkuL_Hluq_A3IO0,181
|
|
27
27
|
idlib/systems/ror.py,sha256=q_NyvVP-Xe9DrzQMFZAC2WeQU6QyxSa6RzrqQ0P7gUA,8067
|
|
28
|
-
idlib/systems/rrid.py,sha256=
|
|
28
|
+
idlib/systems/rrid.py,sha256=XVHyHyiGC2OvbOSXmfU3_wswS6yUw65qZ3Pct0sjbfU,6886
|
|
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.dev20.dist-info/LICENSE,sha256=nEuJBsoHfpXGgf6ZyFGUhQJqxFWwhSYF-45pRAqTSb4,1080
|
|
32
|
+
idlib-0.0.1.dev20.dist-info/METADATA,sha256=KrxuH4b2cYtMO0scJJCocd0lI8aIczeKhfIvOQLRToM,2012
|
|
33
|
+
idlib-0.0.1.dev20.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
34
|
+
idlib-0.0.1.dev20.dist-info/top_level.txt,sha256=xIk87gJPbeCKih9BVMP8PlEFdpcsGplenz0VQhx5sP8,6
|
|
35
|
+
idlib-0.0.1.dev20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|