diff --git a/nagare/namespaces/common.py b/nagare/namespaces/common.py deleted file mode 100644 index 81ddee0..0000000 --- a/nagare/namespaces/common.py +++ /dev/null @@ -1,52 +0,0 @@ -#-- -# Copyright (c) 2008-2013 Net-ng. -# All rights reserved. -# -# This software is licensed under the BSD License, as described in -# the file LICENSE.txt, which you should have received as part of -# this distribution. -#-- - -"""Base class of all the renderers""" - -import random - - -class Renderer(object): - def new(self): - """Create a new renderer from the same type of this renderer - """ - return self.__class__(self) - - def start_rendering(self, comp, model): - """Method calls before to render a component - - In: - - ``comp`` -- the component to render - - ``model`` -- the view to render - """ - pass - - def end_rendering(self, output): - """Method call after the rendering of the component - - In: - - ``output`` -- the rendering tree - """ - return output - - def generate_id(self, prefix=''): - """Generate a random id - - In: - - ``prefix`` -- prefix of the generated id - """ - return prefix + str(random.randint(10000000, 99999999)) - - def __reduce__(self): - """Prevent a renderer to be pickled - - Prevent the common error of capturing the renderer into the closure - of a callback - """ - raise TypeError("can't pickle Renderer objects (are you using a renderer object in a callback ?)") diff --git a/nagare/namespaces/esi.py b/nagare/namespaces/esi.py deleted file mode 100644 index 12add45..0000000 --- a/nagare/namespaces/esi.py +++ /dev/null @@ -1,61 +0,0 @@ -#-- -# Copyright (c) 2008-2013 Net-ng. -# All rights reserved. -# -# This software is licensed under the BSD License, as described in -# the file LICENSE.txt, which you should have received as part of -# this distribution. -#-- - -"""Edge Server-side Include renderer""" - -from lxml import etree as ET - -from nagare.namespaces import xml -from nagare.namespaces.xml import TagProp - -# Official ESI namespace -NS = 'http://www.edge-delivery.org/esi/1.0' - - -class Renderer(xml.XmlRenderer): - """ The ESI renderer - """ - - # The ESI tags - # ------------ - - include = TagProp('include', set(('src', 'alt', 'onerror'))) - inline = TagProp('inline', set(('name', 'fetchable'))) - choose = TagProp('choose', set()) - when = TagProp('when', set(('test',))) - otherwise = TagProp('otherwise', set()) - try_ = TagProp('try', set()) - attempt = TagProp('attempt', set()) - except_ = TagProp('except', set()) - comment = TagProp('comment', set(('text',))) - remove = TagProp('remove', set()) - vars = TagProp('vars', set()) - - def esi(self, text): - """Generate a ``esi`` comment element - - In: - - ``text`` -- comment text - - Return: - - the comment element - """ - return ET.Comment('esi ' + text) - -if __name__ == '__main__': - from nagare.namespaces import xhtml - - h = xhtml.Renderer() - s = Renderer() - s.namespaces = {'esi': NS} - s.default_namespace = 'esi' - - html = h.html(h.body(h.h1('hello'), s.include(dict(src='http://www.net-ng.com'), s.include(src='http://www.net-ng.com')), h.p('world'))) - - print html.write_xmlstring(pretty_print=True) diff --git a/nagare/namespaces/test/helloworld.html b/nagare/namespaces/test/helloworld.html deleted file mode 100644 index 56c0549..0000000 --- a/nagare/namespaces/test/helloworld.html +++ /dev/null @@ -1,7 +0,0 @@ - -

english : hello world

-

french : bonjour monde

-

chinese : 你好世界

-

russian : здравствулте! мир

-

japanese : こんにちは世界

- \ No newline at end of file diff --git a/nagare/namespaces/test/test_xmlns.py b/nagare/namespaces/test/test_xmlns.py deleted file mode 100644 index 5393535..0000000 --- a/nagare/namespaces/test/test_xmlns.py +++ /dev/null @@ -1,780 +0,0 @@ -#-- -# Copyright (c) 2008-2013 Net-ng. -# All rights reserved. -# -# This software is licensed under the BSD License, as described in -# the file LICENSE.txt, which you should have received as part of -# this distribution. -#-- - -from __future__ import with_statement - -import csv -import os -from types import ListType - -from lxml import etree as ET - -from nagare.namespaces import xml - - -def append_text_test1(): - """ XML namespace unit test - append_text Append text to an empty node - - In: - - - - Out: - - test - """ - x = xml.Renderer() - - node = x.node() - node.append_text('test') - assert node.text == 'test' - assert node.write_xmlstring() == 'test' - - -def append_text_test2(): - """ XML namespace unit test - append_text - Append text to node with text child - - In: - - test1 - - Out: - - test1test2 - """ - x = xml.Renderer() - - node = x.node('test1') - node.append_text('test2') - assert node.text == 'test1test2' - assert node.write_xmlstring() == 'test1test2' - - -def append_text_test3(): - """ XML namespace unit test - append_text - Append text to node with node child - - In: - - - - Out: - - test - """ - x = xml.Renderer() - - node = x.node(x.child()) - node.append_text('test') - assert node.getchildren()[0].tail == 'test' - assert node.write_xmlstring() == 'test' - - -def append_text_test4(): - """ XML namespace unit test - append_text - Append text to node with text & node children - - In: - - test1 - - Out: - - test1test2 - """ - x = xml.Renderer() - - node = x.node(['test1', x.child()]) - node.append_text('test2') - assert node.text == 'test1' - assert node.getchildren()[0].tail == 'test2' - assert node.write_xmlstring() == 'test1test2' - - -def add_child_test1(): - """ XML namespace unit test - add_child - add text - - In: - - - - Out: - - test - """ - x = xml.Renderer() - - node = x.node('test') - assert node.text == 'test' - assert node.write_xmlstring() == 'test' - - -def add_child_test2(): - """ XML namespace unit test - add_child - add node - - In: - - - - Out: - - - """ - x = xml.Renderer() - - child = x.child() - node = x.node(child) - assert node.getchildren()[0] == child - assert node.write_xmlstring() == '' - - -def add_child_test3(): - """ XML namespace unit test - add_child - add dictionnary - - In: - - - - Out: - - - """ - x = xml.Renderer() - - node = x.node({'test': 'test'}) - assert node.attrib == {'test': 'test'} - assert node.write_xmlstring() == '' - - -def add_child_test4(): - """ XML namespace unit test - add_child - add attribute with keyword - - In: - - - - Out: - - - """ - x = xml.Renderer() - - node = x.node(test='test') - assert node.attrib == {'test': 'test'} - assert node.write_xmlstring() == '' - - -def add_child_test5(): - """ XML namespace unit test - add_child - add tuple (text, node, text, dict) - - In: - - - - Out: - - testtest - """ - x = xml.Renderer() - - child = x.child() - node = x.node(('test', child, 'test', {'test': 'test'})) - - assert node.attrib == {'test': 'test'} - assert node.text == 'test' - assert node.getchildren()[0] == child - assert node.getchildren()[0].tail == 'test' - assert node.write_xmlstring() == 'testtest' - - -def add_child_test6(): - """ XML namespace unit test - add_child - add list [text, node, text, dict] - - In: - - - - Out: - - testtest - """ - x = xml.Renderer() - - child = x.child() - node = x.node(['test', child, 'test', {'test':'test'}]) - - assert node.attrib == {'test': 'test'} - assert node.text == 'test' - assert node.getchildren()[0] == child - assert node.getchildren()[0].tail == 'test' - assert node.write_xmlstring() == 'testtest' - - -def add_child_test7(): - """ XML namespace unit test - add_child - add int - - In: - - - - Out: - - 42 - """ - x = xml.Renderer() - - node = x.node(42) - assert node.text == '42' - assert node.write_xmlstring() == '42' - - -def add_child_test8(): - """ XML namespace unit test - add_child - add float - - In: - - - - Out: - - 0.1 - """ - x = xml.Renderer() - - node = x.node(0.1) - assert node.text == '0.1' - assert node.write_xmlstring() == '0.1' - - -def add_child_test9(): - """ XML namespace unit test - add_child - add dictionnary with python keyword - - In: - - - - Out: - - - """ - x = xml.Renderer() - - node = x.node({'class_': 'test'}) - assert node.attrib == {'class': 'test'} - assert node.write_xmlstring() == '' - - -def add_child_test10(): - """ XML namespace unit test - add_child - add attribute with python keyword - - In: - - - - Out: - - - """ - x = xml.Renderer() - - node = x.node(class_='test') - assert node.attrib == {'class': 'test'} - assert node.write_xmlstring() == '' - - -def add_child_test11(): - """ XML namespace unit test - add_child - add object instance and raise exception - - In: - - - - Out: - - Exception - """ - x = xml.Renderer() - - try: - x.node(object()) - except Exception: - assert True - else: - assert False - - -def replace_test1(): - """ XML namespace unit test - replace - replace simple node by node - - In: - - - - Out: - - - """ - x = xml.Renderer() - - child1 = x.child1() - node = x.node(child1) - assert node.getchildren()[0] == child1 - child2 = x.child2() - child1.replace(child2) - assert node.getchildren()[0] == child2 - assert node.write_xmlstring() == '' - - -def replace_test2(): - """ XML namespace unit test - replace - replace simple node with text before by node - - In: - - - - Out: - - - """ - x = xml.Renderer() - - child1 = x.child1() - node = x.node('test', child1) - assert node.getchildren()[0] == child1 - child2 = x.child2() - child1.replace(child2) - assert node.getchildren()[0] == child2 - assert node.write_xmlstring() == 'test' - - -def replace_test3(): - """ XML namespace unit test - replace - replace simple node with text after by node - - In: - - - - Out: - - - """ - x = xml.Renderer() - - child1 = x.child1() - node = x.node(child1, 'test') - assert node.getchildren()[0] == child1 - child2 = x.child2() - child1.replace(child2) - assert node.getchildren()[0] == child2 - assert node.write_xmlstring() == 'test' - - -def replace_test4(): - """ XML namespace unit test - replace - replace simple node by text - - In: - - - - Out: - - test - """ - x = xml.Renderer() - - child1 = x.child1() - node = x.node(child1) - assert node.getchildren()[0] == child1 - child1.replace('test') - assert node.text == 'test' - assert node.write_xmlstring() == 'test' - - -def replace_test5(): - """ XML namespace unit test - replace - replace simple node by node + text - - In: - - - - Out: - - test - """ - x = xml.Renderer() - - child1 = x.child1() - node = x.node(child1) - assert node.getchildren()[0] == child1 - child2 = x.child2() - child1.replace('test', child2) - assert node.text == 'test' - assert node.write_xmlstring() == 'test' - - -def replace_test6(): - """ XML namespace unit test - replace - replace root node - - In: - - - - Out: - - - """ - x = xml.Renderer() - - node = x.node() - node.replace('test') - assert node.write_xmlstring() == '' - -xml_test1_in = """ - - - -""" - - -def repeat_test1(): - """ XML namespace unit test - repeat - Repeat with 2 simple text, use childname argument""" - x = xml.Renderer() - node = x.parse_xmlstring(xml_test1_in) - iterator = node.repeat(['test1', 'test2'], childname='child') - - for child, value in iterator: - child.append_text(value) - assert [child.text for child in node.getchildren()] == ['test1', 'test2'] - - -def repeat_test2(): - """ XML namespace unit test - repeat - Repeat with 2 simple text, don't use childname argument""" - x = xml.Renderer() - node = x.parse_xmlstring(xml_test1_in) - child = node.findmeld('child') - iterator = child.repeat(['test1', 'test2']) - - for child, value in iterator: - child.append_text(value) - assert [child.text for child in node.getchildren()] == ['test1', 'test2'] - - -def repeat_test3(): - """ XML namespace unit test - repeat - findmeld in repeat loop """ - h = xml.Renderer() - - xhtml_tree_2 = '
  • count
