From a7d56f2d31ecfc809a25bc772ea9e9d30c0478e8 Mon Sep 17 00:00:00 2001 From: Tony Mack Date: Tue, 16 Feb 2010 17:38:40 +0000 Subject: [PATCH] adding xmlbuilder --- xmlbuilder-0.9/LICENSE | 21 +++ xmlbuilder-0.9/MANIFEST.in | 2 + xmlbuilder-0.9/PKG-INFO | 80 +++++++++ xmlbuilder-0.9/README.txt | 1 + xmlbuilder-0.9/setup.cfg | 5 + xmlbuilder-0.9/setup.py | 43 +++++ xmlbuilder-0.9/xmlbuilder.egg-info/PKG-INFO | 80 +++++++++ .../xmlbuilder.egg-info/SOURCES.txt | 11 ++ .../xmlbuilder.egg-info/dependency_links.txt | 1 + .../xmlbuilder.egg-info/top_level.txt | 1 + xmlbuilder-0.9/xmlbuilder/__init__.py | 153 ++++++++++++++++++ xmlbuilder-0.9/xmlbuilder/docs/long_descr.rst | 68 ++++++++ xmlbuilder-0.9/xmlbuilder/tests/__init__.py | 99 ++++++++++++ 13 files changed, 565 insertions(+) create mode 100644 xmlbuilder-0.9/LICENSE create mode 100644 xmlbuilder-0.9/MANIFEST.in create mode 100644 xmlbuilder-0.9/PKG-INFO create mode 100644 xmlbuilder-0.9/README.txt create mode 100644 xmlbuilder-0.9/setup.cfg create mode 100644 xmlbuilder-0.9/setup.py create mode 100644 xmlbuilder-0.9/xmlbuilder.egg-info/PKG-INFO create mode 100644 xmlbuilder-0.9/xmlbuilder.egg-info/SOURCES.txt create mode 100644 xmlbuilder-0.9/xmlbuilder.egg-info/dependency_links.txt create mode 100644 xmlbuilder-0.9/xmlbuilder.egg-info/top_level.txt create mode 100644 xmlbuilder-0.9/xmlbuilder/__init__.py create mode 100644 xmlbuilder-0.9/xmlbuilder/docs/long_descr.rst create mode 100644 xmlbuilder-0.9/xmlbuilder/tests/__init__.py diff --git a/xmlbuilder-0.9/LICENSE b/xmlbuilder-0.9/LICENSE new file mode 100644 index 00000000..0d0f57c4 --- /dev/null +++ b/xmlbuilder-0.9/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2008 Konstantin Danilov aka koder + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/xmlbuilder-0.9/MANIFEST.in b/xmlbuilder-0.9/MANIFEST.in new file mode 100644 index 00000000..207725e9 --- /dev/null +++ b/xmlbuilder-0.9/MANIFEST.in @@ -0,0 +1,2 @@ +include xmlbuild/docs *.rst +include . LICENSE \ No newline at end of file diff --git a/xmlbuilder-0.9/PKG-INFO b/xmlbuilder-0.9/PKG-INFO new file mode 100644 index 00000000..d931c15a --- /dev/null +++ b/xmlbuilder-0.9/PKG-INFO @@ -0,0 +1,80 @@ +Metadata-Version: 1.0 +Name: xmlbuilder +Version: 0.9 +Summary: Pythonic way to create xml files +Home-page: http://pypi.python.org/pypi/xmlbuilder +Author: koder +Author-email: koder_dot_mail@gmail_dot_com +License: MIT +Download-URL: http://pypi.python.org/pypi/xmlbuilder +Description: Example of usage: + ----------------- + + + from __future__ import with_statement + from xmlbuilder import XMLBuilder + x = XMLBuilder(format=True) + with x.root(a = 1): + with x.data: + [x << ('node',{'val':i}) for i in range(10)] + + print str(x) + + will print + + <root a="1"> + <data> + <node val="0" /> + <node val="1" /> + <node val="2" /> + <node val="3" /> + <node val="4" /> + <node val="5" /> + <node val="6" /> + <node val="7" /> + <node val="8" /> + <node val="9" /> + </data> + </root> + + Mercurial repo:http://hg.assembla.com/MyPackages/ + + Documentations + -------------- + `XMLBuilder` is simple library build on top of `ElementTree.TreeBuilder` to + simplify xml files creation as much as possible. Althow it can produce + structured result with identated child tags. `XMLBuilder` use python `with` + statement to define xml tag levels and `<<` operator for simple cases - + text and tag without childs. + + First we need to create xmlbuilder + + from xmlbuilder import XMLBuilder + # params - encoding = 'utf8', + # builder = None, - ElementTree.TreeBuilder + # tab_level = None, - current tab l;evel - for formatted output only + # format = False, - create formatted output + # tab_step = " " * 4 - indentation step + xml = XMLBuilder() + + + Use `with` statement to make document structure + #create and open tag 'root_tag' with text 'text' and attributes + with xml.root_tag(text,attr1=val1,attr2=val2): + #create and open tag 'sub_tag' + with xml.sub_tag(text,attr3=val3): + #create tag which are not valid python identificator + with xml('one-more-sub-tag',attr7=val37): + xml << "Some textual data" + #here tag 'one-more-sub-tag' are closed + #Tags without children can be created using `<<` operator + for val in range(15): + xml << ('message',"python rocks!"[:i]) + #create 15 child tag like <message> python r</message> + #all tags closed + node = ~x # get etree.ElementTree object + xml_data = str(x) + unicode_xml_data = unicode(x) + +Keywords: xml +Platform: UNKNOWN diff --git a/xmlbuilder-0.9/README.txt b/xmlbuilder-0.9/README.txt new file mode 100644 index 00000000..7a7131fc --- /dev/null +++ b/xmlbuilder-0.9/README.txt @@ -0,0 +1 @@ +Pythonic way to build xml files \ No newline at end of file diff --git a/xmlbuilder-0.9/setup.cfg b/xmlbuilder-0.9/setup.cfg new file mode 100644 index 00000000..b14b0bc3 --- /dev/null +++ b/xmlbuilder-0.9/setup.cfg @@ -0,0 +1,5 @@ +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + diff --git a/xmlbuilder-0.9/setup.py b/xmlbuilder-0.9/setup.py new file mode 100644 index 00000000..931cb315 --- /dev/null +++ b/xmlbuilder-0.9/setup.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +#------------------------------------------------------------------------------- +import os +import sys +import glob +import os.path +from setuptools import setup +#from distutils.core import setup +#------------------------------------------------------------------------------- +if 'upload' in sys.argv: + # for .pypirc file + try: + os.environ['HOME'] + except KeyError: + os.environ['HOME'] = '..\\' +#------------------------------------------------------------------------------- +fpath = lambda x : os.path.join(*x.split('/')) +#------------------------------------------------------------------------------- +PYPI_URL = 'http://pypi.python.org/pypi/xmlbuilder' +ld = open(fpath('xmlbuilder/docs/long_descr.rst')).read() +ld = ld.replace('&','&').replace('<','<').replace('>','>') +setup( + name = "xmlbuilder", + fullname = "xmlbuilder", + version = "0.9", + packages = ["xmlbuilder"], + package_dir = {'xmlbuilder':'xmlbuilder'}, + author = "koder", + author_email = "koder_dot_mail@gmail_dot_com", + maintainer = 'koder', + maintainer_email = "koder_dot_mail@gmail_dot_com", + description = "Pythonic way to create xml files", + license = "MIT", + keywords = "xml", + test_suite = "xml_buider.tests", + url = PYPI_URL, + download_url = PYPI_URL, + long_description = ld, + #include_package_data = True, + #package_data = {'xmlbuilder':["docs/*.rst"]}, + #data_files = [('', ['xmlbuilder/docs/long_descr.rst'])] +) +#------------------------------------------------------------------------------- diff --git a/xmlbuilder-0.9/xmlbuilder.egg-info/PKG-INFO b/xmlbuilder-0.9/xmlbuilder.egg-info/PKG-INFO new file mode 100644 index 00000000..d931c15a --- /dev/null +++ b/xmlbuilder-0.9/xmlbuilder.egg-info/PKG-INFO @@ -0,0 +1,80 @@ +Metadata-Version: 1.0 +Name: xmlbuilder +Version: 0.9 +Summary: Pythonic way to create xml files +Home-page: http://pypi.python.org/pypi/xmlbuilder +Author: koder +Author-email: koder_dot_mail@gmail_dot_com +License: MIT +Download-URL: http://pypi.python.org/pypi/xmlbuilder +Description: Example of usage: + ----------------- + + + from __future__ import with_statement + from xmlbuilder import XMLBuilder + x = XMLBuilder(format=True) + with x.root(a = 1): + with x.data: + [x << ('node',{'val':i}) for i in range(10)] + + print str(x) + + will print + + <root a="1"> + <data> + <node val="0" /> + <node val="1" /> + <node val="2" /> + <node val="3" /> + <node val="4" /> + <node val="5" /> + <node val="6" /> + <node val="7" /> + <node val="8" /> + <node val="9" /> + </data> + </root> + + Mercurial repo:http://hg.assembla.com/MyPackages/ + + Documentations + -------------- + `XMLBuilder` is simple library build on top of `ElementTree.TreeBuilder` to + simplify xml files creation as much as possible. Althow it can produce + structured result with identated child tags. `XMLBuilder` use python `with` + statement to define xml tag levels and `<<` operator for simple cases - + text and tag without childs. + + First we need to create xmlbuilder + + from xmlbuilder import XMLBuilder + # params - encoding = 'utf8', + # builder = None, - ElementTree.TreeBuilder + # tab_level = None, - current tab l;evel - for formatted output only + # format = False, - create formatted output + # tab_step = " " * 4 - indentation step + xml = XMLBuilder() + + + Use `with` statement to make document structure + #create and open tag 'root_tag' with text 'text' and attributes + with xml.root_tag(text,attr1=val1,attr2=val2): + #create and open tag 'sub_tag' + with xml.sub_tag(text,attr3=val3): + #create tag which are not valid python identificator + with xml('one-more-sub-tag',attr7=val37): + xml << "Some textual data" + #here tag 'one-more-sub-tag' are closed + #Tags without children can be created using `<<` operator + for val in range(15): + xml << ('message',"python rocks!"[:i]) + #create 15 child tag like <message> python r</message> + #all tags closed + node = ~x # get etree.ElementTree object + xml_data = str(x) + unicode_xml_data = unicode(x) + +Keywords: xml +Platform: UNKNOWN diff --git a/xmlbuilder-0.9/xmlbuilder.egg-info/SOURCES.txt b/xmlbuilder-0.9/xmlbuilder.egg-info/SOURCES.txt new file mode 100644 index 00000000..57272a81 --- /dev/null +++ b/xmlbuilder-0.9/xmlbuilder.egg-info/SOURCES.txt @@ -0,0 +1,11 @@ +LICENSE +MANIFEST.in +README.txt +setup.py +xmlbuilder/__init__.py +xmlbuilder.egg-info/PKG-INFO +xmlbuilder.egg-info/SOURCES.txt +xmlbuilder.egg-info/dependency_links.txt +xmlbuilder.egg-info/top_level.txt +xmlbuilder/docs/long_descr.rst +xmlbuilder/tests/__init__.py \ No newline at end of file diff --git a/xmlbuilder-0.9/xmlbuilder.egg-info/dependency_links.txt b/xmlbuilder-0.9/xmlbuilder.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/xmlbuilder-0.9/xmlbuilder.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/xmlbuilder-0.9/xmlbuilder.egg-info/top_level.txt b/xmlbuilder-0.9/xmlbuilder.egg-info/top_level.txt new file mode 100644 index 00000000..9f1d4861 --- /dev/null +++ b/xmlbuilder-0.9/xmlbuilder.egg-info/top_level.txt @@ -0,0 +1 @@ +xmlbuilder diff --git a/xmlbuilder-0.9/xmlbuilder/__init__.py b/xmlbuilder-0.9/xmlbuilder/__init__.py new file mode 100644 index 00000000..1be17b0f --- /dev/null +++ b/xmlbuilder-0.9/xmlbuilder/__init__.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +#------------------------------------------------------------------------------- +from __future__ import with_statement +#------------------------------------------------------------------------------- +from xml.etree.ElementTree import TreeBuilder,tostring +#------------------------------------------------------------------------------- +__all__ = ["XMLBuilder"] +__doc__ = """ +XMLBuilder is simple library build on top of ElementTree.TreeBuilder to +simplify xml files creation as much as possible. Althow it can produce +structured result with identated child tags. `XMLBuilder` use python `with` +statement to define xml tag levels and `<<` operator for simple cases - +text and tag without childs. + +from __future__ import with_statement +from xmlbuilder import XMLBuilder +x = XMLBuilder(format=True) +with x.root(a = 1): + with x.data: + [x << ('node',{'val':i}) for i in range(10)] + +etree_node = ~x +print str(x) +""" +#------------------------------------------------------------------------------- +class _XMLNode(object): + """Class for internal usage""" + def __init__(self,parent,name,builder): + self.builder = builder + self.name = name + self.text = [] + self.attrs = {} + self.entered = False + self.parent = parent + def __call__(self,*dt,**mp): + text = "".join(dt) + if self.entered: + self.builder.data(text) + else: + self.text.append(text) + if self.entered: + raise ValueError("Can't add attributes to already opened element") + smp = dict((k,str(v)) for k,v in mp.items()) + self.attrs.update(smp) + return self + def __enter__(self): + self.parent += 1 + self.builder.start(self.name,self.attrs) + self.builder.data("".join(self.text)) + self.entered = True + return self + def __exit__(self,x,y,z): + self.parent -= 1 + self.builder.end(self.name) + return False +#------------------------------------------------------------------------------- +class XMLBuilder(object): + """XmlBuilder(encoding = 'utf-8', # result xml file encoding + builder = None, #etree.TreeBuilder or compatible class + tab_level = None, #current tabulation level - string + format = False, # make formatted output + tab_step = " " * 4) # tabulation step + use str(builder) or unicode(builder) to get xml text or + ~builder to obtaine etree.ElementTree + """ + def __init__(self,encoding = 'utf-8', + builder = None, + tab_level = None, + format = False, + tab_step = " " * 4): + self.__builder = builder or TreeBuilder() + self.__encoding = encoding + if format : + if tab_level is None: + tab_level = "" + if tab_level is not None: + if not format: + raise ValueError("format is False, but tab_level not None") + self.__tab_level = tab_level # current format level + self.__tab_step = tab_step # format step + self.__has_sub_tag = False # True, if current tag had childrens + self.__node = None + # called from _XMLNode when tag opened + def __iadd__(self,val): + self.__has_sub_tag = False + if self.__tab_level is not None: + self.__builder.data("\n" + self.__tab_level) + self.__tab_level += self.__tab_step + return self + # called from XMLNode when tag closed + def __isub__(self,val): + if self.__tab_level is not None: + self.__tab_level = self.__tab_level[:-len(self.__tab_step)] + if self.__has_sub_tag: + self.__builder.data("\n" + self.__tab_level) + self.__has_sub_tag = True + return self + def __getattr__(self,name): + return _XMLNode(self,name,self.__builder) + def __call__(self,name,*dt,**mp): + x = _XMLNode(self,name,self.__builder) + x(*dt,**mp) + return x + #create new tag or add text + #possible shift values + #string - text + #tuple(string1,string2,dict) - new tag with name string1,attrs = dict,and text string2 + #dict and string2 are optional + def __lshift__(self,val): + if isinstance(val,basestring): + self.__builder.data(val) + else: + self.__has_sub_tag = True + assert hasattr(val,'__len__'),\ + 'Shifted value should be tuple or list like object not %r' % val + assert hasattr(val,'__getitem__'),\ + 'Shifted value should be tuple or list like object not %r' % val + name = val[0] + if len(val) == 3: + text = val[1] + attrs = val[2] + elif len(val) == 1: + text = "" + attrs = {} + elif len(val) == 2: + if isinstance(val[1],basestring): + text = val[1] + attrs = {} + else: + text = "" + attrs = val[1] + if self.__tab_level is not None: + self.__builder.data("\n" + self.__tab_level) + self.__builder.start(name, + dict((k,str(v)) for k,v in attrs.items())) + if text: + self.__builder.data(text) + self.__builder.end(name) + return self # to allow xml << some1 << some2 << some3 + #close builder + def __invert__(self): + if self.__node is not None: + return self.__node + self.__node = self.__builder.close() + return self.__node + def __str__(self): + """return generated xml""" + return tostring(~self,self.__encoding) + def __unicode__(self): + """return generated xml""" + res = tostring(~self,self.__encoding) + return res.decode(self.__encoding) +#------------------------------------------------------------------------------- diff --git a/xmlbuilder-0.9/xmlbuilder/docs/long_descr.rst b/xmlbuilder-0.9/xmlbuilder/docs/long_descr.rst new file mode 100644 index 00000000..4e82bc85 --- /dev/null +++ b/xmlbuilder-0.9/xmlbuilder/docs/long_descr.rst @@ -0,0 +1,68 @@ +Example of usage: +----------------- + + +from __future__ import with_statement +from xmlbuilder import XMLBuilder +x = XMLBuilder(format=True) +with x.root(a = 1): + with x.data: + [x << ('node',{'val':i}) for i in range(10)] + +print str(x) + +will print + + + + + + + + + + + + + + + + +Mercurial repo:http://hg.assembla.com/MyPackages/ + +Documentations +-------------- +`XMLBuilder` is simple library build on top of `ElementTree.TreeBuilder` to +simplify xml files creation as much as possible. Althow it can produce +structured result with identated child tags. `XMLBuilder` use python `with` +statement to define xml tag levels and `<<` operator for simple cases - +text and tag without childs. + +First we need to create xmlbuilder + + from xmlbuilder import XMLBuilder + # params - encoding = 'utf8', + # builder = None, - ElementTree.TreeBuilder + # tab_level = None, - current tab l;evel - for formatted output only + # format = False, - create formatted output + # tab_step = " " * 4 - indentation step + xml = XMLBuilder() + + +Use `with` statement to make document structure + #create and open tag 'root_tag' with text 'text' and attributes + with xml.root_tag(text,attr1=val1,attr2=val2): + #create and open tag 'sub_tag' + with xml.sub_tag(text,attr3=val3): + #create tag which are not valid python identificator + with xml('one-more-sub-tag',attr7=val37): + xml << "Some textual data" + #here tag 'one-more-sub-tag' are closed + #Tags without children can be created using `<<` operator + for val in range(15): + xml << ('message',"python rocks!"[:i]) + #create 15 child tag like python r + #all tags closed + node = ~x # get etree.ElementTree object + xml_data = str(x) + unicode_xml_data = unicode(x) diff --git a/xmlbuilder-0.9/xmlbuilder/tests/__init__.py b/xmlbuilder-0.9/xmlbuilder/tests/__init__.py new file mode 100644 index 00000000..67eaa67f --- /dev/null +++ b/xmlbuilder-0.9/xmlbuilder/tests/__init__.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +from __future__ import with_statement +#------------------------------------------------------------------------------- +import unittest +from xml.etree.ElementTree import fromstring +#------------------------------------------------------------------------------- +from xmlbuilder import XMLBuilder +#------------------------------------------------------------------------------- +def xmlStructureEqual(xml1,xml2): + tree1 = fromstring(xml1) + tree2 = fromstring(xml2) + return _xmlStructureEqual(tree1,tree2) +#------------------------------------------------------------------------------- +def _xmlStructureEqual(tree1,tree2): + if tree1.tag != tree2.tag: + return False + attr1 = list(tree1.attrib.items()) + attr1.sort() + attr2 = list(tree2.attrib.items()) + attr2.sort() + if attr1 != attr2: + return False + return tree1.getchildren() == tree2.getchildren() +#------------------------------------------------------------------------------- +result1 = \ +""" + + + + + xyz + abc + + + + test + + +""".strip() +#------------------------------------------------------------------------------- +class TestXMLBuilder(unittest.TestCase): + def testShift(self): + xml = (XMLBuilder() << ('root',)) + self.assertEqual(str(xml),"") + + xml = XMLBuilder() + xml << ('root',"some text") + self.assertEqual(str(xml),"some text") + + xml = XMLBuilder() + xml << ('root',{'x':1,'y':'2'}) + self.assert_(xmlStructureEqual(str(xml),"some text")) + + xml = XMLBuilder() + xml << ('root',{'x':1,'y':'2'}) + self.assert_(xmlStructureEqual(str(xml),"")) + + xml = XMLBuilder() + xml << ('root',{'x':1,'y':'2'}) + self.assert_(not xmlStructureEqual(str(xml),"")) + + + xml = XMLBuilder() + xml << ('root',"gonduras.ua",{'x':1,'y':'2'}) + self.assert_(xmlStructureEqual(str(xml),"gonduras.ua")) + + xml = XMLBuilder() + xml << ('root',"gonduras.ua",{'x':1,'y':'2'}) + self.assert_(xmlStructureEqual(str(xml),"gonduras.com")) + #--------------------------------------------------------------------------- + def testWith(self): + xml = XMLBuilder() + with xml.root(lenght = 12): + pass + self.assertEqual(str(xml),'') + + xml = XMLBuilder() + with xml.root(): + xml << "text1" << "text2" << ('some_node',) + self.assertEqual(str(xml),"text1text2") + #--------------------------------------------------------------------------- + def testFormat(self): + x = XMLBuilder('utf-8',format = True) + with x.root(): + x << ('array',) + with x.array(len = 10): + with x.el(val = 0): + pass + with x.el('xyz',val = 1): + pass + x << ("el","abc",{'val':2}) << ('el',dict(val=3)) + x << ('el',dict(val=4)) << ('el',dict(val='5')) + with x('sup-el',val = 23): + x << "test " + self.assertEqual(str(x),result1) +#------------------------------------------------------------------------------- +if __name__ == '__main__': + unittest.main() +#------------------------------------------------------------------------------- -- 2.43.0