def test_user_object_parse_aliased(): """Parse an aliased user object""" xml_string = """ <root> <book>Harry Potter</book> <person> <name>Ron</name> <age>18</age> </person> </root> """ processor = xml.dictionary('root', [ xml.string('book'), xml.user_object('person', Person, [xml.string('name'), xml.integer('age')], alias='character') ]) expected = { 'book': 'Harry Potter', 'character': Person().set_values(name='Ron', age=18) } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_user_object_serialize_aliased(): """Serializes an aliased user object""" value = { 'book': 'Harry Potter', 'character': Person().set_values(name='Malfoy', age=17) } processor = xml.dictionary('root', [ xml.string('book'), xml.user_object('person', Person, [xml.string('name'), xml.integer('age')], alias='character') ]) expected = strip_xml(""" <root> <book>Harry Potter</book> <person> <name>Malfoy</name> <age>17</age> </person> </root> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def test_user_object_parse_nested(): """Parse a user object as a nested element in the document""" xml_string = """ <root> <position>quarterback</position> <person> <name>Bob</name> <pet>Fluffy</pet> <pet>Spots</pet> </person> </root> """ processor = xml.dictionary('root', [ xml.string('position'), xml.user_object('person', Person, [ xml.string('name'), xml.array(xml.string('pet'), alias='pets'), ]) ]) expected = { 'position': 'quarterback', 'person': Person().set_values(name='Bob', pets=['Fluffy', 'Spots']) } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_named_tuple_serialize(): """Serialize a namedtuple value""" value = Author(name='Robert A. Heinlein', books=[ Book(title='Starship Troopers', year_published=1959), Book(title='Stranger in a Strange Land', year_published=1961) ]) processor = xml.named_tuple('author', Author, [ xml.string('name'), xml.array(xml.named_tuple('book', Book, [ xml.string('title'), xml.integer('year-published', alias='year_published') ]), alias='books') ]) expected = strip_xml(""" <author> <name>Robert A. Heinlein</name> <book> <title>Starship Troopers</title> <year-published>1959</year-published> </book> <book> <title>Stranger in a Strange Land</title> <year-published>1961</year-published> </book> </author> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def test_user_object_serialize_nested(): """Serializes a nested user object""" value = { 'position': 'quarterback', 'person': Person().set_values(name='Bob', pets=['Fluffy', 'Spots']) } processor = xml.dictionary('root', [ xml.string('position'), xml.user_object('person', Person, [ xml.string('name'), xml.array(xml.string('pet'), alias='pets'), ]) ]) expected = strip_xml(""" <root> <position>quarterback</position> <person> <name>Bob</name> <pet>Fluffy</pet> <pet>Spots</pet> </person> </root> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def test_parse_dictionary_aliased(): """Parses a dictionary value that is aliased""" xml_string = """ <person> <name>John Doe</name> <demographics> <age>25</age> <gender>male</gender> </demographics> </person> """ stats = xml.dictionary('demographics', [ xml.integer('age'), xml.string('gender'), ], alias='stats') person = xml.dictionary('person', [ xml.string('name'), stats, ]) expected = { 'name': 'John Doe', 'stats': { 'age': 25, 'gender': 'male', }, } actual = xml.parse_from_string(person, xml_string) assert expected == actual
def test_parse_dictionary_missing(): """Parse a missing dictionary""" xml_string = """ <person> <name>John Doe</name> <demographics> <age>25</age> <gender>male</gender> </demographics> </person> """ demographics = xml.dictionary('demographics', [ xml.integer('age'), xml.string('gender'), ]) address = xml.dictionary('address', [ xml.string('street'), xml.integer('zip'), xml.string('state'), ]) person = xml.dictionary('person', [ xml.string('name'), demographics, address, ]) with pytest.raises(xml.MissingValue): xml.parse_from_string(person, xml_string)
class TestSlashFromRootArray(_ProcessorTestCase): """Process with a slash starting from the root element""" xml_string = strip_xml(""" <locations> <cities> <city name="Kansas City" state="MO" /> <city name="Lincoln" state="NE" /> <city name="Salt Lake City" state="UT" /> </cities> </locations> """) value = [{ 'name': 'Kansas City', 'state': 'MO' }, { 'name': 'Lincoln', 'state': 'NE' }, { 'name': 'Salt Lake City', 'state': 'UT' }] processor = xml.array(xml.dictionary('city', [ xml.string('.', attribute='name'), xml.string('.', attribute='state'), ]), nested='locations/cities', alias='cities')
def _plays_to_games(self, data): def after_players_hook(_, status): return status["name"] if "name" in status else "Unknown" plays_processor = xml.dictionary("plays", [ xml.array( xml.dictionary('play', [ xml.integer(".", attribute="id", alias="playid"), xml.dictionary('item', [ xml.string(".", attribute="name", alias="gamename"), xml.integer(".", attribute="objectid", alias="gameid") ], alias='game'), xml.array( xml.dictionary( 'players/player', [ xml.string(".", attribute="name", required=False, default="Unknown") ], required=False, alias='players', hooks=xml.Hooks(after_parse=after_players_hook))) ], required=False, alias="plays")) ]) plays = xml.parse_from_string(plays_processor, data) plays = plays["plays"] return plays
def test_dictionary_serialize_nested_missing_optional(): """Serializes nested dictionaries""" value = { 'name': 'John Doe', 'demographics': { 'age': 27, 'gender': 'male', }, } processor = xml.dictionary('root', [ xml.string('name'), xml.dictionary( 'demographics', [xml.integer('age'), xml.string('gender')]), xml.dictionary('favorites', [xml.string('food'), xml.string('color')], required=False) ]) expected = strip_xml(""" <root> <name>John Doe</name> <demographics> <age>27</age> <gender>male</gender> </demographics> </root> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def test_dictionary_serialize_nested_aliased(): """Serializes nested aliased dictionaries""" value = { 'name': 'John Doe', 'stats': { 'age': 27, 'gender': 'male', } } processor = xml.dictionary('root', [ xml.string('name'), xml.dictionary( 'demographics', [xml.integer('age'), xml.string('gender')], alias='stats') ]) expected = strip_xml(""" <root> <name>John Doe</name> <demographics> <age>27</age> <gender>male</gender> </demographics> </root> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def test_attribute_serialize_multiple(): """Serializing multiple attributes to the same element""" value = { 'attribute_a': 'Hello, World', 'attribute_b': True, 'data': 1, 'message': 'Hello, World' } processor = xml.dictionary('root', [ xml.integer('data'), xml.string('data', attribute='attribute_a'), xml.boolean('data', attribute='attribute_b'), xml.string('message') ]) expected = strip_xml(""" <root> <data attribute_a="Hello, World" attribute_b="True">1</data> <message>Hello, World</message> </root> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def __init__(self): self.processor = xml.user_object( "annotation", Annotation, [ xml.user_object("size", Size, [ xml.integer("width"), xml.integer("height"), ]), xml.array( xml.user_object( "object", Object, [ xml.string("name"), xml.user_object( "bndbox", Box, [ xml.floating_point("xmin"), xml.floating_point("ymin"), xml.floating_point("xmax"), xml.floating_point("ymax"), ], alias="box" ) ] ), alias="objects" ), xml.string("filename") ] )
def test_parse_missing_non_required_namedtuple_issue_24(): """Parse XML with a non-required namedtuple value.""" Author = namedtuple('Author', [ 'name', 'genre', ]) Genre = namedtuple('Genre', [ 'name', ]) processor = xml.named_tuple('author', Author, [ xml.string('name'), xml.named_tuple('genre', Genre, [ xml.string('name') ], required=False) ]) author_xml = """ <author> <name>Robert A. Heinlein</name> </author> """ expected_value = Author(name='Robert A. Heinlein', genre=None) actual_value = xml.parse_from_string(processor, author_xml) assert expected_value == actual_value
def update(self): logging.debug('ExecutorEntryBuilder') executor_proc = xml.user_object('PASSPORT/EXECUTOR', Executor, [ xml.string('EXECUTORNAME', alias='name'), xml.string('EXECUTORPHONE', alias='phone') ]) executor = xml.parse_from_file(executor_proc, self.xml_data) super(ExecutorEntryBuilder, self).replace_bookmark(self.doc, 'EXECUTORNAME', executor.name) super(ExecutorEntryBuilder, self).replace_bookmark(self.doc, 'EXECUTORPHONE', executor.phone)
def _collection_to_games(self, data): def after_status_hook(_, status): return [tag for tag, value in status.items() if value == "1"] game_in_collection_processor = xml.dictionary("items", [ xml.array( xml.dictionary('item', [ xml.integer(".", attribute="objectid", alias="id"), xml.string("name"), xml.dictionary("status", [ xml.string(".", attribute="fortrade"), xml.string(".", attribute="own"), xml.string(".", attribute="preordered"), xml.string(".", attribute="prevowned"), xml.string(".", attribute="want"), xml.string(".", attribute="wanttobuy"), xml.string(".", attribute="wanttoplay"), xml.string(".", attribute="wishlist"), ], alias='tags', hooks=xml.Hooks( after_parse=after_status_hook)), xml.integer("numplays"), ], required=False, alias="items"), ) ]) collection = xml.parse_from_string(game_in_collection_processor, data) collection = collection["items"] return collection
def test_can_parse_and_serialize_frozen_attrs_class(): """Parse and serialize a frozen attrs class.""" processor = xml.user_object('book', _FrozenBook, [ xml.string('title'), xml.string('author'), ]) value = _FrozenBook( title='The Three Body Problem', author='Liu Cixin' ) assert_can_roundtrip_xml_value(processor, value)
def test_can_parse_and_serialize_attrs_class_with_no_defaults(): """Parse and serialize an attrs class.""" processor = xml.user_object('book', _BookWithNoDefaults, [ xml.string('title'), xml.string('author'), ]) value = _BookWithNoDefaults( title='The Three Body Problem', author='Liu Cixin' ) assert_can_roundtrip_xml_value(processor, value)
def test_parse_dictionary_nested(): """Parse nested dictionaries""" xml_string = """ <person> <name>John Doe</name> <demographics> <age>25</age> <gender>male</gender> </demographics> <address> <street>123 ABC Street</street> <zip>123456</zip> <state>NY</state> </address> </person> """ demographics = xml.dictionary('demographics', [ xml.integer('age'), xml.string('gender'), ]) address = xml.dictionary('address', [ xml.string('street'), xml.integer('zip'), xml.string('state'), ]) person = xml.dictionary('person', [ xml.string('name'), demographics, address, ]) expected = { 'name': 'John Doe', 'demographics': { 'age': 25, 'gender': 'male', }, 'address': { 'street': '123 ABC Street', 'zip': 123456, 'state': 'NY', }, } actual = xml.parse_from_string(person, xml_string) assert expected == actual
def json2cdata(input): author_processor = xml.dictionary('rows', [ xml.array(xml.dictionary('row', [ xml.string('qid'), xml.integer('code'), xml.string('answer'), xml.integer('sortorder'), xml.integer('assessment_value'), xml.integer('language'), xml.integer('scale_id'), ]), alias='rows') ]) xmlstr = xml.serialize_to_string(author_processor, input, indent=' ') return xmlstr
def test_named_tuple_transform(): """Transform a named tuple value""" Person = namedtuple('Person', ['name', 'age']) xml_string = strip_xml(""" <person> <name>John</name> <age>24</age> </person> """) value = { 'name': 'John', 'age': 24, } def _after_parse(_, tuple_value): return { 'name': tuple_value.name, 'age': tuple_value.age, } def _before_serialize(_, dict_value): return Person(name=dict_value['name'], age=dict_value['age']) processor = xml.named_tuple('person', Person, [ xml.string('name'), xml.integer('age'), ], hooks=xml.Hooks( after_parse=_after_parse, before_serialize=_before_serialize)) _transform_test_case_run(processor, value, xml_string)
def test_parse_array_embedded_aliased(): """Parse array embedded within its parent element""" xml_string = """ <root> <message>Goodbye, World!</message> <value>765</value> <value>3456</value> </root> """ values_array = xml.array(xml.integer('value'), alias='numbers') processor = xml.dictionary('root', [ xml.string('message'), values_array, ]) expected = { 'message': 'Goodbye, World!', 'numbers': [765, 3456], } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_parse_array_embedded(): """Parse array embedded within its parent element""" xml_string = """ <root> <message>Hello, World!</message> <value>21</value> <value>17</value> <value>90</value> <value>6</value> </root> """ values_array = xml.array(xml.integer('value')) processor = xml.dictionary('root', [ xml.string('message'), values_array, ]) expected = { 'message': 'Hello, World!', 'value': [21, 17, 90, 6], } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_user_object_serialize_array(): """Serializes an array of user objects""" value = [ Person().set_values(name='Bob', age=33), Person().set_values(name='Jan', age=24), Person().set_values(name='Tom', age=29) ] processor = xml.array(xml.user_object( 'person', Person, [xml.string('name'), xml.integer('age')]), nested='people') expected = strip_xml(""" <people> <person> <name>Bob</name> <age>33</age> </person> <person> <name>Jan</name> <age>24</age> </person> <person> <name>Tom</name> <age>29</age> </person> </people> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def test_parse_primitive_aliased(): """Parses primitive values with aliases""" xml_string = """ <root> <boolean>true</boolean> <float>3.14</float> <int>1</int> <string>Hello, World</string> </root> """ processor = xml.dictionary('root', [ xml.boolean('boolean', alias='b'), xml.floating_point('float', alias='f'), xml.integer('int', alias='i'), xml.string('string', alias='s'), ]) expected = { 'b': True, 'f': 3.14, 'i': 1, 's': 'Hello, World', } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_primitive_default_present(): """Parses primitive values with defaults specified""" xml_string = """ <root> <boolean>false</boolean> <float>3.14</float> <int>1</int> <string>Hello, World</string> </root> """ processor = xml.dictionary('root', [ xml.boolean('boolean', required=False, default=True), xml.floating_point('float', required=False, default=0.0), xml.integer('int', required=False, default=0), xml.string('string', required=False, default=''), ]) expected = { 'boolean': False, 'float': 3.14, 'int': 1, 'string': 'Hello, World', } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_non_root_dictionary(self): """Apply a transform to a non-root dictionary""" xml_string = strip_xml(""" <results> <name>Dataset 1</name> <data> <a>17</a> <b>42</b> <c>23</c> </data> </results> """) value = { 'name': 'Dataset 1', 'data': [ ('a', 17), ('b', 42), ('c', 23), ], } processor = xml.dictionary('results', [ xml.string('name'), self._dict_processor, ]) _transform_test_case_run(processor, value, xml_string)
def test_user_object_non_root(self): """Custom error message for user object values.""" processor = xml.dictionary('data', [ xml.user_object('user', _UserClass, [ xml.string('name'), xml.integer('age'), ], hooks=self._hooks) ]) xml_string = strip_xml(""" <data> <user> <name>Bob</name> <age>24</age> </user> </data> """) value = {'user': _UserClass(name='Bob', age=24)} location = 'data/user' self._assert_error_message(processor, value, xml_string, location)
def test_dictionary_non_root(self): """Custom error message for dictionary values.""" processor = xml.dictionary('data', [ xml.dictionary('user', [ xml.string('name'), xml.integer('age'), ], hooks=self._hooks) ]) xml_string = strip_xml(""" <data> <user> <name>Bob</name> <age>24</age> </user> </data> """) value = { 'user': { 'name': 'Bob', 'age': 24, } } location = 'data/user' self._assert_error_message(processor, value, xml_string, location)
def test_non_root_array(self): """Transform array values for non-root arrays""" xml_string = strip_xml(""" <data> <name>Dataset 1</name> <value key="a">17</value> <value key="b">42</value> <value key="c">37</value> </data> """) value = { 'name': 'Dataset 1', 'values': OrderedDict([ ('a', 17), ('b', 42), ('c', 37), ]), } processor = xml.dictionary('data', [ xml.string('name'), xml.array(self._item_processor, alias='values', hooks=self._hooks) ]) _transform_test_case_run(processor, value, xml_string)