annotate genshi/builder.py @ 379:e1d659c87ddf trunk

The builder API now accepts streams as children of elements and fragments.
author cmlenz
date Thu, 23 Nov 2006 17:48:17 +0000
parents 2aa7ca37ae6a
children 228907abb726 3eb30e4ece8c
rev   line source
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
2 #
66
59eb24184e9c Switch copyright to Edgewall and URLs to markup.edgewall.org.
cmlenz
parents: 65
diff changeset
3 # Copyright (C) 2006 Edgewall Software
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
4 # All rights reserved.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
5 #
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
230
84168828b074 Renamed Markup to Genshi in repository.
cmlenz
parents: 182
diff changeset
8 # are also available at http://genshi.edgewall.org/wiki/License.
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
9 #
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
230
84168828b074 Renamed Markup to Genshi in repository.
cmlenz
parents: 182
diff changeset
12 # history and logs, available at http://genshi.edgewall.org/log/.
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
13
230
84168828b074 Renamed Markup to Genshi in repository.
cmlenz
parents: 182
diff changeset
14 from genshi.core import Attrs, Namespace, QName, Stream, START, END, TEXT
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
15
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
16 __all__ = ['Fragment', 'Element', 'tag']
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
17
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
18
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
19 class Fragment(object):
28
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
20 """Represents a markup fragment, which is basically just a list of element
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
21 or text nodes.
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
22 """
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
23 __slots__ = ['children']
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
24
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
25 def __init__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
26 self.children = []
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
27
65
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
28 def __add__(self, other):
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
29 return Fragment()(self, other)
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
30
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
31 def __call__(self, *args):
133
79f445396cd7 Minor cleanup and performance improvement for the builder module.
cmlenz
parents: 119
diff changeset
32 map(self.append, args)
65
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
33 return self
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
34
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
35 def __iter__(self):
98
44af12832c5a Bugfix in `builder` module: attribute values need to be converted to strings when generating streams.
cmlenz
parents: 94
diff changeset
36 return self._generate()
65
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
37
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
38 def __repr__(self):
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
39 return '<%s>' % self.__class__.__name__
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
40
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
41 def __str__(self):
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
42 return str(self.generate())
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
43
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
44 def __unicode__(self):
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
45 return unicode(self.generate())
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
46
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
47 def append(self, node):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
48 """Append an element or string as child node."""
379
e1d659c87ddf The builder API now accepts streams as children of elements and fragments.
cmlenz
parents: 345
diff changeset
49 if isinstance(node, (Stream, Element, basestring, int, float, long)):
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
50 # For objects of a known/primitive type, we avoid the check for
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
51 # whether it is iterable for better performance
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
52 self.children.append(node)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
53 elif isinstance(node, Fragment):
133
79f445396cd7 Minor cleanup and performance improvement for the builder module.
cmlenz
parents: 119
diff changeset
54 self.children.extend(node.children)
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
55 elif node is not None:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
56 try:
133
79f445396cd7 Minor cleanup and performance improvement for the builder module.
cmlenz
parents: 119
diff changeset
57 map(self.append, iter(node))
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
58 except TypeError:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
59 self.children.append(node)
94
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
60
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
61 def _generate(self):
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
62 for child in self.children:
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
63 if isinstance(child, Fragment):
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
64 for event in child._generate():
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
65 yield event
379
e1d659c87ddf The builder API now accepts streams as children of elements and fragments.
cmlenz
parents: 345
diff changeset
66 elif isinstance(child, Stream):
e1d659c87ddf The builder API now accepts streams as children of elements and fragments.
cmlenz
parents: 345
diff changeset
67 for event in child:
e1d659c87ddf The builder API now accepts streams as children of elements and fragments.
cmlenz
parents: 345
diff changeset
68 yield event
94
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
69 else:
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
70 if not isinstance(child, basestring):
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
71 child = unicode(child)
133
79f445396cd7 Minor cleanup and performance improvement for the builder module.
cmlenz
parents: 119
diff changeset
72 yield TEXT, child, (None, -1, -1)
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
73
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
74 def generate(self):
28
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
75 """Return a markup event stream for the fragment."""
94
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
76 return Stream(self._generate())
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
77
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
78
345
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
79 def _value_to_unicode(value):
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
80 if isinstance(value, unicode):
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
81 return value
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
82 return unicode(value)
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
83
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
84 def _kwargs_to_attrs(kwargs):
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
85 return [(k.rstrip('_').replace('_', '-'), _value_to_unicode(v))
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
86 for k, v in kwargs.items() if v is not None]
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
87
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
88
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
89 class Element(Fragment):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
90 """Simple XML output generator based on the builder pattern.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
91
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
92 Construct XML elements by passing the tag name to the constructor:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
93
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
94 >>> print Element('strong')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
95 <strong/>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
96
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
97 Attributes can be specified using keyword arguments. The values of the
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
98 arguments will be converted to strings and any special XML characters
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
99 escaped:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
100
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
101 >>> print Element('textarea', rows=10, cols=60)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
102 <textarea rows="10" cols="60"/>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
103 >>> print Element('span', title='1 < 2')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
104 <span title="1 &lt; 2"/>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
105 >>> print Element('span', title='"baz"')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
106 <span title="&#34;baz&#34;"/>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
107
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
108 The " character is escaped using a numerical entity.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
109 The order in which attributes are rendered is undefined.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
110
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
111 If an attribute value evaluates to `None`, that attribute is not included
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
112 in the output:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
113
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
114 >>> print Element('a', name=None)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
115 <a/>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
116
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
117 Attribute names that conflict with Python keywords can be specified by
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
118 appending an underscore:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
119
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
120 >>> print Element('div', class_='warning')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
121 <div class="warning"/>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
122
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
123 Nested elements can be added to an element using item access notation.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
124 The call notation can also be used for this and for adding attributes
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
125 using keyword arguments, as one would do in the constructor.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
126
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
127 >>> print Element('ul')(Element('li'), Element('li'))
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
128 <ul><li/><li/></ul>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
129 >>> print Element('a')('Label')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
130 <a>Label</a>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
131 >>> print Element('a')('Label', href="target")
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
132 <a href="target">Label</a>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
133
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
134 Text nodes can be nested in an element by adding strings instead of
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
135 elements. Any special characters in the strings are escaped automatically:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
136
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
137 >>> print Element('em')('Hello world')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
138 <em>Hello world</em>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
139 >>> print Element('em')(42)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
140 <em>42</em>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
141 >>> print Element('em')('1 < 2')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
142 <em>1 &lt; 2</em>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
143
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
144 This technique also allows mixed content:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
145
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
146 >>> print Element('p')('Hello ', Element('b')('world'))
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
147 <p>Hello <b>world</b></p>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
148
34
3421dd98f015 quotes should not be escaped inside text nodes
mgood
parents: 28
diff changeset
149 Quotes are not escaped inside text nodes:
3421dd98f015 quotes should not be escaped inside text nodes
mgood
parents: 28
diff changeset
150 >>> print Element('p')('"Hello"')
3421dd98f015 quotes should not be escaped inside text nodes
mgood
parents: 28
diff changeset
151 <p>"Hello"</p>
3421dd98f015 quotes should not be escaped inside text nodes
mgood
parents: 28
diff changeset
152
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
153 Elements can also be combined with other elements or strings using the
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
154 addition operator, which results in a `Fragment` object that contains the
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
155 operands:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
156
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
157 >>> print Element('br') + 'some text' + Element('br')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
158 <br/>some text<br/>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
159
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
160 Elements with a namespace can be generated using the `Namespace` and/or
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
161 `QName` classes:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
162
230
84168828b074 Renamed Markup to Genshi in repository.
cmlenz
parents: 182
diff changeset
163 >>> from genshi.core import Namespace
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
164 >>> xhtml = Namespace('http://www.w3.org/1999/xhtml')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
165 >>> print Element(xhtml.html, lang='en')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
166 <html lang="en" xmlns="http://www.w3.org/1999/xhtml"/>
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
167 """
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
168 __slots__ = ['tag', 'attrib']
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
169
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
170 def __init__(self, tag_, **attrib):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
171 Fragment.__init__(self)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
172 self.tag = QName(tag_)
345
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
173 self.attrib = Attrs(_kwargs_to_attrs(attrib))
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
174
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
175 def __call__(self, *args, **kwargs):
345
2aa7ca37ae6a Make `Attrs` instances immutable.
cmlenz
parents: 230
diff changeset
176 self.attrib |= Attrs(_kwargs_to_attrs(kwargs))
98
44af12832c5a Bugfix in `builder` module: attribute values need to be converted to strings when generating streams.
cmlenz
parents: 94
diff changeset
177 Fragment.__call__(self, *args)
44af12832c5a Bugfix in `builder` module: attribute values need to be converted to strings when generating streams.
cmlenz
parents: 94
diff changeset
178 return self
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
179
65
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
180 def __repr__(self):
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
181 return '<%s "%s">' % (self.__class__.__name__, self.tag)
b3fdf93057ab Support the use of directives as elements to reduce the need for using `py:strip`.
cmlenz
parents: 34
diff changeset
182
94
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
183 def _generate(self):
133
79f445396cd7 Minor cleanup and performance improvement for the builder module.
cmlenz
parents: 119
diff changeset
184 yield START, (self.tag, self.attrib), (None, -1, -1)
94
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
185 for kind, data, pos in Fragment._generate(self):
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
186 yield kind, data, pos
133
79f445396cd7 Minor cleanup and performance improvement for the builder module.
cmlenz
parents: 119
diff changeset
187 yield END, self.tag, (None, -1, -1)
94
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
188
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
189 def generate(self):
28
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
190 """Return a markup event stream for the fragment."""
94
0f8800c46e21 Some bugfixes and minor performance improvements for the builder module.
cmlenz
parents: 91
diff changeset
191 return Stream(self._generate())
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
192
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
193
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
194 class ElementFactory(object):
28
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
195 """Factory for `Element` objects.
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
196
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
197 A new element is created simply by accessing a correspondingly named
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
198 attribute of the factory object:
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
199
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
200 >>> factory = ElementFactory()
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
201 >>> print factory.foo
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
202 <foo/>
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
203 >>> print factory.foo(id=2)
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
204 <foo id="2"/>
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
205
119
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
206 Markup fragments (lists of nodes without a parent element) can be created
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
207 by calling the factory:
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
208
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
209 >>> print factory('Hello, ', factory.em('world'), '!')
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
210 Hello, <em>world</em>!
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
211
28
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
212 A factory can also be bound to a specific namespace:
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
213
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
214 >>> factory = ElementFactory('http://www.w3.org/1999/xhtml')
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
215 >>> print factory.html(lang="en")
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
216 <html lang="en" xmlns="http://www.w3.org/1999/xhtml"/>
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
217
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
218 The namespace for a specific element can be altered on an existing factory
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
219 by specifying the new namespace using item access:
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
220
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
221 >>> factory = ElementFactory()
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
222 >>> print factory.html(factory['http://www.w3.org/2000/svg'].g(id=3))
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
223 <html><g id="3" xmlns="http://www.w3.org/2000/svg"/></html>
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
224
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
225 Usually, the `ElementFactory` class is not be used directly. Rather, the
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
226 `tag` instance should be used to create elements.
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
227 """
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
228
19
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
229 def __init__(self, namespace=None):
28
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
230 """Create the factory, optionally bound to the given namespace.
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
231
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
232 @param namespace: the namespace URI for any created elements, or `None`
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
233 for no namespace
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
234 """
20
cc92d74ce9e5 Fix tests broken in [20].
cmlenz
parents: 19
diff changeset
235 if namespace and not isinstance(namespace, Namespace):
19
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
236 namespace = Namespace(namespace)
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
237 self.namespace = namespace
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
238
119
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
239 def __call__(self, *args):
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
240 return Fragment()(*args)
cc2aee07f53b Allow creating fragments from the `tag` object in `markup.builder`.
cmlenz
parents: 98
diff changeset
241
19
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
242 def __getitem__(self, namespace):
28
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
243 """Return a new factory that is bound to the specified namespace."""
19
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
244 return ElementFactory(namespace)
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
245
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
246 def __getattr__(self, name):
28
35956040ba6e More docstrings for the builder module.
cmlenz
parents: 27
diff changeset
247 """Create an `Element` with the given name."""
19
704f10b06507 Enable `ElementFactory` to create namespaced elements.
cmlenz
parents: 17
diff changeset
248 return Element(self.namespace and self.namespace[name] or name)
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
249
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
250
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
251 tag = ElementFactory()
Copyright (C) 2012-2017 Edgewall Software