Name | pysxm JSON |
Version |
1.5.0
JSON |
| download |
home_page | |
Summary | Simple and extensible xml python marshaller |
upload_time | 2024-01-26 17:37:02 |
maintainer | |
docs_url | None |
author | Josue Kouka |
requires_python | >2.7 |
license | MIT |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
Simple XML Python Marshaller
============================
.. image:: https://travis-ci.org/josuebrunel/pysxm.svg?branch=master
:target: https://travis-ci.org/josuebrunel/pysxm
.. image:: https://coveralls.io/repos/github/josuebrunel/pysxm/badge.svg?branch=master
:target: https://coveralls.io/github/josuebrunel/pysxm?branch=master
.. image:: http://pepy.tech/badge/pysxm
:target: http://pepy.tech/count/pysxm
**pysxm** is a simple and extensible xml python marshaller.
It comes with two simple and basic types:
- SimpleType
- ComplexType
It supports py2 and py3 and uses *lxml.objectify* under the hood.
Installation
------------
.. code:: python
pip install pysxm
Quickstart
----------
.. code:: python
In [1]: from pysxm import ComplexType
In [2]: class Person(ComplexType):
...: attrib = {'description': 'a random person'}
...: def __init__(self, fname, lname):
...: self.fname = fname
...: self.lname = lname
...:
In [3]: person = Person('token', 'black')
In [4]: print(person)
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" description="a random person">
<lname>black</lname>
<fname>token</fname>
</person>
Let's say, we want a different **tag** for our object.
An attribute **tagname** or **_tagname** can be set to define the **xml tag name** of the object.
.. code:: python
In [5]: class Person(ComplexType):
...: attrib = {'description': 'a random person'}
...: tagname = 'student'
...: def __init__(self, fname, lname):
...: self.fname = fname
...: self.lname = lname
...:
In [6]: person = Person('token', 'black')
In [7]: print(person)
<student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" description="a random person">
<lname>black</lname>
<fname>token</fname>
</student>
A **sequence** or **_sequence** (tuple or list) attribute can be set to decide of the **order** or the **presence** of an subelement in the xml.
.. code:: python
In [8]: class Person(ComplexType):
...: attrib = {'description': 'a random person'}
...: tagname = 'student'
...: _sequence = ('city', 'fname')
...:
...: def __init__(self, fname, lname, city):
...: self.fname = fname
...: self.lname = lname
...: self.city = city
...:
In [9]: person = Person('token', 'black', 'south park')
In [10]: print(person)
<student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" description="a random person">
<city>south park</city>
<fname>token</fname>
</student>
Let's add a **namespace** to our object.
.. code:: python
In [11]: class Person(ComplexType):
...: attrib = {'description': 'a random south park character'}
...: nsmap = {'sp': 'http://southpark/xml/'}
...:
...: def __init__(self, fname, lname, city):
...: self.fname = fname
...: self.lname = lname
...: self.city = city
...:
In [12]: person = Person('token', 'black', 'south park')
In [13]: print(person)
<sp:person xmlns:sp="http://southpark/xml/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" description="a random south park character">
<sp:lname>black</sp:lname>
<sp:city>south park</sp:city>
<sp:fname>token</sp:fname>
</sp:person>
Let's make sure that a *person*'s group is either *coon* or *goth*.
To do so, we can inherit from **SimpleType** object and define a restriction by overriding **check_restriction(self, value)** method.
.. code:: python
In [7]: from pysxm import ComplexType, SimpleType
In [8]: class Group(SimpleType):
...: allowed_groups = ('coon', 'goth')
...: def check_restriction(self, value):
...: if value not in self.allowed_groups:
...: raise ValueError('<%s> value %s not in %s' % (self.tagname, value, self.allowed_groups))
...:
In [9]: class Person(ComplexType):
...: def __init__(self, fname, lname, group):
...: self.fname = fname
...: self.lname = lname
...: self.group = Group(group)
...:
In [10]: Person('token', 'black', 'boys')
...
<ipython-input-8-116b49042116> in check_restriction(self, value)
3 def check_restriction(self, value):
4 if value not in self.allowed_groups:
----> 5 raise ValueError('<%s> value %s not in %s' % (self.tagname, value, self.allowed_groups))
6
ValueError: <group> value boys not in ('coon', 'goth')
In [11]: print(Person('token', 'black', 'goth'))
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lname>black</lname>
<group>goth</group>
<fname>token</fname>
</person>
**Note**: *ComplexType* can have *ComplexType* and *SimpleType* as attribute
.. code:: python
from pysxm import ComplexType, SimpleType
class AdultAge(SimpleType):
tagname = 'age'
attrib = {'minvalue': '18', 'maxvalue': '100'}
def check_restriction(self, value):
if int(value) < 18:
raise ValueError("<%s> '%d' < 18" % (self.tagname, value))
class Credentials(ComplexType):
def __init__(self, login, password):
self.login = login
self.password = password
class Person(ComplexType):
def __init__(self, fname, lname, credentials, age):
self.fname = fname
self.lname = lname
self.credentials = Credentials(credentials['login'], credentials['password'])
self.age = AdultAge(age)
In [3]: data = {
...: 'fname': 'token', 'lname': 'black',
...: 'credentials': {'login': 't0ken', 'password': 'l33tolite'},
...: 'age': '30'}
In [4]: person = Person(**data)
In [5]: print(person)
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lname>black</lname>
<credentials>
<login>t0ken</login>
<password>l33tolite</password>
</credentials>
<age maxvalue="100" minvalue="18">30</age>
<fname>token</fname>
</person>
In [6]: person.save('token.xml')
The **save** method (*object.save(<filename>)*) allows you to save the xml result into a file.
.. code:: python
In [7]: cat token.xml
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lname>black</lname>
<credentials>
<login>t0ken</login>
<password>l33tolite</password>
</credentials>
<age maxvalue="100" minvalue="18">30</age>
<fname>token</fname>
</person>
The ext module
^^^^^^^^^^^^^^
Pysxm comes with a couple of extended types. Those types are defined in *pysxm.ext* module.
DataComplexType
"""""""""""""""
This is a simple *DataClass* of *ComplexType*. Here is how you can set one up:
.. code:: python
from pysxm.ext import DataComplexType, XSimpleType
class Game(DataComplexType):
platform = XSimpleType('platform', ['xboxone', 'xboxx'], lambda v, av: v in av)
>>> game = Game(name='state of decay 2', editor='undead labs', platform='xboxone')
>>> print(game)
<game>
<name>state of decay 2</name>
<platform>xboxone</platform>
<editor>undead labs</editor>
</game>
XSimpleType
"""""""""""
It gets tiresome to subclass a *SimpleType* everytime you want to check a value. To overcome that, **pysxm** provides a **descriptor** called **XSimpleType**:
.. code:: python
class XSimpleType(object):
def __init__(name=None, restriction=None, checker=None, error_msg=None, **kwargs):
'''name: it's the name of the attribute.
restriction: self explanatory
checker: the fucntion that checks the input value
error_msg: message returned when checking fails
kwargs: as tagname, attrib or nsmap
'''
Here is an example:
.. code:: python
class XboxGamer(ComplexType):
platform = XSimpleType('platform', ('xone', 'xbox360', 'xbox'), lambda v, av: v in av)
score = XSimpleType('score', (4000, 1000000), lambda v, av: int(av[0]) <= int(v) < int(av[1]))
lastlogin = XDateTimeType('lastlogin')
def __init__(self, gamertag, platform, score, lastlogin):
self.gamertag = gamertag
self.platform = platform
self.score = score
self.lastlogin = lastlogin
In [1]: print(gamer_data)
{'gamertag': 'LokingHD', 'platform': 'ps4', 'score': '22526', 'lastlogin': '2018-03-21'}
In [2]: XboxGamer(**gamer_data)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-2-61f95466da46> in <module>()
----> 1 XboxGamer(**gamer_data)
/home/josue/workspace/dev/pysxdb/pysxm/ext.pyc in check(self, instance, value)
77 if not self.checker(value, self.restriction_values):
78 raise ValueError('tagname <%s> value %s is invalid: expected (%s)'
---> 79 % (instance.tagname, value, self.restriction_values))
80
81 def check_restriction(self, instance, value):
ValueError: tagname <xboxgamer> value ps4 is invalid: expected (('xone', 'xbox360', 'xbox'))
In [3]: gamer_data['platform'] = 'xone'
In [4]: gamer = XboxGamer(**gamer_data)
In [5]: print(gamer)
<xboxgamer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<gamertag>LokingHD</gamertag>
<platform>xone</platform>
<score>22526</score>
<lastlogin>2018-03-21T00:00:00</lastlogin>
</xboxgamer>
Most of the types defined in *pysxm.ext* are descriptors and they're subclassable.
Voila :wink:
Raw data
{
"_id": null,
"home_page": "",
"name": "pysxm",
"maintainer": "",
"docs_url": null,
"requires_python": ">2.7",
"maintainer_email": "",
"keywords": "",
"author": "Josue Kouka",
"author_email": "josuebrunel@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/3b/6f/7ec680a2cef12c9da11912e2e04f5c5d8fa3d9bcc436a157ecc48c027cff/pysxm-1.5.0.tar.gz",
"platform": null,
"description": "Simple XML Python Marshaller\n============================\n\n.. image:: https://travis-ci.org/josuebrunel/pysxm.svg?branch=master\n :target: https://travis-ci.org/josuebrunel/pysxm\n.. image:: https://coveralls.io/repos/github/josuebrunel/pysxm/badge.svg?branch=master\n :target: https://coveralls.io/github/josuebrunel/pysxm?branch=master\n.. image:: http://pepy.tech/badge/pysxm\n :target: http://pepy.tech/count/pysxm\n\n\n**pysxm** is a simple and extensible xml python marshaller.\nIt comes with two simple and basic types:\n\n- SimpleType\n- ComplexType\n\nIt supports py2 and py3 and uses *lxml.objectify* under the hood.\n\n\nInstallation\n------------\n\n.. code:: python\n\n pip install pysxm\n\n\nQuickstart\n----------\n\n.. code:: python\n\n In [1]: from pysxm import ComplexType\n In [2]: class Person(ComplexType):\n ...: attrib = {'description': 'a random person'}\n ...: def __init__(self, fname, lname):\n ...: self.fname = fname\n ...: self.lname = lname\n ...:\n In [3]: person = Person('token', 'black')\n In [4]: print(person)\n <person xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" description=\"a random person\">\n <lname>black</lname>\n <fname>token</fname>\n </person>\n\nLet's say, we want a different **tag** for our object.\nAn attribute **tagname** or **_tagname** can be set to define the **xml tag name** of the object.\n\n.. code:: python\n\n In [5]: class Person(ComplexType):\n ...: attrib = {'description': 'a random person'}\n ...: tagname = 'student'\n ...: def __init__(self, fname, lname):\n ...: self.fname = fname\n ...: self.lname = lname\n ...:\n In [6]: person = Person('token', 'black')\n In [7]: print(person)\n <student xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" description=\"a random person\">\n <lname>black</lname>\n <fname>token</fname>\n </student>\n\nA **sequence** or **_sequence** (tuple or list) attribute can be set to decide of the **order** or the **presence** of an subelement in the xml.\n\n.. code:: python\n\n In [8]: class Person(ComplexType):\n ...: attrib = {'description': 'a random person'}\n ...: tagname = 'student'\n ...: _sequence = ('city', 'fname')\n ...:\n ...: def __init__(self, fname, lname, city):\n ...: self.fname = fname\n ...: self.lname = lname\n ...: self.city = city\n ...:\n In [9]: person = Person('token', 'black', 'south park')\n In [10]: print(person)\n <student xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" description=\"a random person\">\n <city>south park</city>\n <fname>token</fname>\n </student>\n\nLet's add a **namespace** to our object.\n\n.. code:: python\n\n In [11]: class Person(ComplexType):\n ...: attrib = {'description': 'a random south park character'}\n ...: nsmap = {'sp': 'http://southpark/xml/'}\n ...:\n ...: def __init__(self, fname, lname, city):\n ...: self.fname = fname\n ...: self.lname = lname\n ...: self.city = city\n ...:\n In [12]: person = Person('token', 'black', 'south park')\n In [13]: print(person)\n <sp:person xmlns:sp=\"http://southpark/xml/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" description=\"a random south park character\">\n <sp:lname>black</sp:lname>\n <sp:city>south park</sp:city>\n <sp:fname>token</sp:fname>\n </sp:person>\n\nLet's make sure that a *person*'s group is either *coon* or *goth*.\nTo do so, we can inherit from **SimpleType** object and define a restriction by overriding **check_restriction(self, value)** method.\n\n.. code:: python\n\n In [7]: from pysxm import ComplexType, SimpleType\n In [8]: class Group(SimpleType):\n ...: allowed_groups = ('coon', 'goth')\n ...: def check_restriction(self, value):\n ...: if value not in self.allowed_groups:\n ...: raise ValueError('<%s> value %s not in %s' % (self.tagname, value, self.allowed_groups))\n ...:\n In [9]: class Person(ComplexType):\n ...: def __init__(self, fname, lname, group):\n ...: self.fname = fname\n ...: self.lname = lname\n ...: self.group = Group(group)\n ...:\n In [10]: Person('token', 'black', 'boys')\n ...\n <ipython-input-8-116b49042116> in check_restriction(self, value)\n 3 def check_restriction(self, value):\n 4 if value not in self.allowed_groups:\n ----> 5 raise ValueError('<%s> value %s not in %s' % (self.tagname, value, self.allowed_groups))\n 6\n ValueError: <group> value boys not in ('coon', 'goth')\n\n In [11]: print(Person('token', 'black', 'goth'))\n <person xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <lname>black</lname>\n <group>goth</group>\n <fname>token</fname>\n </person>\n\n**Note**: *ComplexType* can have *ComplexType* and *SimpleType* as attribute\n\n.. code:: python\n\n from pysxm import ComplexType, SimpleType\n\n\n class AdultAge(SimpleType):\n\n tagname = 'age'\n attrib = {'minvalue': '18', 'maxvalue': '100'}\n\n def check_restriction(self, value):\n if int(value) < 18:\n raise ValueError(\"<%s> '%d' < 18\" % (self.tagname, value))\n\n\n class Credentials(ComplexType):\n\n def __init__(self, login, password):\n self.login = login\n self.password = password\n\n\n class Person(ComplexType):\n\n def __init__(self, fname, lname, credentials, age):\n self.fname = fname\n self.lname = lname\n self.credentials = Credentials(credentials['login'], credentials['password'])\n self.age = AdultAge(age)\n\n In [3]: data = {\n ...: 'fname': 'token', 'lname': 'black',\n ...: 'credentials': {'login': 't0ken', 'password': 'l33tolite'},\n ...: 'age': '30'}\n In [4]: person = Person(**data)\n In [5]: print(person)\n <person xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <lname>black</lname>\n <credentials>\n <login>t0ken</login>\n <password>l33tolite</password>\n </credentials>\n <age maxvalue=\"100\" minvalue=\"18\">30</age>\n <fname>token</fname>\n </person>\n In [6]: person.save('token.xml')\n\nThe **save** method (*object.save(<filename>)*) allows you to save the xml result into a file.\n\n.. code:: python\n\n In [7]: cat token.xml\n <person xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <lname>black</lname>\n <credentials>\n <login>t0ken</login>\n <password>l33tolite</password>\n </credentials>\n <age maxvalue=\"100\" minvalue=\"18\">30</age>\n <fname>token</fname>\n </person>\n\n\nThe ext module\n^^^^^^^^^^^^^^\n\nPysxm comes with a couple of extended types. Those types are defined in *pysxm.ext* module.\n\nDataComplexType\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nThis is a simple *DataClass* of *ComplexType*. Here is how you can set one up:\n\n.. code:: python\n\n from pysxm.ext import DataComplexType, XSimpleType\n\n\n class Game(DataComplexType):\n platform = XSimpleType('platform', ['xboxone', 'xboxx'], lambda v, av: v in av)\n\n >>> game = Game(name='state of decay 2', editor='undead labs', platform='xboxone')\n >>> print(game)\n <game>\n <name>state of decay 2</name>\n <platform>xboxone</platform>\n <editor>undead labs</editor>\n </game>\n\nXSimpleType\n\"\"\"\"\"\"\"\"\"\"\"\n\nIt gets tiresome to subclass a *SimpleType* everytime you want to check a value. To overcome that, **pysxm** provides a **descriptor** called **XSimpleType**:\n\n.. code:: python\n\n class XSimpleType(object):\n\n def __init__(name=None, restriction=None, checker=None, error_msg=None, **kwargs):\n '''name: it's the name of the attribute.\n restriction: self explanatory\n checker: the fucntion that checks the input value\n error_msg: message returned when checking fails\n kwargs: as tagname, attrib or nsmap\n '''\n\nHere is an example:\n\n\n.. code:: python\n\n class XboxGamer(ComplexType):\n platform = XSimpleType('platform', ('xone', 'xbox360', 'xbox'), lambda v, av: v in av)\n score = XSimpleType('score', (4000, 1000000), lambda v, av: int(av[0]) <= int(v) < int(av[1]))\n lastlogin = XDateTimeType('lastlogin')\n\n def __init__(self, gamertag, platform, score, lastlogin):\n self.gamertag = gamertag\n self.platform = platform\n self.score = score\n self.lastlogin = lastlogin\n\n In [1]: print(gamer_data)\n {'gamertag': 'LokingHD', 'platform': 'ps4', 'score': '22526', 'lastlogin': '2018-03-21'}\n In [2]: XboxGamer(**gamer_data)\n ---------------------------------------------------------------------------\n ValueError Traceback (most recent call last)\n <ipython-input-2-61f95466da46> in <module>()\n ----> 1 XboxGamer(**gamer_data)\n /home/josue/workspace/dev/pysxdb/pysxm/ext.pyc in check(self, instance, value)\n 77 if not self.checker(value, self.restriction_values):\n 78 raise ValueError('tagname <%s> value %s is invalid: expected (%s)'\n ---> 79 % (instance.tagname, value, self.restriction_values))\n 80\n 81 def check_restriction(self, instance, value):\n ValueError: tagname <xboxgamer> value ps4 is invalid: expected (('xone', 'xbox360', 'xbox'))\n In [3]: gamer_data['platform'] = 'xone'\n In [4]: gamer = XboxGamer(**gamer_data)\n In [5]: print(gamer)\n <xboxgamer xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <gamertag>LokingHD</gamertag>\n <platform>xone</platform>\n <score>22526</score>\n <lastlogin>2018-03-21T00:00:00</lastlogin>\n </xboxgamer>\n\n\nMost of the types defined in *pysxm.ext* are descriptors and they're subclassable.\n\n\nVoila :wink:\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Simple and extensible xml python marshaller",
"version": "1.5.0",
"project_urls": null,
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8f6f5c5059902b8b292eaef291cf3429065b01da005088f6811bef1f56e6a526",
"md5": "366c2b13c6b459511d42709865dec204",
"sha256": "826732fc9ed9faea4aa720fa0d4241c0bc5271cc48cdb8db2bc4b05376b5c327"
},
"downloads": -1,
"filename": "pysxm-1.5.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "366c2b13c6b459511d42709865dec204",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": ">2.7",
"size": 8362,
"upload_time": "2024-01-26T17:37:00",
"upload_time_iso_8601": "2024-01-26T17:37:00.531877Z",
"url": "https://files.pythonhosted.org/packages/8f/6f/5c5059902b8b292eaef291cf3429065b01da005088f6811bef1f56e6a526/pysxm-1.5.0-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3b6f7ec680a2cef12c9da11912e2e04f5c5d8fa3d9bcc436a157ecc48c027cff",
"md5": "5ee745d9f2597c7c7d2256e6785fdb72",
"sha256": "98c2e0f3a644d5dfd60d4829dcaf224bdebed6e1507c9427f794d689c2e9cd2a"
},
"downloads": -1,
"filename": "pysxm-1.5.0.tar.gz",
"has_sig": false,
"md5_digest": "5ee745d9f2597c7c7d2256e6785fdb72",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">2.7",
"size": 6280,
"upload_time": "2024-01-26T17:37:02",
"upload_time_iso_8601": "2024-01-26T17:37:02.032378Z",
"url": "https://files.pythonhosted.org/packages/3b/6f/7ec680a2cef12c9da11912e2e04f5c5d8fa3d9bcc436a157ecc48c027cff/pysxm-1.5.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-26 17:37:02",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "pysxm"
}