' - - root = h.parse_xmlstring(xhtml_tree_2, fragment=True)[0] - - for (elem, count) in root.repeat(range(2), 'entry'): - elem.findmeld('count').fill(count) - - h << root - - assert h.root.write_xmlstring() == '
  • 0
  • 1
' - - -def root_test1(): - """ XML namespace unit test - root - one element """ - x = xml.Renderer() - x << x.node() - - assert not isinstance(x.root, ListType) - - -def root_test2(): - """ XML namespace unit test - root - two elements """ - x = xml.Renderer() - x << x.node() - x << x.node() - - assert isinstance(x.root, ListType) - - -def parse_xmlstring_test1(): - """ XML namespace unit test - parse_xmlstring - good encoding """ - try: - x = xml.Renderer() - f = open(os.path.join(os.path.dirname(__file__), 'test_xmlns_1.xml')) - x.parse_xmlstring(f.read()) - f.close() - except UnicodeDecodeError: - assert False - else: - assert True - - -def parse_xmlstring_test2(): - """ XML namespace unit test - parse_xmlstring - bad encoding """ - try: - x = xml.Renderer() - f = open(os.path.join(os.path.dirname(__file__), 'iso-8859.xml')) - x.parse_xml(f, encoding='utf-8') - f.close() - except ET.XMLSyntaxError: - assert True - else: - assert False - - -xml_fragments_1 = """leading_texttext""" - - -def parse_xmlstring_test3(): - """ XML namespace unit test - parse_xmlstring - parse fragment xml with fragment flag """ - x = xml.Renderer() - roots = x.parse_xmlstring(xml_fragments_1, fragment=True) - assert roots[0] == 'leading_text' - assert roots[1].write_xmlstring() == "text" - assert roots[1].tail == "text" - assert roots[2].write_xmlstring() == "" - - -def parse_xmlstring_test4(): - """ XML namespace unit test - parse_xmlstring - parse xml tree with fragment flag """ - x = xml.Renderer() - roots = x.parse_xmlstring(xml_fragments_1, fragment=True, no_leading_text=True) - assert roots[0].write_xmlstring() == "text" - assert roots[0].tail == "text" - assert roots[1].write_xmlstring() == "" - - -xml_tree_1 = "text" - - -def parse_xmlstring_test5(): - """ XML namespace unit test - parse_xmlstring - Test parse child type """ - x = xml.Renderer() - root = x.parse_xmlstring(xml_tree_1) - assert type(root) == xml._Tag - - -def parse_xml_test1(): - """ XML namespace unit test - parse_xmlstring - good encoding """ - try: - x = xml.Renderer() - x.parse_xml(os.path.join(os.path.dirname(__file__), 'test_xmlns_1.xml')) - except UnicodeDecodeError: - assert False - else: - assert True - - -def findmeld_test1(): - """ XML namespace unit test - find_meld - one element """ - x = xml.Renderer() - node = x.parse_xmlstring(xml_test1_in) - child = node.findmeld('child') - - assert child is not None - - -def findmeld_test2(): - """ XML namespace unit test - find_meld - zero element """ - x = xml.Renderer() - node = x.parse_xmlstring("""""") - child = node.findmeld('child') - assert child is None - - -def findmeld_test3(): - """ XML namespace unit test - find_meld - zero element and default argument """ - x = xml.Renderer() - node = x.parse_xmlstring("""""") - child = node.findmeld('child', 'test') - assert child == 'test' - -# Test for XML namespace - -xml_test2_in = """ - - - - This is the title - - -
-
-
- - - - - - - - - - - -
NameDescription
NameDescription
- -
-
- - """ - - -def global_test1(): - """ XML namespace unit test - create xml by procedural way """ - x = xml.Renderer() - - filePath = os.path.join(os.path.dirname(__file__), 'helloworld.csv') - - reader = csv.reader(open(filePath, 'r')) - - with x.helloWorlds: - for row in reader: - with x.helloWorld(language=row[0].decode('utf-8')): - x << row[1].decode('utf-8') - - xmlToTest = x.root.write_xmlstring(xml_declaration=True, pretty_print=True).strip() - - f = open(os.path.join(os.path.dirname(__file__), 'test_xmlns_1.xml')) - xmlToCompare = f.read() - f.close() - assert xmlToTest == xmlToCompare - - -def global_test2(): - """ XML namespace unit test - create xml by functionnal way """ - x = xml.Renderer() - - filePath = os.path.join(os.path.dirname(__file__), 'helloworld.csv') - - reader = csv.reader(open(filePath, 'r')) - - root = x.helloWorlds([x.helloWorld(row[1].decode('utf-8'), - {'language':row[0].decode('utf-8')}) for row in reader]) - - xmlToTest = root.write_xmlstring(xml_declaration=True, pretty_print=True).strip() - - f = open(os.path.join(os.path.dirname(__file__), 'test_xmlns_1.xml')) - xmlToCompare = f.read() - f.close() - assert xmlToTest == xmlToCompare - - -def global_test3(): - """ XML namespace unit test - test parse_xmlstring method """ - x = xml.Renderer() - - f = open(os.path.join(os.path.dirname(__file__), 'test_xmlns_1.xml')) - root = x.parse_xmlstring(f.read()) - f.close() - - xmlToTest = root.write_xmlstring(xml_declaration=True, pretty_print=True).strip() - - f = open(os.path.join(os.path.dirname(__file__), 'test_xmlns_1.xml')) - xmlToCompare = f.read() - f.close() - assert xmlToTest == xmlToCompare - - -def global_test4(): - """ XML namespace unit test - meld3 - test findmeld with children affectation """ - - x = xml.Renderer() - root = x.parse_xmlstring(xml_test2_in) - - root.findmeld('title').text = 'My document' - root.findmeld('form1').set('action', './handler') - data = ( - {'name': 'Girls', - 'description': 'Pretty'}, - {'name': 'Boys', - 'description': 'Ugly'}, - ) - - iterator = root.findmeld('tr').repeat(data) - for element, item in iterator: - td1 = element.findmeld('td1') - td1.text = item['name'] - element.findmeld('td2').text = item['description'] - - assert [elt.text for elt in root.xpath('.//x:td', namespaces={'x': 'http://www.w3.org/1999/xhtml'})] == ['Girls', 'Pretty', 'Boys', 'Ugly'] - assert root[0][1].text == 'My document' - assert root.xpath('.//x:form', namespaces={'x': 'http://www.w3.org/1999/xhtml'})[0].attrib['action'] == './handler' - - -def global_test5(): - """ XML namespace unit test - meld3 - test findmeld & replace method """ - x = xml.Renderer() - root = x.parse_xmlstring(xml_test2_in) - - root.findmeld('title').text = 'My document' - root.findmeld('form1').set('action', './handler') - - data = ( - {'name': 'Girls', - 'description': 'Pretty'}, - {'name': 'Boys', - 'description': 'Ugly'}, - ) - - children = [] - for elt in data: - children.append(x.tr([x.td(elt['name']), x.td(elt['description'])], {'class': 'bar'})) - - root.findmeld('tr').replace(children) - - assert root.findall('.//tr')[1].attrib['class'] == 'bar' - assert [elt.text for elt in root.xpath('.//td')] == ['Girls', 'Pretty', 'Boys', 'Ugly'] - - -def global_test6(): - """ XML namespace unit test - meld3 - test option write_xmlstring method with option pipeline=False """ - x = xml.Renderer() - root = x.parse_xmlstring(xml_test2_in) - - root.findmeld('title').text = 'My document' - root.findmeld('form1').set('action', './handler') - - data = ( - {'name': 'Girls', - 'description': 'Pretty'}, - {'name': 'Boys', - 'description': 'Ugly'}, - ) - - children = [] - for elt in data: - children.append(x.tr([x.td(elt['name']), x.td(elt['description'])], {'class': 'bar'})) - - root.findmeld('tr').replace(children) - - root.write_xmlstring(xml_declaration=True, pretty_print=True, pipeline=False).strip() - - assert root.findmeld('tr') is None - assert root.findmeld('content_well') is None - - -def global_test7(): - """ XML namespace unit test - meld3 - test option write_xmlstring method with option pipeline=True """ - x = xml.Renderer() - root = x.parse_xmlstring(xml_test2_in) - - root.findmeld('title').text = 'My document' - root.findmeld('form1').set('action', './handler') - - data = ( - {'name': 'Girls', - 'description': 'Pretty'}, - {'name': 'Boys', - 'description': 'Ugly'}, - ) - - children = [] - for elt in data: - children.append(x.tr([x.td(elt['name']), x.td(elt['description'])], {'class': 'bar'})) - - root.findmeld('tr').replace(children) - - root.write_xmlstring(xml_declaration=True, pretty_print=True, pipeline=False).strip() - - assert root.findmeld('tr') is None - assert root.findmeld('content_well') is None - - -def global_test8(): - """ XML namespace unit test - create xml """ - x = xml.Renderer() - x.namespaces = {'meld': 'http://www.plope.com/software/meld3'} - data = ( - {'name': 'Girls', - 'description': 'Pretty'}, - {'name': 'Boys', - 'description': 'Ugly'}, - ) - - with x.html: - with x.head: - with x.meta: - x << {'content': 'text/html; charset=ISO-8859-1', 'http-equiv': 'content-type'} - with x.title.meld_id('title'): - x << 'My document' - with x.body: - with x.div: - pass - x << x.comment(' empty tag ') - with x.div: - with x.form.meld_id('form1'): - x << {'action': './handler'} - with x.table: - with x.tbody: - with x.tr: - x << x.th('Name') << x.th('Description') - for elt in data: - with x.tr.meld_id('tr'): - x << x.td(elt['name']).meld_id('td') << x.td(elt['description']).meld_id('td') - with x.input: - x << {'type': 'submit', 'name': 'next', 'value': ' Next '} - - assert [elt.text for elt in x.root.xpath('.//td')] == ['Girls', 'Pretty', 'Boys', 'Ugly'] - assert x.root[0][1].text == 'My document' - assert x.root.xpath('.//form')[0].attrib['action'] == './handler' diff --git a/nagare/namespaces/test/test_xslns.py b/nagare/namespaces/test/test_xslns.py index 9cc4a8f..2878a31 100644 --- a/nagare/namespaces/test/test_xslns.py +++ b/nagare/namespaces/test/test_xslns.py @@ -9,43 +9,10 @@ from __future__ import with_statement -import os - from nagare.namespaces import xsl -from nagare.namespaces import xml from nagare.namespaces import xhtml -def test1(): - """ XSL namespace unit test - simple xsl transformation 1 """ - x = xsl.Renderer() - x.namespaces = {'xsl': 'http://www.w3.org/1999/XSL/Transform'} - x.default_namespace = 'xsl' - - styleSheet = x.stylesheet( - x.output(encoding="utf-8", method="html"), - x.template(x.copy(x.apply_templates(select="@*|node()")), match="@*|node()"), - x.template(x.element(name="head"), - x.element(x.element(x.apply_templates(select="@*|node()"), name="body"), name="html"), - match="helloWorlds"), - x.template(x.element(x.value_of(select="@language"), ' : ', x.value_of(select="."), name="h1"), match="helloWorld") - ) - - x = xml.Renderer() - - f = open(os.path.join(os.path.dirname(__file__), 'test_xmlns_1.xml')) - root = x.parse_xmlstring(f.read()) - f.close() - - r = root.getroottree().xslt(styleSheet) - - f = open(os.path.join(os.path.dirname(__file__), 'helloworld.html')) - xmlToCompare = f.read() - f.close() - - assert r.__str__().strip() == xmlToCompare - - def test2(): """ XSL namespace unit test - simple xsl transformation 2 """ x = xsl.Renderer() diff --git a/nagare/namespaces/xhtml_base.py b/nagare/namespaces/xhtml_base.py deleted file mode 100644 index 13590a5..0000000 --- a/nagare/namespaces/xhtml_base.py +++ /dev/null @@ -1,423 +0,0 @@ -#-- -# Copyright (c) 2008-2013 Net-ng. -# All rights reserved. -# -# This software is licensed under the BSD License, as described in -# the file LICENSE.txt, which you should have received as part of -# this distribution. -#-- - -"""The XHTML renderer - -This renderer only depends of the ``nagare.namespaces.xml`` module. -Having not dependencies to the framework make it suitable to be used in others frameworks. -""" - -from __future__ import with_statement - -import cStringIO -import urllib -import peak - -from lxml import etree as ET - -from nagare.namespaces import xml -from nagare.namespaces.xml import TagProp - -# --------------------------------------------------------------------------- - -# Common attributes -# ----------------- - -componentattrs = ('id', 'class', 'style', 'title') -i18nattrs = ('lang', 'dir') -eventattrs = ('onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmousemove', 'onmouseover', 'onmouseout', 'onkeypress', 'onkeydown', 'onkeyup') -allattrs = componentattrs + i18nattrs + eventattrs -focusattrs = ('accesskey', 'tabindex', 'onfocus', 'onblur') - -class _HTMLTag(xml._Tag): - """A xhtml tag - """ - def write_xmlstring(self, encoding='utf-8', pipeline=True, **kw): - """Serialize in XML the tree beginning at this tag - - In: - - ``encoding`` -- encoding of the XML - - ``pipeline`` -- if False, the ``meld:id`` attributes are deleted - - Return: - - the XML - """ - return xml._Tag.write_xmlstring(self.decorate_error(), encoding, pipeline, **kw) - - def write_htmlstring(self, encoding='utf-8', pipeline=True, **kw): - """Serialize in XHTML the tree beginning at this tag - - In: - - ``encoding`` -- encoding of the XML - - ``pipeline`` -- if False, the ``meld:id`` attributes are deleted - - Return: - - the XHTML - """ - if not pipeline: - for element in self.xpath('.//*[@meld:id]', namespaces={'meld': xml._MELD_NS}): - del element.attrib[xml._MELD_ID] - - return ET.tostring(self.decorate_error(), encoding=encoding, method='html', **kw) - - def error(self, err): - """Mark this tag as erroneous - - In: - - ``err`` -- the error message - - Return: - - ``self`` - """ - if err is not None: - self.has_error = err - - return self - - def decorate_error(self): - """Decorate this tag with an error structure - - Forward the call to the renderer ``decorate_error()`` method - - Return: - - a tree - """ - err = getattr(self, 'has_error', None) - return self if err is None else self.renderer.decorate_error(self, err) - - -@peak.rules.when(xml.add_child, (_HTMLTag, _HTMLTag)) -def add_child(next_method, self, element): - """Add a tag to a tag - - In: - - ``self`` -- the tag - - ``element`` -- the tag to add - """ - return next_method(self, element.decorate_error()) - - -@peak.rules.when(xml.add_attribute, (_HTMLTag, basestring, basestring)) -def add_attribute(next_method, self, name, value): - if name.startswith('data_'): - name = name.replace('_', '-') - - next_method(self, name, value) - - -class HeadRenderer(xml.XmlRenderer): - """The XHTML head Renderer - - This renderer knows about the possible tags of a html ```` - """ - - # Tag factories - # ------------- - - base = TagProp('base', set(('id', 'href', 'target'))) - head = TagProp('head', set(i18nattrs + ('id', 'profile'))) - link = TagProp('link', set(allattrs + ('charset', 'href', 'hreflang', 'type', 'rel', 'rev', 'media', 'target'))) - meta = TagProp('meta', set(i18nattrs + ('id', 'http_equiv', 'name', 'content', 'scheme'))) - title = TagProp('title', set(i18nattrs + ('id',))) - style = TagProp('style', set(i18nattrs + ('id',))) - script = TagProp('script', set(i18nattrs + ('id',))) - - @classmethod - def class_init(cls, specialTags): - """Class initialisation - - In: - -- ``special_tags`` -- tags that have a special factory - """ - # Create a XML parser that generate ``_HTMLTag`` nodes - cls._xml_parser = ET.XMLParser() - cls._xml_parser.setElementClassLookup(ET.ElementDefaultClassLookup(element=_HTMLTag)) - - -class Renderer(xml.XmlRenderer): - head_renderer_factory = HeadRenderer - - componentattrs = ('id', 'class', 'style', 'title') - i18nattrs = ('lang', 'dir') - eventattrs = ('onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmousemove', 'onmouseover', 'onmouseout', 'onkeypress', 'onkeydown', 'onkeyup') - focusattrs = ('accesskey', 'tabindex', 'onfocus', 'onblur') - cellhalignattrs = ('align', 'char', 'charoff') - cellvalignattrs = ('valign',) - allattrs = componentattrs + i18nattrs + eventattrs - - # The HTML tags - # ------------- - - a = TagProp('a', set(allattrs + focusattrs + ('charset', 'type', 'name', 'href', 'hreflang', 'rel', 'rev', 'shape', 'coords', 'target', 'oncontextmenu'))) - abbr = TagProp('abbr', set(allattrs)) - acronym = TagProp('acronym', set(allattrs)) - address = TagProp('address', set(allattrs)) - applet = TagProp('applet', set(componentattrs + ('codebase', 'archive', 'code', 'object', 'alt', 'name', 'width' - 'height', 'align', 'hspace', 'vspace'))) - area = TagProp('area', set(allattrs + focusattrs + ('shape', 'coords', 'href', 'nohref', 'alt', 'target'))) - b = TagProp('b', set(allattrs)) - basefont = TagProp('basefont', set(componentattrs + i18nattrs + ('id', 'size', 'color', 'face'))) - bdo = TagProp('bdo', set(componentattrs + eventattrs + ('lang', 'dir'))) - big = TagProp('big', set(allattrs)) - blockquote = TagProp('blockquote', set(allattrs + ('cite',))) - body = TagProp('body', set(allattrs + ('onload', 'onunload', 'onfocus', 'background', 'bgcolor', 'text' - 'link', 'vlink', 'alink', 'leftmargin', 'topmargin', 'marginwidth', 'marginheight'))) - br = TagProp('br', set(componentattrs + ('clear',))) - button = TagProp('button', set(allattrs + focusattrs + ('name', 'value', 'type', 'disabled'))) - caption = TagProp('caption', set(allattrs + ('align',))) - center = TagProp('center', set(allattrs)) - cite = TagProp('cite', set(allattrs)) - code = TagProp('code', set(allattrs)) - col = TagProp('col', set(allattrs + cellhalignattrs + cellvalignattrs + ('span', 'width'))) - colgroup = TagProp('colgroup', set(allattrs + cellhalignattrs + cellvalignattrs + ('span', 'width'))) - dd = TagProp('dd', set(allattrs)) - del_ = TagProp('del', set(allattrs + ('cite', 'datetime'))) - dfn = TagProp('dfn', set(allattrs)) - dir = TagProp('dir', set(allattrs + ('compact',))) - div = TagProp('div', set(allattrs + ('align',))) - dl = TagProp('dl', set(allattrs + ('compact',))) - dt = TagProp('dt', set(allattrs)) - em = TagProp('em', set(allattrs)) - embed = TagProp('embed', set(('width', 'height', 'src', 'controller', 'href', 'target', 'border', 'pluginspage', - 'quality', 'type', 'bgcolor', 'menu'))) - fieldset = TagProp('fieldset', set(allattrs)) - font = TagProp('font', set(componentattrs + i18nattrs + ('face', 'size', 'color'))) - form = TagProp('form', set(allattrs + ('action', 'method', 'name', 'enctype', 'onsubmit', 'onreset', 'accept_charset', 'target'))) - frame = TagProp('frame', set()) - frameset = TagProp('frameset', set(componentattrs + ('rows', 'cols', 'onload', 'onunload', 'framespacing', 'border', 'marginwidth' - 'marginheight', 'frameborder', 'noresize', 'scrolling'))) - h1 = TagProp('h1', set(allattrs + ('align',))) - h2 = TagProp('h2', set(allattrs + ('align',))) - h3 = TagProp('h3', set(allattrs + ('align',))) - h4 = TagProp('h4', set(allattrs + ('align',))) - h5 = TagProp('h5', set(allattrs + ('align',))) - h6 = TagProp('h6', set(allattrs + ('align',))) - hr = TagProp('hr', set(allattrs + ('align', 'noshade', 'size', 'width', 'color'))) - html = TagProp('html', set(i18nattrs + ('id',))) - i = TagProp('i', set(allattrs)) - iframe = TagProp('iframe', set(componentattrs + ('longdesc', 'name', 'src', 'frameborder', 'marginwidth', 'marginheight' - 'noresize', 'scrolling', 'align', 'height', 'width', 'hspace', 'vspace', 'bordercolor'))) - img = TagProp('img', set(allattrs + ('src', 'alt', 'name', 'longdesc', 'width', 'height', 'usemap', 'ismap' - 'align', 'border', 'hspace', 'vspace', 'lowsrc'))) - input = TagProp('input', set(allattrs + focusattrs + ('type', 'name', 'value', 'checked', 'disabled', 'readonly', 'size', 'maxlength', 'src' - 'alt', 'usemap', 'onselect', 'onchange', 'accept', 'align', 'border'))) - ins = TagProp('ins', set(allattrs + ('cite', 'datetime'))) - isindex = TagProp('isindex', set(componentattrs + i18nattrs + ('prompt',))) - kbd = TagProp('kbd', set(allattrs)) - label = TagProp('label', set(allattrs + ('for', 'accesskey', 'onfocus', 'onblur'))) - legend = TagProp('legend', set(allattrs + ('accesskey', 'align'))) - li = TagProp('li', set(allattrs + ('type', 'value'))) - map = TagProp('map', set(i18nattrs + eventattrs + ('id', 'class', 'style', 'title', 'name'))) - menu = TagProp('menu', set(allattrs + ('compact',))) - noframes = TagProp('noframes', set(allattrs)) - noscript = TagProp('noscript', set(allattrs)) - object = TagProp('object', set(allattrs + ('declare', 'classid', 'codebase', 'data', 'type', 'codetype' - 'archive', 'standby', 'height', 'width', 'usemap', 'name' - 'tabindex', 'align', 'border', 'hspace', 'vspace'))) - ol = TagProp('ol', set(allattrs + ('type', 'compact', 'start'))) - optgroup = TagProp('optgroup', set(allattrs + ('disabled', 'label'))) - option = TagProp('option', set(allattrs + ('selected', 'disabled', 'label', 'value'))) - p = TagProp('p', set(allattrs + ('align',))) - param = TagProp('param', set(('id', 'name', 'value', 'valuetype', 'type'))) - pre = TagProp('pre', set(allattrs + ('width',))) - q = TagProp('q', set(allattrs + ('cite',))) - s = TagProp('s', set(allattrs)) - samp = TagProp('samp', set(allattrs)) - script = TagProp('script', set(('id', 'charset', 'type', 'language', 'src', 'defer'))) - select = TagProp('select', set(allattrs + ('name', 'size', 'multiple', 'disabled', 'tabindex', 'onfocus', 'onblur', 'onchange', 'rows'))) - small = TagProp('small', set(allattrs)) - span = TagProp('span', set(allattrs)) - strike = TagProp('strike', set(allattrs)) - strong = TagProp('strong', set(allattrs)) - style = TagProp('style', set(i18nattrs + ('id', 'type', 'media', 'title'))) - sub = TagProp('sub', set(allattrs)) - sup = TagProp('sup', set(allattrs)) - table = TagProp('table', set(componentattrs + i18nattrs + ('prompt',))) - tbody = TagProp('tbody', set(allattrs + cellhalignattrs + cellvalignattrs)) - td = TagProp('td', set(allattrs + cellhalignattrs + cellvalignattrs + ('abbr', 'axis', 'headers', 'scope', 'rowspan' - 'colspan', 'nowrap', 'bgcolor', 'width', 'height' - 'background', 'bordercolor'))) - textarea = TagProp('textarea', set(allattrs + focusattrs + ('name', 'rows', 'cols', 'disabled', 'readonly', 'onselect', 'onchange', 'wrap'))) - tfoot = TagProp('tfoot', set(allattrs + cellhalignattrs + cellvalignattrs)) - th = TagProp('th', set(allattrs + cellhalignattrs + cellvalignattrs + ('abbr', 'axis', 'headers', 'scope', 'rowspan' - 'colspan', 'nowrap', 'bgcolor', 'width', 'height' - 'background', 'bordercolor'))) - thead = TagProp('thead', set(allattrs + cellhalignattrs + cellvalignattrs)) - tr = TagProp('tr', set(allattrs + cellhalignattrs + cellvalignattrs + ('bgcolor', 'nowrap', 'width', 'background'))) - tt = TagProp('tt', set(allattrs)) - u = TagProp('u', set(allattrs)) - ul = TagProp('ul', set(allattrs + ('type', 'compact'))) - var = TagProp('var', set(allattrs)) - -# frame = TagProp('frame', set(componentattrs + ('longdesc', 'name', 'src', 'frameborder', 'marginwidht', 'marginheight', -# 'noresize', 'scrolling', 'framespacing', 'border', 'marginwidth', 'marginheight', -# 'frameborder', 'noresize', 'scrolling'))) - @classmethod - def class_init(cls, specialTags): - """Class initialisation - - In: - -- ``special_tags`` -- tags that have a special factory - """ - # Create a HTML parser that generate ``_HTMLTag`` nodes - cls._html_parser = ET.HTMLParser() - cls._html_parser.setElementClassLookup(ET.ElementDefaultClassLookup(element=_HTMLTag)) - - def __init__(self, parent=None, **kw): - """Renderer initialisation - - In: - - ``parent`` -- parent renderer - """ - super(Renderer, self).__init__(parent) - - if parent is None: - self.head = self.head_renderer_factory(**kw) - else: - self.head = parent.head - - def makeelement(self, tag): - """Make a tag - - In: - - ``tag`` -- name of the tag to create - - Return: - - the new tag - """ - return self._makeelement(tag, self._html_parser) - - def _parse_html(self, parser, source, fragment, no_leading_text, **kw): - """Parse a HTML file - - In: - - ``parser`` -- XML or HTML parser to use - - ``source`` -- can be a filename or a file object - - ``fragment`` -- if ``True``, can parse a HTML fragment i.e a HTML without - a unique root - - ``no_leading_text`` -- if ``fragment`` is ``True``, ``no_leading_text`` - is ``False`` and the HTML to parsed begins by a text, this text is keeped - - ``kw`` -- keywords parameters are passed to the HTML parser - - Return: - - the root element of the parsed HTML, if ``fragment`` is ``False`` - - a list of HTML elements, if ``fragment`` is ``True`` - """ - if isinstance(source, basestring): - if source.startswith(('http://', 'https://', 'ftp://')): - source = urllib.urlopen(source) - else: - source = open(source) - - if not fragment: - # Parse a HTML file - # ---------------- - - root = ET.parse(source, parser).getroot() - source.close() - - # Attach the renderer to the root - root._renderer = self - return root - - # Parse a HTML fragment - # --------------------- - - # Create a dummy ```` - html = cStringIO.StringIO('%s' % source.read()) - source.close() - - body = ET.parse(html, parser).getroot()[0] - for e in body: - if isinstance(e, _HTMLTag): - # Attach the renderer to each roots - e._renderer = self - - # Return the children of the dummy ```` - return ([body.text] if body.text and not no_leading_text else []) + body[:] - - def parse_html(self, source, fragment=False, no_leading_text=False, xhtml=False, **kw): - """Parse a (X)HTML file - - In: - - ``source`` -- can be a filename or a file object - - ``fragment`` -- if ``True``, can parse a HTML fragment i.e a HTML without - a unique root - - ``no_leading_text`` -- if ``fragment`` is ``True``, ``no_leading_text`` - is ``False`` and the HTML to parsed begins by a text, this text is keeped - - ``xhtml`` -- is the HTML to parse a valid XHTML ? - - ``kw`` -- keywords parameters are passed to the HTML parser - - Return: - - the root element of the parsed HTML, if ``fragment`` is ``False`` - - a list of HTML elements, if ``fragment`` is ``True`` - """ - parser = ET.XMLParser(**kw) if xhtml else ET.HTMLParser(**kw) - parser.setElementClassLookup(ET.ElementDefaultClassLookup(element=_HTMLTag)) - - return self._parse_html(parser, source, fragment, no_leading_text, **kw) - - def parse_htmlstring(self, text, fragment=False, no_leading_text=False, xhtml=False, **kw): - """Parse a (X)HTML string - - In: - - ``text`` -- can be a ``str`` or ``unicode`` strings - - ``source`` -- can be a filename or a file object - - ``fragment`` -- if ``True``, can parse a HTML fragment i.e a HTML without - a unique root - - ``no_leading_text`` -- if ``fragment`` is ``True``, ``no_leading_text`` - is ``False`` and the HTML to parsed begins by a text, this text is keeped - - ``xhtml`` -- is the HTML to parse a valid XHTML ? - - ``kw`` -- keywords parameters are passed to the HTML parser - - Return: - - the root element of the parsed HTML, if ``fragment`` is ``False`` - - a list of HTML elements, if ``fragment`` is ``True`` - """ - if isinstance(text, unicode): - text = text.encode(kw.setdefault('encoding', 'utf-8')) - - return self.parse_html(cStringIO.StringIO(text), fragment, no_leading_text, xhtml, **kw) - -# --------------------------------------------------------------------------- - -if __name__ == '__main__': - t = ((1, 'a'), (2, 'b'), (3, 'c')) - - h = Renderer() - - h.head << h.head.title('A test') - h.head << h.head.script('function() {}') - h.head << h.head.meta(name='meta1', content='content1') - - with h.body(onload='javascript:alert()'): - with h.ul: - with h.li('Hello'): - pass - with h.li: - h << 'world' - h << h.li('yeah') - - with h.div(class_='toto'): - with h.h1('moi'): - h << h.i('toto') - - with h.div: - h << 'yeah' - for i in range(3): - h << i - - with h.table(toto='toto'): - for row in t: - with h.tr: - for column in row: - with h.td: - h << column - - print h.html(h.head.head(h.head.root), h.root).write_htmlstring(pretty_print=True) diff --git a/nagare/namespaces/xml.py b/nagare/namespaces/xml.py deleted file mode 100644 index fed44a1..0000000 --- a/nagare/namespaces/xml.py +++ /dev/null @@ -1,766 +0,0 @@ -#-- -# Copyright (c) 2008-2013 Net-ng. -# All rights reserved. -# -# This software is licensed under the BSD License, as described in -# the file LICENSE.txt, which you should have received as part of -# this distribution. -#-- - -"""XML renderer""" - -from __future__ import with_statement - -import types -import copy -import cStringIO -import urllib - -import peak.rules - -from lxml import etree as ET - -from nagare.namespaces import common - -CHECK_ATTRIBUTES = False - -# Namespace for the ``meld:id`` attribute -_MELD_NS = 'http://www.plope.com/software/meld3' -_MELD_ID = '{%s}id' % _MELD_NS - -# --------------------------------------------------------------------------- - -class _Tag(ET.ElementBase): - """A xml tag - """ - def init(self, renderer): - """Each tag keeps track of the renderer that created it - - Return: - - ``self`` - """ - self._renderer = renderer - return self - - @property - def renderer(self): - """Return the renderer that created this tag - - Return: - - the renderer - """ - # The renderer is search first, in this tag, else at the root of the tree - return getattr(self, '_renderer', None) or self.getroottree().getroot()._renderer - - def write_xmlstring(self, encoding='utf-8', pipeline=True, **kw): - """Serialize in XML the tree beginning at this tag - - In: - - ``encoding`` -- encoding of the XML - - ``pipeline`` -- if False, the ``meld:id`` attributes are deleted - - Return: - - the XML - """ - if not pipeline: - for element in self.xpath('.//*[@meld:id]', namespaces={'meld': _MELD_NS}): - del element.attrib[_MELD_ID] - - return ET.tostring(self, encoding=encoding, method='xml', **kw) - - def xpath(self, *args, **kw): - """Override ``xpath()`` to associate a renderer to all the returned nodes - """ - nodes = super(_Tag, self).xpath(*args, **kw) - - renderer = self.renderer - for node in nodes: - node._renderer = renderer - - return nodes - - def findmeld(self, id, default=None): - """Find a tag with a given ``meld:id`` value - - In: - - ``id`` -- value of the ``meld:id`` attribute to search - - ``default`` -- value returned if the tag is not found - - Return: - - the tag found, else the ``default`` value - """ - nodes = self.xpath('.//*[@meld:id="%s"]' % id, namespaces={'meld': _MELD_NS}) - - if len(nodes) != 0: - # Return only the first tag found - return nodes[0] - - return default - - def append_text(self, text): - """Append a text to this tag - - In: - - ``text`` -- text to add - """ - if len(self) != 0: - self[-1].tail = (self[-1].tail or '') + text - else: - self.text = (self.text or '') + text - - def add_child(self, child): - """Append a child to this tag - - In: - - ``child`` -- child to add - """ - # Forward the call to the generic method - add_child(self, child) - - def meld_id(self, id): - """Set the value of the attribute ``meld:id`` of this tag - - In: - - ``id`` - value of the ``meld;id`` attribute - - Return: - - ``self`` - """ - self.add_child({_MELD_ID: id}) - return self - - def fill(self, *children, **attrib): - """Change all the child and append attributes of this tag - - In: - - ``children`` -- list of the new children of this tag - - ``attrib`` -- dictionnary of attributes of this tag - - Return: - - ``self`` - """ - self[:] = [] - self.text = None - - return self.__call__(*children, **attrib) - - def replace(self, *children): - """Replace this tag by others - - In: - - ``children`` -- list of tags to replace this tag - """ - parent = self.getparent() - - # We can not replace the root of the tree - if parent is not None: - tail = self.tail - l = len(parent) - - i = parent.index(self) - parent.fill(parent.text or '', parent[:i], children, self.tail or '', parent[i + 1:]) - - if len(parent) >= l: - parent[i - l].tail = tail - - def repeat(self, iterable, childname=None): - """Iterate over a sequence, cloning a new child each time - - In: - - ``iterable`` -- the sequence - - ``childname`` -- If ``None``, clone this tag each time else - clone each time the tag that have ``childname`` as ``meld:id`` value - - Return: - - list of tuples (cloned child, item of the sequence) - """ - # Find the child to clone - if childname is None: - element = self - else: - element = self.findmeld(childname) - - parent = element.getparent() - parent.remove(element) - - for thing in iterable: - clone = copy.deepcopy(element) - clone._renderer = element.renderer - parent.append(clone) - - yield (clone, thing) - - def __call__(self, *children, **attrib): - """Append child and attributes to this tag - - In: - - ``children`` -- children to add - - ``attrib`` -- attributes to add - - Return: - - ``self`` - """ - if attrib: - self.add_child(attrib) - - nb = len(children) - if nb != 0: - if nb == 1: - children = children[0] - self.add_child(children) - - if CHECK_ATTRIBUTES and self._authorized_attribs and not frozenset(self.attrib).issubset(self._authorized_attribs): - raise AttributeError("Bad attributes for element <%s>: " % self.tag + ', '.join(list(frozenset(self.attrib) - self._authorized_attribs))) - - return self - - def __enter__(self): - return self.renderer.enter(self) - - def __exit__(self, exception, data, tb): - if exception is None: - self.renderer.exit() - -# --------------------------------------------------------------------------- - -# Generic methods to add a child to a tag -# --------------------------------------- - -def add_child(self, o): - """Default method to add an object to a tag - - In: - - ``self`` -- the tag - - ``o`` -- object to add - - Try to add the result of ``o.render()`` to the tag - """ - render = getattr(o, 'render', None) - if render is None: - raise TypeError("Can't append a '%s' to element <%s>" % (type(o), self.tag)) - - self.add_child(render(self.renderer)) - - -@peak.rules.when(add_child, (_Tag, basestring)) -def add_child(self, s): - """Add a string to a tag - - In: - - ``self`` -- the tag - - ``s`` - str or unicode string to add - """ - self.append_text(s) - - -@peak.rules.when(add_child, (_Tag, (list, tuple, types.GeneratorType))) -def add_child(self, i): - """Add elements to a tag - - In: - - ``self`` -- the tag - - ``i`` -- elements to add - - Add each element as a child - """ - for child in i: - self.add_child(child) - - -@peak.rules.when(add_child, (_Tag, (int, long, float))) -def add_child(self, n): - """Add a number to a tag - - In: - - ``self`` -- the tag - - ``n`` -- number to add - - Convert the number to string and then add it - """ - self.append_text(str(n)) - - -@peak.rules.when(add_child, (_Tag, ET._Element)) -def add_child(self, element): - """Add a tag to a tag - - In: - - ``self`` -- the tag - - ``element`` -- the tag to add - """ - if hasattr(element, '_renderer'): - del element._renderer - - self.append(element) - - -@peak.rules.when(add_child, (_Tag, ET._Comment)) -def add_child(self, element): - """Add a comment element to a tag - - In: - - ``self`` -- the tag - - ``element`` -- the comment to add - """ - if hasattr(element, '_renderer'): - del element._renderer - - self.append(element) - - -@peak.rules.when(add_child, (_Tag, ET._ProcessingInstruction)) -def add_child(self, element): - """Add a PI element to a tag - - In: - - ``self`` -- the tag - - ``element`` -- the PI to add - - Do nothing - """ - self.append(element) - - -@peak.rules.when(add_child, (_Tag, dict)) -def add_child(self, d): - """Add a dictionary to a tag - - In: - - ``self`` -- the tag - - ``element`` -- the dictionary to add - - Each key/value becomes an attribute of the tag - - Attribute name can end with a '_' which is removed - """ - for (name, value) in d.items(): - add_attribute(self, name, value) - -# --------------------------------------------------------------------------- - -# Generic methods to add an attribute to a tag -# -------------------------------------------- - -def add_attribute(self, name, value): - """Default method to add an attribute to a tag - - In: - - ``self`` -- the tag - - ``name`` -- name of the attribute to add - - ``value`` -- value of the attribute to add - """ - add_attribute(self, name, unicode(value)) - - -@peak.rules.when(add_attribute, (_Tag, basestring, basestring)) -def add_attribute(self, name, value): - if name.endswith('_'): - name = name[:-1] - - self.set(name, value) - -@peak.rules.when(add_attribute, (ET._ProcessingInstruction, basestring, basestring)) -def add_attribute(self, name, value): - if name.endswith('_'): - name = name[:-1] - - self.text += (' %s="%s"' % (name, value)) - -# --------------------------------------------------------------------------- - -class TagProp(object): - """Tag factory with a behavior of an object attribute - - Each time this attribute is read, a new tag is created - """ - def __init__(self, name, authorized_attribs=None, factory=None): - """Initialization - - In: - - ``name`` -- name of the tags to create - - ``authorized_attribs`` -- names of the valid attributes - - ``factory`` -- special factory to create the tag - """ - self._name = name - self._factory = factory - - if CHECK_ATTRIBUTES: - self._authorized_attribs = frozenset(authorized_attribs) if authorized_attribs is not None else None - - def __get__(self, renderer, cls): - """Create a new tag each time this attribute is read - - In: - - ``renderer`` -- the object that has this attribute - - ``cls`` -- *not used* - - Return: - - a new tag - """ - element = renderer.makeelement(self._name) - - if CHECK_ATTRIBUTES: - element._authorized_attribs = self._authorized_attribs - - return element - - -class RendererMetaClass(type): - """Meta class for the renderer class - - Discover the tags that have a special factory and pass them to the - ``class_init()`` method of the class - """ - def __new__(self, cls_name, bases, ns): - """Creation of the class - - In: - - ``cls_name`` -- name of the class to create - - ``bases`` -- tuple of the base classes of the class to create - - ``ns`` -- namespace of the class to create - - Return: - - the new class - """ - cls = super(RendererMetaClass, self).__new__(self, cls_name, bases, ns) - - special_tags = {} - - for (k, v) in ns.items(): - if isinstance(v, TagProp): - if v._factory is not None: - special_tags[v._name] = v._factory - del v._factory - - cls.class_init(special_tags) - - return cls - -# ----------------------------------------------------------------------- - -class XmlRenderer(common.Renderer): - """The base class of all the renderers that generate a XML dialect - """ - __metaclass__ = RendererMetaClass - - doctype = '' - content_type = 'text/xml' - - @classmethod - def class_init(cls, special_tags): - """Class initialisation - - In: - -- ``special_tags`` -- tags that have a special factory - """ - # Create a XML parser that generate ``_Tag`` nodes - cls._xml_parser = ET.XMLParser() - cls._xml_parser.setElementClassLookup(ET.ElementDefaultClassLookup(element=_Tag)) - - def __init__(self, parent=None): - """Renderer initialisation - - In: - - ``parent`` -- parent renderer - """ - if parent is None: - self.namespaces = None - self._default_namespace = None - else: - # This renderer use the same XML namespaces than its parent - self.namespaces = parent.namespaces - self._default_namespace = parent._default_namespace - - self.parent = parent - self._prefix = '' - - # The stack, contening the last tag push by a ``with`` statement - # Initialized with a dummy root - self._stack = [self.makeelement('_renderer_root_')] - - # Each renderer created has a unique id - self.id = self.generate_id('id') - - def _get_default_namespace(self): - """Return the default_namespace - - Return: - - the default namespace or ``None`` if no default namespace was set - """ - return self._default_namespace - - def _set_default_namespace(self, namespace): - """Change the default namespace - - The namespace must be a key of the ``self.namespaces`` dictionary or be - ``None`` - - For example: - - .. code-block:: python - - x.namespaces = { 'xsl' : 'http://www.w3.org/1999/XSL/Transform' } - x.set_default_namespace('xsl') - """ - self._default_namespace = namespace - - if namespace is None: - self._prefix = '' - else: - self._prefix = '{%s}' % self.namespaces[namespace] - default_namespace = property(_get_default_namespace, _set_default_namespace) - - @property - def root(self): - """Return the first tag(s) sent to the renderer - - .. warning:: - A list of tags can be returned - - Return: - - the tag(s) - """ - children = self._stack[0].getchildren() - - text = self._stack[0].text - - if text is not None: - children.insert(0, text) - - if not children: - return '' - - if len(children) == 1: - return children[0] - - return children - - def enter(self, current): - """A new tag is pushed by a ``with`` statement - - In: - - ``current`` -- the tag - - Return: - - ``current`` - """ - self << current # Append the tag to its parent - self._stack.append(current) # Push it onto the stack - - return current - - def exit(self): - """End of a ``with`` statement - """ - self._stack.pop() # Pop the current tag from the stack - - def _makeelement(self, tag, parser): - """Make a tag, in the default namespace set - - In: - - ``tag`` -- name of the tag to create - - ``parser`` -- parser used to create the tag - - Return: - - the new tag - """ - # 1. Create the tag with in the default namespace - element = parser.makeelement(self._prefix + tag, nsmap=self.namespaces) - # 2. Initialize it with this renderer - return element.init(self) - - def makeelement(self, tag): - """Make a tag, in the default namespace set - - In: - - ``tag`` -- name of the tag to create - - Return: - - the new tag - """ - # Create the tag with the XML parser - return self._makeelement(tag, self._xml_parser) - - def __lshift__(self, current): - """Add a tag to the last tag pushed by a ``with`` statement - - In: - - ``current`` -- tag to add - - Return: - - ``self``, the renderer - """ - add_child(self._stack[-1], current) - return self - - def comment(self, text=''): - """Create a comment element - - In: - - ``text`` -- text of the comment - - Return: - - the new comment element - """ - return ET.Comment(text) - - def processing_instruction(self, target, text=None, **kw): - """Create a processing instruction element - - In: - - ``target`` -- the PI target - - ``text`` -- the PI text - - ``kw`` -- pseudo attributes - - Return: - - the new processing instruction element - """ - pi = ET.ProcessingInstruction(target, text) - - for name, value in kw.items(): - add_attribute(pi, name, value) - - return pi - - def parse_xml(self, source, fragment=False, no_leading_text=False, **kw): - """Parse a XML file - - In: - - ``source`` -- can be a filename or a file object - - ``fragment`` -- if ``True``, can parse a XML fragment i.e a XML without - a unique root - - ``no_leading_text`` -- if ``fragment`` is ``True``, ``no_leading_text`` - is ``False`` and the XML to parsed begins by a text, this text is keeped - - ``kw`` -- keywords parameters are passed to the XML parser - - Return: - - the root element of the parsed XML, if ``fragment`` is ``False`` - - a list of XML elements, if ``fragment`` is ``True`` - """ - if isinstance(source, basestring): - if source.startswith(('http://', 'https://', 'ftp://')): - source = urllib.urlopen(source) - else: - source = open(source) - - # Create a dedicated XML parser with the ``kw`` parameter - parser = ET.XMLParser(**kw) - # This parser will generate nodes of type ``_Tag`` - parser.setElementClassLookup(ET.ElementDefaultClassLookup(element=_Tag)) - - if not fragment: - # Parse a XML file - # ---------------- - - root = ET.parse(source, parser).getroot() - source.close() - - # Attach the renderer to the root - root._renderer = self - return root - - # Parse a XML fragment - # -------------------- - - # Create a dummy root - xml = cStringIO.StringIO('%s' % source.read()) - source.close() - - root = ET.parse(xml, parser).getroot() - for e in root[:]: - # Attach the renderer to each roots - e._renderer = self - - # Return the children of the dummy root - return ([root.text] if root.text and not no_leading_text else []) + root[:] - - def parse_xmlstring(self, text, fragment=False, no_leading_text=False, **kw): - """Parse a XML string - - In: - - ``text`` -- can be a ``str`` or ``unicode`` string - - ``fragment`` -- if ``True``, can parse a XML fragment i.e a XML without - a unique root - - ``no_leading_text`` -- if ``fragment`` is ``True``, ``no_leading_text`` - is ``False`` and the XML to parsed begins by a text, this text is keeped - - ``kw`` -- keywords parameters are passed to the XML parser - - Return: - - the root element of the parsed XML, if ``fragment`` is ``False`` - - a list of XML elements, if ``fragment`` is ``True`` - """ - if type(text) == unicode: - text = text.encode(kw.setdefault('encoding', 'utf-8')) - - return self.parse_xml(cStringIO.StringIO(text), fragment, no_leading_text, **kw) - -# --------------------------------------------------------------------------- - -class Renderer(XmlRenderer): - """The XML Renderer - - This renderer generate any tags you give - - .. code-block:: pycon - - >>> xml = xml.Renderer() - >>> xml.foo(xml.bar).write_xmlstring() - '' - """ - def __getattr__(self, name): - """Any attribute access becomes a tag generation - - In: - - ``name`` -- name of the tag to generate - - Return: - - the generated tag - """ - return self.makeelement(name) - -# --------------------------------------------------------------------------- - -if __name__ == '__main__': - x = Renderer() - x.namespaces = {'meld': 'http://www.plope.com/software/meld3'} - - with x.contacts: - with x.contact.meld_id('contact'): - x << x.name.meld_id('name') - with x.address.meld_id('addr'): - x << 'ici, rennes' - - print x.root.write_xmlstring(xml_declaration=True, pretty_print=True) - print - - for (e, (name, addr)) in x.root.repeat((('bill', 'seatle'), ('steve', 'cupertino')), 'contact'): - e.findmeld('name').text = name - e.findmeld('addr').text = addr - - print x.root.write_xmlstring(pretty_print=True) - print - - # ----------------------------------------------------------------------- - - x = Renderer() - x << x.foo - x << x.bar - - print x.all(x.root).write_xmlstring(xml_declaration=True, pretty_print=True) - print - - # ----------------------------------------------------------------------- - - t1 = x.parse_xmlstring(''' - avantkjkjkl#helloapres - ''') - - t2 = x.parse_xmlstring(''' - xxxworldyyy - ''') - - t1[1].replace(t2[0]) - #t1[1].replace('new') - #t1[1].replace() - - print t1.write_xmlstring() diff --git a/nagare/namespaces/xsl.py b/nagare/namespaces/xsl.py deleted file mode 100644 index ccb6cee..0000000 --- a/nagare/namespaces/xsl.py +++ /dev/null @@ -1,112 +0,0 @@ -#-- -# Copyright (c) 2008-2013 Net-ng. -# All rights reserved. -# -# This software is licensed under the BSD License, as described in -# the file LICENSE.txt, which you should have received as part of -# this distribution. -#-- - -"""XSL renderer""" - -from __future__ import with_statement - -from nagare.namespaces import xml -from nagare.namespaces.xml import TagProp - -# ---------------------------------------------------------------------------------- - -class Renderer(xml.XmlRenderer): - """ The XSL renderer - """ - - content_type = 'text/xsl' - - # The XSL tags - # ------------ - - apply_imports = TagProp('apply-imports', set()) - apply_templates = TagProp('apply-templates', set(('select', 'mode'))) - attribute = TagProp('attribute', set(('name', 'namespace'))) - attribute_set = TagProp('attribute-set', set(('name', 'use-attribute-sets'))) - call_template = TagProp('call-template', set(('name',))) - choose = TagProp('choose', set()) - comment = TagProp('comment', set()) - copy = TagProp('copy', set(('use-attribute-sets',))) - copy_of = TagProp('copy-of', set(('select',))) - decimal_format = TagProp('decimal-format', set(('name', 'decimal-separator', 'grouping-separator', 'infinity', - 'minus-sign', 'NaN', 'percent', 'per-mille', 'zero-digit', - 'pattern-separator'))) - element = TagProp('element', set(('name', 'namespace', 'use-attribute-sets'))) - fallback = TagProp('fallback', set(('select',))) - if_ = TagProp('if', set(('test',))) - import_ = TagProp('import', set(('href',))) - include = TagProp('include', set(('href',))) - for_each = TagProp('for-each', set(('select',))) - key = TagProp('key', set(('name', 'match', 'use'))) - message = TagProp('message', set(('terminate',))) - namespace_alias = TagProp('namespace-alias', set(('stylesheet-prefix',))) - number = TagProp('number', set(('level', 'count', 'from', 'value', 'format', - 'lang', 'letter-value', 'grouping-separator', - 'grouping-size'))) - otherwise = TagProp('otherwise', set()) - output = TagProp('output', set(('method', 'version', 'encoding', - 'omit-xml-declaration', 'standalone', - 'doctype-public', 'doctype-system', - 'cdata-section-elements', 'indent', - 'media-type'))) - param = TagProp('param', set(('name', 'select'))) - preserve_space = TagProp('preserve-space', set(('elements',))) - processing_instruction = TagProp('processing-instruction', set(('name',))) - sort = TagProp('sort', set(('select', 'lang', 'data-type', 'order', 'case-order'))) - strip_space = TagProp('strip-space', set(('elements',))) - stylesheet = TagProp('stylesheet', set(('version', 'id', - 'extension-element-prefixes', - 'exclude-result-prefixes'))) - template = TagProp('template', set(('match', 'name', 'priority', 'mode'))) - transform = TagProp('transform', set(('version', 'id', - 'extension-element-prefixes', - 'exclude-result-prefixes'))) - text = TagProp('text', set()) - value_of = TagProp('value-of', set(('select', 'disable-output-escaping'))) - variable = TagProp('variable', set(('name', 'select'))) - when = TagProp('when', set(('test',))) - with_param = TagProp('with-param', set(('name', 'select'))) - -# ---------------------------------------------------------------------------------- - -""" - - - - - - -""" - -if __name__ == '__main__': - from nagare.namespaces import xhtml - - x = Renderer() - x.namespaces = {'xsl': 'http://www.w3.org/1999/XSL/Transform'} - x.default_namespace = 'xsl' - - xsl = x.stylesheet( - x.output(encoding="utf-8"), - x.template( - x.copy_of(select="."), match="/" - ) - ) - - print xsl.write_xmlstring(xml_declaration=True, pretty_print=True) - - h = xhtml.Renderer() - - page = h.html(h.h1('Hello'), h.h2('world')) - - print page.write_xmlstring(pretty_print=True) - - r = page.getroottree().xslt(xsl) - - print str(r) - print diff --git a/setup.py b/setup.py index 44f77f6..cf210be 100644 --- a/setup.py +++ b/setup.py @@ -68,7 +68,7 @@ namespace_packages=('nagare',), zip_safe=False, dependency_links=('http://www.nagare.org/download/',), - install_requires=('PEAK-Rules', 'ConfigObj', 'lxml>=3.0.1', 'WebOb>=1.2.3', 'Paste', 'flup', 'python-memcached'), + install_requires=('PEAK-Rules', 'ConfigObj', 'lxml>=3.0.1', 'WebOb>=1.2.3', 'Paste', 'flup', 'python-memcached', 'nagare-namespaces'), message_extractors={'nagare': [ ('test/**', 'ignore', None), ('**.py', 'python', None),