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 CHANGED
@@ -55,4 +55,4 @@ def get_right_id(uri):
55
55
  return pi
56
56
 
57
57
 
58
- __version__ = '0.0.1.dev18'
58
+ __version__ = '0.0.1.dev20'
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
- return self.__class__(prefix='pio.view', suffix=self.slug)
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
- return self.__class__(prefix='pio.api', suffix=self.slug)
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
- return self.__class__(prefix='pio.api1', suffix=self.slug)
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
- return self.__class__(prefix='pio.api3', suffix=self.slug)
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
- else:
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 and j['status_code'] in (250, 205):
601
- message = j['text'] + ' ' + self.identifier.asStr()
602
- raise exc.NotAuthorizedError(message)
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
- orcid = self.metadata()['orcid']
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
- return self.metadata()['bio']
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
- id = metadata['rrid']['curie']
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
- source = metadata['hits']['hits'][0]['_source']
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
- proper_citation = metadata['rrid']['properCitation']
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
- m.update(proper_citation.encode())
116
- for vuri in self.vendorUris:
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
- m = self.metadata()
132
- if m is not None:
133
- return m['item']['name']
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
- m = self.metadata()['item']
140
- fs = 'label', 'synonyms', 'abbreviations'
141
- out = []
142
- for f in fs:
143
- if f in m:
144
- for v in m[f]:
145
- out.append(v)
146
-
147
- return out
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
- return self.metadata()['item']['description']
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.dev18
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] (>=0.0.13)
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 (>=0.1.28) ; extra == 'rdf'
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 (>=1.1.0) ; extra == 'test'
36
+ Requires-Dist: joblib >=1.1.0 ; extra == 'test'
37
37
  Requires-Dist: beautifulsoup4[html5lib] ; extra == 'test'
38
- Requires-Dist: pyontutils (>=0.1.28) ; extra == 'test'
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=IlCGOp7TpxDvJl6gTKHuw5Vb3id-TGDILLbtyEV9rLU,1696
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=92z-2WNjgXTHoOEUEMKqQPxQ_DSR-s2IuCboOof7lU0,91420
8
+ idlib/from_oq.py,sha256=HlgepGbgSUbOt5R79ALRhgiLOEvU6TSu3evB8zq7N84,94170
9
9
  idlib/identifiers.py,sha256=s39bAS-fCQrlwAbMtaa7tjSnqKq4YPlfSbfJ6ju2o7I,3861
10
- idlib/streams.py,sha256=Ck3p2boDFXwaIhlZoaqnn8wwCmelGtr9028iLT2sP00,26296
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=kzQKbX6BRG3XpttiSCYjEEFqas545uxWRD0tNKy5PyU,5679
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.dev18.dist-info/LICENSE,sha256=nEuJBsoHfpXGgf6ZyFGUhQJqxFWwhSYF-45pRAqTSb4,1080
32
- idlib-0.0.1.dev18.dist-info/METADATA,sha256=hZ-pz0FIf0w-u1rDTZOhD-rqyP6pAI3hYY3ZO-1505E,2020
33
- idlib-0.0.1.dev18.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110
34
- idlib-0.0.1.dev18.dist-info/top_level.txt,sha256=xIk87gJPbeCKih9BVMP8PlEFdpcsGplenz0VQhx5sP8,6
35
- idlib-0.0.1.dev18.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.40.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any