Skip to content

Commit 89cb572

Browse files
committed
Handle server errors and Core flag changes
1 parent 3106eaf commit 89cb572

File tree

6 files changed

+97
-62
lines changed

6 files changed

+97
-62
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ directly to the constructor (see the code below) or via environment variables.
2222

2323
```python
2424
from plasticity import Plasticity
25-
plasticity = Plasticity("<YOUR_TOKEN>")
25+
plasticity = Plasticity('<YOUR_TOKEN>')
2626
```
2727

2828
Alternately, a Plasticity constructor without these parameters will look for

plasticity/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,7 @@ def _post(self, url, data):
4646
if self.token:
4747
headers['authorization'] = "Bearer " + self.token
4848
response = requests.request("POST", url, data=data, headers=headers)
49-
return json.loads(response.text)
49+
try:
50+
return json.loads(response.text)
51+
except ValueError:
52+
return json.loads(response.text[:response.text.rfind('<!DOCTYPE')])

plasticity/base/response.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from __future__ import division
33
from __future__ import print_function
44

5-
from plasticity.utils import utils
6-
75

86
class Response(object):
97
"""A Response is a specific API response to an API endpoint.
@@ -12,10 +10,12 @@ class Response(object):
1210
plasticity: a Plasticity instance with the API URL and token
1311
"""
1412
def __init__(
15-
self, data, error, graph_enabled=None, ner_enabled=None,
16-
pretty_enabled=None):
13+
self, data, error, error_code, error_message,
14+
graph_enabled=None, ner_enabled=None, pretty_enabled=None):
1715
self.data = data
1816
self.error = error
17+
self.error_code = error_code
18+
self.error_message = error_message
1919

2020
self.graph_enabled = graph_enabled
2121
self.ner_enabled = ner_enabled
@@ -30,6 +30,8 @@ def __str__(self):
3030
@classmethod
3131
def from_json(cls, res, **kwargs):
3232
"""Builds a `Response` from a json object."""
33-
data = utils.deep_get(res, 'data')
34-
error = utils.deep_get(res, 'error')
35-
return cls(data, error, **kwargs)
33+
data = res.get('data')
34+
error = res.get('error')
35+
error_code = res.get('errorCode')
36+
error_message = res.get('message')
37+
return cls(data, error, error_code, error_message, **kwargs)

plasticity/sapien/core.py

Lines changed: 79 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,18 @@ def __repr__(self):
6161

6262
def __str__(self):
6363
output = 'CoreResponse'
64-
output += ' - {} sentence{}:'.format(
65-
len(self.data), '' if len(self.data) == 1 else 's')
66-
output += '\n'
67-
for d in self.data:
68-
output += utils.indent('{}'.format(d))
64+
if self.error:
65+
output += ' - {} error:'.format(self.error_code)
66+
output += '\n'
67+
output += utils.indent(
68+
utils.shorten('{}'.format(self.error_message)))
69+
else:
70+
output += ' - {} sentence{}:'.format(
71+
len(self.data), '' if len(self.data) == 1 else 's')
6972
output += '\n'
73+
for d in self.data:
74+
output += utils.indent('{}'.format(d))
75+
output += '\n'
7076
return output
7177

