Now the various objects attributes are derived directly from the data with which they're initialized.

This commit is contained in:
Jason R. Coombs 2016-09-03 14:21:06 -04:00
parent 6abccdc728
commit 9be618cd8c
2 changed files with 60 additions and 34 deletions

View File

@ -68,7 +68,17 @@ class ErrorHandler(object):
class Document(dict): class Document(dict):
pass _attr_types = {}
"Override the types from the document"
def __getattr__(self, name):
type = self._attr_types.get(name, lambda x: x)
attr_name = '@' + name
try:
val = self[name] if name in self else self[attr_name]
except KeyError:
raise AttributeError(name)
return type(val)
class Result(ErrorHandler, Document): class Result(ErrorHandler, Document):
@ -140,60 +150,74 @@ class Image(Document):
""" """
Holds information about an image included with an answer. Holds information about an image included with an answer.
""" """
def __init__(self, *args, **kwargs): _attr_types = dict(
super(Image, self).__init__(*args, **kwargs) height=int,
self.title = self['@title'] width=int,
self.alt = self['@alt'] )
self.height = self['@height']
self.width = self['@width'] @classmethod
self.src = self['@src'] def from_doc(cls, doc):
"""
Load images from the xmltodictresult. Always return
a list, even if the result is a singleton.
"""
if type(doc) != list:
doc = [doc]
return list(map(Image, doc))
class Subpod(Document): class Subpod(Document):
""" """
Holds a specific answer or additional information relevant to said answer. Holds a specific answer or additional information relevant to said answer.
""" """
def __init__(self, *args, **kwargs): _attr_types = dict(
super(Subpod, self).__init__(*args, **kwargs) img=Image.from_doc,
self.title = self['@title'] )
self.text = self['plaintext']
self.img = self['img'] @classmethod
# Allow images to be accessed in a consistent way, def from_doc(cls, doc):
# as a list, regardless of how many there are. """
if type(self.img) != list: Load subpods from the xmltodict result. Always return
self.img = [self.img] a list, even if the result is a singleton.
self.img = list(map(Image, self.img)) """
if type(doc) != list:
doc = [doc]
return list(map(cls, doc))
def xml_bool(str_val):
return (
bool(int(str_val))
if str_val.isdigit() else
str_val.lower() != 'true'
)
class Pod(ErrorHandler, Document): class Pod(ErrorHandler, Document):
""" """
Groups answers and information contextualizing those answers. Groups answers and information contextualizing those answers.
""" """
_attr_types = dict(
position=float,
numsubpods=int,
subpod=Subpod.from_doc,
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Pod, self).__init__(*args, **kwargs) super(Pod, self).__init__(*args, **kwargs)
self.error = self['@error']
self._handle_error(self) self._handle_error(self)
self.title = self['@title']
self.scanner = self['@scanner'] @property
self.id = self['@id'] def primary(self):
self.position = float(self['@position']) return '@primary' in self and xml_bool(self['@primary'])
self.number_of_subpods = int(self['@numsubpods'])
self.subpods = self['subpod']
# Allow subpods to be accessed in a consistent way,
# as a list, regardless of how many there are.
if type(self.subpods) != list:
self.subpods = [self.subpods]
self.subpods = list(map(Subpod, self.subpods))
self.primary = '@primary' in self and self['@primary'] != 'false'
@property @property
def texts(self): def texts(self):
""" """
The text from each subpod in this pod as a list. The text from each subpod in this pod as a list.
""" """
return [subpod.text for subpod in self.subpods] return [subpod.plaintext for subpod in self.subpod]
@property @property
def text(self): def text(self):
return next(iter(self.subpods)).text return next(iter(self.subpod)).plaintext

View File

@ -65,9 +65,11 @@ def test_properties(temp_result):
assert len(info) == len(pods) + len(warnings) + len(assumptions) assert len(info) == len(pods) + len(warnings) + len(assumptions)
def test_pod_position_is_float(temp_result): def test_pod_attributes(temp_result):
pod = next(temp_result.pods) pod = next(temp_result.pods)
assert isinstance(pod.position, float) assert isinstance(pod.position, float)
assert isinstance(pod.id, str)
assert isinstance(pod.subpod[0].img[0].height, int)
def test_invalid_app_id(): def test_invalid_app_id():