7278
@classmethod
@@ -80,9 +86,12 @@ def from_json(
8086
data.append(SentenceGroup.from_json(d))
8187
elif d['type'] == 'sentence':
8288
data.append(Sentence.from_json(d))
83-
error = utils.deep_get(res, 'error')
89+
error = res.get('error')
90+
error_code = res.get('errorCode')
91+
error_message = res.get('message')
8492
return cls(
85-
data, error, graph_enabled=graph_enabled, ner_enabled=ner_enabled,
93+
data, error, error_code, error_message,
94+
graph_enabled=graph_enabled, ner_enabled=ner_enabled,
8695
pretty_enabled=pretty_enabled)
8796

8897
def tpls(self):
@@ -211,9 +220,9 @@ def ner(self):
211220
:returns: The named entities of the text
212221
:rtype: {list}
213222
"""
214-
if not self.ner_enabled:
215-
raise AttributeError('The `ner` flag must be enabled in your '
216-
'request in order to use `ner()`.')
223+
if not self.ner_enabled or not self.graph_enabled:
224+
raise AttributeError('The `ner` and `graph` flags must be enabled '
225+
'in your request in order to use `ner()`.')
217226

218227
data_out = []
219228
for sentence_group in self.data:
@@ -264,10 +273,23 @@ class Sentence(object):
264273
`SentenceGroup` from a Core API call.
265274
"""
266275
def __init__(self, sentence, tokens, graph, dependencies):
267-
self.graph = graph
268-
self.dependencies = dependencies
276+
"""Initializes a new `Sentence`.
277+
278+
Creates a `Sentence` object which holds th
279+
:param sentence: The sentence text
280+
:type sentence: string
281+
:param tokens: A list of the tokens in the sentence
282+
:type tokens: list
283+
:param graph: A graph of the relations in the sentence
284+
(or none if graph is disabled in the request)
285+
:type graph: None|list
286+
:param dependencies: A list of the token dependencies in the sentence
287+
:type dependencies: list
288+
"""
269289
self.sentence = sentence
270290
self.tokens = tokens
291+
self.graph = graph
292+
self.dependencies = dependencies
271293

272294
def __repr__(self):
273295
return '<Sentence {}>'.format(id(self))
@@ -283,24 +305,30 @@ def __str__(self):
283305
output += '\n\n'
284306
output += utils.indent(
285307
utils.shorten('Dependencies: {}'.format(str(self.dependencies))))
286-
output += '\n\n'
287-
output += utils.indent('Graph: {} relation{}'.format(
288-
len(self.graph), '' if len(self.graph) == 1 else 's'))
308+
if self.graph is not None:
309+
output += '\n\n'
310+
output += utils.indent('Graph: {} relation{}'.format(
311+
len(self.graph), '' if len(self.graph) == 1 else 's'))
289312
return output
290313

291314
@classmethod
292315
def from_json(cls, s):
293316
"""Builds a `Sentence` from a json object."""
294-
graph = Graph.from_json(s.get('graph', []))
295-
dependencies = utils.deep_get(s, 'dependencies')
296-
sentence = utils.deep_get(s, 'sentence')
297-
tokens = utils.deep_get(s, 'tokens')
317+
sentence = s.get('sentence')
318+
tokens = s.get('tokens')
319+
graph = s.get('graph')
320+
if graph is not None:
321+
graph = Graph.from_json(graph)
322+
dependencies = s.get('dependencies')
298323
return cls(sentence, tokens, graph, dependencies)
299324

300325

301326
class Graph(list):
302327
"""Holds the `Graph` data within a `Sentence` from a
303328
Core API call.
329+
330+
Returns a `Graph`, which will be an empty list or a list with each
331+
`Relation` contained in the `Sentence`.
304332
"""
305333
def __init__(self, *args, **kwargs):
306334
super(Graph, self).__init__(args[0])
@@ -375,12 +403,12 @@ def from_json(cls, r):
375403
prepositions = [Preposition.from_json(p)
376404
for p in r.get('prepositions', [])
377405
if p.get('type') == 'preposition']
378-
predicate = Predicate.from_json(utils.deep_get(r, 'predicate'))
379-
qualifiers = utils.deep_get(r, 'qualifiers')
380-
vm_subject_prefix = utils.deep_get(r, 'verbModifiersSubjectSuffix')
381-
vm_object_prefix = utils.deep_get(r, 'verbModifiersObjectSuffix')
382-
question = utils.deep_get(r, 'question')
383-
question_auxiliary = utils.deep_get(r, 'questionAuxiliary')
406+
predicate = Predicate.from_json(r.get('predicate'))
407+
qualifiers = r.get('qualifiers')
408+
vm_subject_prefix = r.get('verbModifiersSubjectSuffix')
409+
vm_object_prefix = r.get('verbModifiersObjectSuffix')
410+
question = r.get('question')
411+
question_auxiliary = r.get('questionAuxiliary')
384412
return cls(
385413
subject, predicate, object_, qualifiers, prepositions,
386414
vm_subject_prefix, vm_object_prefix, question, question_auxiliary)
@@ -465,18 +493,19 @@ def __str__(self):
465493
@classmethod
466494
def from_json(cls, e):
467495
"""Builds an `Entity` from a json object."""
468-
entity = utils.deep_get(e, 'entity')
469-
index = utils.deep_get(e, 'index')
470-
determiner = utils.deep_get(e, 'determiner')
471-
proper_noun = utils.deep_get(e, 'properNoun')
472-
person = utils.deep_get(e, 'person')
473-
entity_modifiers_prefix = utils.deep_get(e, 'entityModifiersPrefix')
474-
entity_modifiers_suffix = utils.deep_get(e, 'entityModifiersSuffix')
475-
possessive_entity = utils.deep_get(e, 'possessive_entity')
476-
possessive_suffix = utils.deep_get(e, 'possessive_suffix')
477-
ner = [Concept.from_json(c)
478-
for c in utils.deep_get(e, 'ner')
479-
if c.get('type') == 'concept']
496+
entity = e.get('entity')
497+
index = e.get('index')
498+
determiner = e.get('determiner')
499+
proper_noun = e.get('properNoun')
500+
person = e.get('person')
501+
entity_modifiers_prefix = e.get('entityModifiersPrefix')
502+
entity_modifiers_suffix = e.get('entityModifiersSuffix')
503+
possessive_entity = e.get('possessive_entity')
504+
possessive_suffix = e.get('possessive_suffix')
505+
ner = e.get('ner')
506+
if ner is not None:
507+
ner = [Concept.from_json(c) for c in ner
508+
if c.get('type') == 'concept']
480509
return cls(
481510
entity, index, determiner, proper_noun, person,
482511
entity_modifiers_prefix, entity_modifiers_suffix,
@@ -528,17 +557,17 @@ def __str__(self):
528557
@classmethod
529558
def from_json(cls, p):
530559
"""Builds a `Predicate` from a json object."""
531-
verb = utils.deep_get(p, 'verb')
532-
index = utils.deep_get(p, 'index')
533-
negated = utils.deep_get(p, 'negated')
534-
tense = utils.deep_get(p, 'tense')
535-
conjugation = utils.deep_get(p, 'conjugation')
536-
phrasal_particle = utils.deep_get(p, 'phrasalParticle')
537-
auxiliary_qualifier = utils.deep_get(p, 'auxiliaryQualifier')
538-
verb_prefix = utils.deep_get(p, 'verbPrefix')
539-
verb_suffix = utils.deep_get(p, 'verbSuffix')
540-
verb_modifiers_prefix = utils.deep_get(p, 'verbModifiersPrefix')
541-
verb_modifiers_suffix = utils.deep_get(p, 'verbModifiersSuffix')
560+
verb = p.get('verb')
561+
index = p.get('index')
562+
negated = p.get('negated')
563+
tense = p.get('tense')
564+
conjugation = p.get('conjugation')
565+
phrasal_particle = p.get('phrasalParticle')
566+
auxiliary_qualifier = p.get('auxiliaryQualifier')
567+
verb_prefix = p.get('verbPrefix')
568+
verb_suffix = p.get('verbSuffix')
569+
verb_modifiers_prefix = p.get('verbModifiersPrefix')
570+
verb_modifiers_suffix = p.get('verbModifiersSuffix')
542571
return cls(
543572
verb, index, negated, tense, conjugation, phrasal_particle,
544573
auxiliary_qualifier, verb_prefix, verb_suffix,
@@ -571,8 +600,8 @@ def __str__(self):
571600
@classmethod
572601
def from_json(cls, p):
573602
"""Builds a `Predicate` from a json object."""
574-
preposition = utils.deep_get(p, 'preposition')
575-
index = utils.deep_get(p, 'index')
603+
preposition = p.get('preposition')
604+
index = p.get('index')
576605
type_ = utils.deep_get(p, 'prepositionObject', 'type')
577606
preposition_object = (
578607
Entity.from_json(p['prepositionObject']) if type_ == 'entity' else

plasticity/utils/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ def deep_get(dictionary, *keys):
1818
:returns: The value at the key sequence or `None`
1919
:rtype: {any}
2020
"""
21-
return reduce(lambda d, key: d.get(key, None) if isinstance(d, dict)
22-
else None, keys, dictionary)
21+
return reduce(lambda d, key:
22+
d.get(key, None) if isinstance(d, dict) else None,
23+
keys, dictionary)
2324

2425

2526
def indent(text, prefix='\t'):

plasticity/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version_info__ = ('0', '0', '8')
1+
__version_info__ = ('0', '0', '9')
22
__version__ = '.'.join(__version_info__)

0 commit comments

Comments
 (0)