Mercurial > genshi > genshi-test
annotate genshi/core.py @ 822:ce5ad2d540b3
Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
author | cmlenz |
---|---|
date | Wed, 11 Mar 2009 22:14:32 +0000 |
parents | 7cf2407671c2 |
children | 004f81b59d97 |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
719 | 3 # Copyright (C) 2006-2008 Edgewall Software |
1 | 4 # All rights reserved. |
5 # | |
6 # This software is licensed as described in the file COPYING, which | |
7 # you should have received as part of this distribution. The terms | |
230 | 8 # are also available at http://genshi.edgewall.org/wiki/License. |
1 | 9 # |
10 # This software consists of voluntary contributions made by many | |
11 # individuals. For the exact contribution history, see the revision | |
230 | 12 # history and logs, available at http://genshi.edgewall.org/log/. |
1 | 13 |
14 """Core classes for markup processing.""" | |
15 | |
792
a64cfc8f6fc9
Apply patch to silence a -3 warning about `reduce` removal. Closes #279.
cmlenz
parents:
737
diff
changeset
|
16 try: |
a64cfc8f6fc9
Apply patch to silence a -3 warning about `reduce` removal. Closes #279.
cmlenz
parents:
737
diff
changeset
|
17 from functools import reduce |
a64cfc8f6fc9
Apply patch to silence a -3 warning about `reduce` removal. Closes #279.
cmlenz
parents:
737
diff
changeset
|
18 except ImportError: |
a64cfc8f6fc9
Apply patch to silence a -3 warning about `reduce` removal. Closes #279.
cmlenz
parents:
737
diff
changeset
|
19 pass # builtin in Python <= 2.5 |
634
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
20 from itertools import chain |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
21 import operator |
397
d6e9170c5ccc
* Moved some utility functions from `genshi.core` to `genshi.util` (backwards compatibility preserved via imports)
cmlenz
parents:
382
diff
changeset
|
22 |
d6e9170c5ccc
* Moved some utility functions from `genshi.core` to `genshi.util` (backwards compatibility preserved via imports)
cmlenz
parents:
382
diff
changeset
|
23 from genshi.util import plaintext, stripentities, striptags |
1 | 24 |
377
79a7db5177e9
Add `Attrs` class to `genshi.core.__all__`, so that it can be imported directly from the `genshi` package.
cmlenz
parents:
345
diff
changeset
|
25 __all__ = ['Stream', 'Markup', 'escape', 'unescape', 'Attrs', 'Namespace', |
79a7db5177e9
Add `Attrs` class to `genshi.core.__all__`, so that it can be imported directly from the `genshi` package.
cmlenz
parents:
345
diff
changeset
|
26 'QName'] |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
27 __docformat__ = 'restructuredtext en' |
1 | 28 |
29 | |
17
ad63ad459524
Refactoring to address #6: all match templates are now processed by a single filter, which means that match templates added by included templates are properly applied. A side effect of this refactoring is that `Context` objects may not be reused across multiple template processing runs.
cmlenz
parents:
10
diff
changeset
|
30 class StreamEventKind(str): |
397
d6e9170c5ccc
* Moved some utility functions from `genshi.core` to `genshi.util` (backwards compatibility preserved via imports)
cmlenz
parents:
382
diff
changeset
|
31 """A kind of event on a markup stream.""" |
279
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
32 __slots__ = [] |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
33 _instances = {} |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
34 |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
35 def __new__(cls, val): |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
36 return cls._instances.setdefault(val, str.__new__(cls, val)) |
1 | 37 |
38 | |
39 class Stream(object): | |
40 """Represents a stream of markup events. | |
41 | |
42 This class is basically an iterator over the events. | |
43 | |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
44 Stream events are tuples of the form:: |
397
d6e9170c5ccc
* Moved some utility functions from `genshi.core` to `genshi.util` (backwards compatibility preserved via imports)
cmlenz
parents:
382
diff
changeset
|
45 |
d6e9170c5ccc
* Moved some utility functions from `genshi.core` to `genshi.util` (backwards compatibility preserved via imports)
cmlenz
parents:
382
diff
changeset
|
46 (kind, data, position) |
d6e9170c5ccc
* Moved some utility functions from `genshi.core` to `genshi.util` (backwards compatibility preserved via imports)
cmlenz
parents:
382
diff
changeset
|
47 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
48 where ``kind`` is the event kind (such as `START`, `END`, `TEXT`, etc), |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
49 ``data`` depends on the kind of event, and ``position`` is a |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
50 ``(filename, line, offset)`` tuple that contains the location of the |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
51 original element or text in the input. If the original location is unknown, |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
52 ``position`` is ``(None, -1, -1)``. |
397
d6e9170c5ccc
* Moved some utility functions from `genshi.core` to `genshi.util` (backwards compatibility preserved via imports)
cmlenz
parents:
382
diff
changeset
|
53 |
1 | 54 Also provided are ways to serialize the stream to text. The `serialize()` |
55 method will return an iterator over generated strings, while `render()` | |
56 returns the complete generated text at once. Both accept various parameters | |
57 that impact the way the stream is serialized. | |
58 """ | |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
59 __slots__ = ['events', 'serializer'] |
1 | 60 |
427 | 61 START = StreamEventKind('START') #: a start tag |
62 END = StreamEventKind('END') #: an end tag | |
63 TEXT = StreamEventKind('TEXT') #: literal text | |
460
6b5544bb5a99
Apply patch by Alec Thomas for processing XML declarations (#111). Thanks!
cmlenz
parents:
438
diff
changeset
|
64 XML_DECL = StreamEventKind('XML_DECL') #: XML declaration |
427 | 65 DOCTYPE = StreamEventKind('DOCTYPE') #: doctype declaration |
66 START_NS = StreamEventKind('START_NS') #: start namespace mapping | |
67 END_NS = StreamEventKind('END_NS') #: end namespace mapping | |
68 START_CDATA = StreamEventKind('START_CDATA') #: start CDATA section | |
69 END_CDATA = StreamEventKind('END_CDATA') #: end CDATA section | |
70 PI = StreamEventKind('PI') #: processing instruction | |
71 COMMENT = StreamEventKind('COMMENT') #: comment | |
1 | 72 |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
73 def __init__(self, events, serializer=None): |
1 | 74 """Initialize the stream with a sequence of markup events. |
75 | |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
76 :param events: a sequence or iterable providing the events |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
77 :param serializer: the default serialization method to use for this |
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
78 stream |
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
79 |
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
80 :note: Changed in 0.5: added the `serializer` argument |
1 | 81 """ |
498 | 82 self.events = events #: The underlying iterable producing the events |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
83 self.serializer = serializer #: The default serializion method |
1 | 84 |
85 def __iter__(self): | |
86 return iter(self.events) | |
87 | |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
88 def __or__(self, function): |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
89 """Override the "bitwise or" operator to apply filters or serializers |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
90 to the stream, providing a syntax similar to pipes on Unix shells. |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
91 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
92 Assume the following stream produced by the `HTML` function: |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
93 |
230 | 94 >>> from genshi.input import HTML |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
95 >>> html = HTML('''<p onclick="alert('Whoa')">Hello, world!</p>''') |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
96 >>> print html |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
97 <p onclick="alert('Whoa')">Hello, world!</p> |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
98 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
99 A filter such as the HTML sanitizer can be applied to that stream using |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
100 the pipe notation as follows: |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
101 |
230 | 102 >>> from genshi.filters import HTMLSanitizer |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
103 >>> sanitizer = HTMLSanitizer() |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
104 >>> print html | sanitizer |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
105 <p>Hello, world!</p> |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
106 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
107 Filters can be any function that accepts and produces a stream (where |
397
d6e9170c5ccc
* Moved some utility functions from `genshi.core` to `genshi.util` (backwards compatibility preserved via imports)
cmlenz
parents:
382
diff
changeset
|
108 a stream is anything that iterates over events): |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
109 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
110 >>> def uppercase(stream): |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
111 ... for kind, data, pos in stream: |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
112 ... if kind is TEXT: |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
113 ... data = data.upper() |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
114 ... yield kind, data, pos |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
115 >>> print html | sanitizer | uppercase |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
116 <p>HELLO, WORLD!</p> |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
117 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
118 Serializers can also be used with this notation: |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
119 |
230 | 120 >>> from genshi.output import TextSerializer |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
121 >>> output = TextSerializer() |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
122 >>> print html | sanitizer | uppercase | output |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
123 HELLO, WORLD! |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
124 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
125 Commonly, serializers should be used at the end of the "pipeline"; |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
126 using them somewhere in the middle may produce unexpected results. |
498 | 127 |
128 :param function: the callable object that should be applied as a filter | |
129 :return: the filtered stream | |
130 :rtype: `Stream` | |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
131 """ |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
132 return Stream(_ensure(function(self)), serializer=self.serializer) |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
133 |
123
93bbdcf9428b
Fix for #18: whitespace in space-sensitive elements such as `<pre>` and `<textarea>` is now preserved.
cmlenz
parents:
116
diff
changeset
|
134 def filter(self, *filters): |
93bbdcf9428b
Fix for #18: whitespace in space-sensitive elements such as `<pre>` and `<textarea>` is now preserved.
cmlenz
parents:
116
diff
changeset
|
135 """Apply filters to the stream. |
113
e815c2c07572
Removed the `sanitize()` method from the `Markup` class, and migrate the existing unit tests to `markup.tests.filters`. Provide a `Stream.filter()` method instead which can be used to conveniently apply a filter to a stream.
cmlenz
parents:
111
diff
changeset
|
136 |
123
93bbdcf9428b
Fix for #18: whitespace in space-sensitive elements such as `<pre>` and `<textarea>` is now preserved.
cmlenz
parents:
116
diff
changeset
|
137 This method returns a new stream with the given filters applied. The |
93bbdcf9428b
Fix for #18: whitespace in space-sensitive elements such as `<pre>` and `<textarea>` is now preserved.
cmlenz
parents:
116
diff
changeset
|
138 filters must be callables that accept the stream object as parameter, |
93bbdcf9428b
Fix for #18: whitespace in space-sensitive elements such as `<pre>` and `<textarea>` is now preserved.
cmlenz
parents:
116
diff
changeset
|
139 and return the filtered stream. |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
140 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
141 The call:: |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
142 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
143 stream.filter(filter1, filter2) |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
144 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
145 is equivalent to:: |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
146 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
147 stream | filter1 | filter2 |
498 | 148 |
149 :param filters: one or more callable objects that should be applied as | |
150 filters | |
151 :return: the filtered stream | |
152 :rtype: `Stream` | |
113
e815c2c07572
Removed the `sanitize()` method from the `Markup` class, and migrate the existing unit tests to `markup.tests.filters`. Provide a `Stream.filter()` method instead which can be used to conveniently apply a filter to a stream.
cmlenz
parents:
111
diff
changeset
|
153 """ |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
154 return reduce(operator.or_, (self,) + filters) |
113
e815c2c07572
Removed the `sanitize()` method from the `Markup` class, and migrate the existing unit tests to `markup.tests.filters`. Provide a `Stream.filter()` method instead which can be used to conveniently apply a filter to a stream.
cmlenz
parents:
111
diff
changeset
|
155 |
688
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
156 def render(self, method=None, encoding='utf-8', out=None, **kwargs): |
1 | 157 """Return a string representation of the stream. |
158 | |
498 | 159 Any additional keyword arguments are passed to the serializer, and thus |
160 depend on the `method` parameter value. | |
161 | |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
162 :param method: determines how the stream is serialized; can be either |
200
50eab0469148
Add serialization to plain text, based on cboos' patch. Closes #41.
cmlenz
parents:
182
diff
changeset
|
163 "xml", "xhtml", "html", "text", or a custom serializer |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
164 class; if `None`, the default serialization method of |
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
165 the stream is used |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
166 :param encoding: how the output string should be encoded; if set to |
1 | 167 `None`, this method returns a `unicode` object |
688
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
168 :param out: a file-like object that the output should be written to |
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
169 instead of being returned as one big string; note that if |
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
170 this is a file or socket (or similar), the `encoding` must |
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
171 not be `None` (that is, the output must be encoded) |
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
172 :return: a `str` or `unicode` object (depending on the `encoding` |
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
173 parameter), or `None` if the `out` parameter is provided |
498 | 174 :rtype: `basestring` |
688
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
175 |
498 | 176 :see: XMLSerializer, XHTMLSerializer, HTMLSerializer, TextSerializer |
688
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
177 :note: Changed in 0.5: added the `out` parameter |
1 | 178 """ |
462 | 179 from genshi.output import encode |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
180 if method is None: |
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
181 method = self.serializer or 'xml' |
123
93bbdcf9428b
Fix for #18: whitespace in space-sensitive elements such as `<pre>` and `<textarea>` is now preserved.
cmlenz
parents:
116
diff
changeset
|
182 generator = self.serialize(method=method, **kwargs) |
688
88814cc26d2b
The `Stream.render` now accepts an optional `out` parameter that can be used to pass in a writable file-like object to use for assembling the output, instead of building a big string and returning it.
cmlenz
parents:
685
diff
changeset
|
183 return encode(generator, method=method, encoding=encoding, out=out) |
1 | 184 |
278
8de2620504b9
Fix the handling of namespace context for match templates.
cmlenz
parents:
230
diff
changeset
|
185 def select(self, path, namespaces=None, variables=None): |
1 | 186 """Return a new stream that contains the events matching the given |
187 XPath expression. | |
188 | |
576 | 189 >>> from genshi import HTML |
190 >>> stream = HTML('<doc><elem>foo</elem><elem>bar</elem></doc>') | |
191 >>> print stream.select('elem') | |
192 <elem>foo</elem><elem>bar</elem> | |
193 >>> print stream.select('elem/text()') | |
194 foobar | |
195 | |
196 Note that the outermost element of the stream becomes the *context | |
197 node* for the XPath test. That means that the expression "doc" would | |
198 not match anything in the example above, because it only tests against | |
199 child elements of the outermost element: | |
200 | |
201 >>> print stream.select('doc') | |
202 <BLANKLINE> | |
203 | |
204 You can use the "." expression to match the context node itself | |
205 (although that usually makes little sense): | |
206 | |
207 >>> print stream.select('.') | |
208 <doc><elem>foo</elem><elem>bar</elem></doc> | |
209 | |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
210 :param path: a string containing the XPath expression |
435 | 211 :param namespaces: mapping of namespace prefixes used in the path |
212 :param variables: mapping of variable names to values | |
213 :return: the selected substream | |
498 | 214 :rtype: `Stream` |
435 | 215 :raises PathSyntaxError: if the given path expression is invalid or not |
216 supported | |
1 | 217 """ |
230 | 218 from genshi.path import Path |
278
8de2620504b9
Fix the handling of namespace context for match templates.
cmlenz
parents:
230
diff
changeset
|
219 return Path(path).select(self, namespaces, variables) |
1 | 220 |
123
93bbdcf9428b
Fix for #18: whitespace in space-sensitive elements such as `<pre>` and `<textarea>` is now preserved.
cmlenz
parents:
116
diff
changeset
|
221 def serialize(self, method='xml', **kwargs): |
1 | 222 """Generate strings corresponding to a specific serialization of the |
223 stream. | |
224 | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
225 Unlike the `render()` method, this method is a generator that returns |
1 | 226 the serialized output incrementally, as opposed to returning a single |
227 string. | |
228 | |
498 | 229 Any additional keyword arguments are passed to the serializer, and thus |
230 depend on the `method` parameter value. | |
231 | |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
232 :param method: determines how the stream is serialized; can be either |
200
50eab0469148
Add serialization to plain text, based on cboos' patch. Closes #41.
cmlenz
parents:
182
diff
changeset
|
233 "xml", "xhtml", "html", "text", or a custom serializer |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
234 class; if `None`, the default serialization method of |
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
235 the stream is used |
498 | 236 :return: an iterator over the serialization results (`Markup` or |
237 `unicode` objects, depending on the serialization method) | |
238 :rtype: ``iterator`` | |
239 :see: XMLSerializer, XHTMLSerializer, HTMLSerializer, TextSerializer | |
1 | 240 """ |
462 | 241 from genshi.output import get_serializer |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
242 if method is None: |
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
593
diff
changeset
|
243 method = self.serializer or 'xml' |
462 | 244 return get_serializer(method, **kwargs)(_ensure(self)) |
1 | 245 |
246 def __str__(self): | |
247 return self.render() | |
248 | |
249 def __unicode__(self): | |
250 return self.render(encoding=None) | |
251 | |
737
686bbeecb9ac
Implement the `__html__` protocol as suggested in #202. This would allow Genshi to be used in combination with other markup generating tools, as long as they support the same protocol.
cmlenz
parents:
719
diff
changeset
|
252 def __html__(self): |
686bbeecb9ac
Implement the `__html__` protocol as suggested in #202. This would allow Genshi to be used in combination with other markup generating tools, as long as they support the same protocol.
cmlenz
parents:
719
diff
changeset
|
253 return self |
686bbeecb9ac
Implement the `__html__` protocol as suggested in #202. This would allow Genshi to be used in combination with other markup generating tools, as long as they support the same protocol.
cmlenz
parents:
719
diff
changeset
|
254 |
1 | 255 |
69 | 256 START = Stream.START |
257 END = Stream.END | |
258 TEXT = Stream.TEXT | |
460
6b5544bb5a99
Apply patch by Alec Thomas for processing XML declarations (#111). Thanks!
cmlenz
parents:
438
diff
changeset
|
259 XML_DECL = Stream.XML_DECL |
69 | 260 DOCTYPE = Stream.DOCTYPE |
261 START_NS = Stream.START_NS | |
262 END_NS = Stream.END_NS | |
143
ef761afcedff
CDATA sections in XML input now appear as CDATA sections in the output. This should address the problem with escaping the contents of `<style>` and `<script>` elements, which would only get interpreted correctly if the output was served as `application/xhtml+xml`. Closes #24.
cmlenz
parents:
141
diff
changeset
|
263 START_CDATA = Stream.START_CDATA |
ef761afcedff
CDATA sections in XML input now appear as CDATA sections in the output. This should address the problem with escaping the contents of `<style>` and `<script>` elements, which would only get interpreted correctly if the output was served as `application/xhtml+xml`. Closes #24.
cmlenz
parents:
141
diff
changeset
|
264 END_CDATA = Stream.END_CDATA |
69 | 265 PI = Stream.PI |
266 COMMENT = Stream.COMMENT | |
267 | |
111
8a4d9064f363
Some fixes and more unit tests for the XPath engine.
cmlenz
parents:
100
diff
changeset
|
268 def _ensure(stream): |
8a4d9064f363
Some fixes and more unit tests for the XPath engine.
cmlenz
parents:
100
diff
changeset
|
269 """Ensure that every item on the stream is actually a markup event.""" |
634
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
270 stream = iter(stream) |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
271 event = stream.next() |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
272 |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
273 # Check whether the iterable is a real markup event stream by examining the |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
274 # first item it yields; if it's not we'll need to do some conversion |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
275 if type(event) is not tuple or len(event) != 3: |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
276 for event in chain([event], stream): |
145
56d534eb53f9
* Fix error in expression evaluation when the expression evaluates to an iterable that does not produce event tuples.
cmlenz
parents:
143
diff
changeset
|
277 if hasattr(event, 'totuple'): |
56d534eb53f9
* Fix error in expression evaluation when the expression evaluates to an iterable that does not produce event tuples.
cmlenz
parents:
143
diff
changeset
|
278 event = event.totuple() |
56d534eb53f9
* Fix error in expression evaluation when the expression evaluates to an iterable that does not produce event tuples.
cmlenz
parents:
143
diff
changeset
|
279 else: |
56d534eb53f9
* Fix error in expression evaluation when the expression evaluates to an iterable that does not produce event tuples.
cmlenz
parents:
143
diff
changeset
|
280 event = TEXT, unicode(event), (None, -1, -1) |
634
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
281 yield event |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
282 return |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
283 |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
284 # This looks like a markup event stream, so we'll just pass it through |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
285 # unchanged |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
286 yield event |
60a1fb39f915
Performance optimization for the `genshi.core._ensure` function: instead of checking whether we're dealing with a markup event stream for every item in the iterable, we now check only the first item, and treat the rest of the iterable depending on whether the first one looks like an event.
cmlenz
parents:
605
diff
changeset
|
287 for event in stream: |
145
56d534eb53f9
* Fix error in expression evaluation when the expression evaluates to an iterable that does not produce event tuples.
cmlenz
parents:
143
diff
changeset
|
288 yield event |
111
8a4d9064f363
Some fixes and more unit tests for the XPath engine.
cmlenz
parents:
100
diff
changeset
|
289 |
69 | 290 |
345 | 291 class Attrs(tuple): |
292 """Immutable sequence type that stores the attributes of an element. | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
293 |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
294 Ordering of the attributes is preserved, while access by name is also |
345 | 295 supported. |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
296 |
182
41db0260ebb1
Renamed `Attributes` to `Attrs` to reduce the verbosity.
cmlenz
parents:
172
diff
changeset
|
297 >>> attrs = Attrs([('href', '#'), ('title', 'Foo')]) |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
298 >>> attrs |
403
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
299 Attrs([('href', '#'), ('title', 'Foo')]) |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
300 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
301 >>> 'href' in attrs |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
302 True |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
303 >>> 'tabindex' in attrs |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
304 False |
403
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
305 >>> attrs.get('title') |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
306 'Foo' |
345 | 307 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
308 Instances may not be manipulated directly. Instead, the operators ``|`` and |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
309 ``-`` can be used to produce new instances that have specific attributes |
345 | 310 added, replaced or removed. |
311 | |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
312 To remove an attribute, use the ``-`` operator. The right hand side can be |
345 | 313 either a string or a set/sequence of strings, identifying the name(s) of |
314 the attribute(s) to remove: | |
315 | |
316 >>> attrs - 'title' | |
403
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
317 Attrs([('href', '#')]) |
345 | 318 >>> attrs - ('title', 'href') |
319 Attrs() | |
320 | |
321 The original instance is not modified, but the operator can of course be | |
322 used with an assignment: | |
323 | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
324 >>> attrs |
403
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
325 Attrs([('href', '#'), ('title', 'Foo')]) |
345 | 326 >>> attrs -= 'title' |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
327 >>> attrs |
403
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
328 Attrs([('href', '#')]) |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
329 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
330 To add a new attribute, use the ``|`` operator, where the right hand value |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
331 is a sequence of ``(name, value)`` tuples (which includes `Attrs` |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
332 instances): |
170
f1ac0510d392
Allow initialization of `Attributes` with keyword arguments.
cmlenz
parents:
161
diff
changeset
|
333 |
403
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
334 >>> attrs | [('title', 'Bar')] |
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
335 Attrs([('href', '#'), ('title', 'Bar')]) |
171
34e0455ada92
Follow-up to [214]: allow initializing `Attributes` with attribute names that contain dashes or conflict with a reserved word (such as ?class?.)
cmlenz
parents:
170
diff
changeset
|
336 |
345 | 337 If the attributes already contain an attribute with a given name, the value |
338 of that attribute is replaced: | |
171
34e0455ada92
Follow-up to [214]: allow initializing `Attributes` with attribute names that contain dashes or conflict with a reserved word (such as ?class?.)
cmlenz
parents:
170
diff
changeset
|
339 |
403
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
340 >>> attrs | [('href', 'http://example.org/')] |
32b283e1d310
Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents:
397
diff
changeset
|
341 Attrs([('href', 'http://example.org/')]) |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
342 """ |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
343 __slots__ = [] |
1 | 344 |
345 def __contains__(self, name): | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
346 """Return whether the list includes an attribute with the specified |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
347 name. |
498 | 348 |
349 :return: `True` if the list includes the attribute | |
350 :rtype: `bool` | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
351 """ |
133
b9a0031d4bbb
Minor cleanup and performance improvement for the builder module.
cmlenz
parents:
123
diff
changeset
|
352 for attr, _ in self: |
b9a0031d4bbb
Minor cleanup and performance improvement for the builder module.
cmlenz
parents:
123
diff
changeset
|
353 if attr == name: |
b9a0031d4bbb
Minor cleanup and performance improvement for the builder module.
cmlenz
parents:
123
diff
changeset
|
354 return True |
1 | 355 |
345 | 356 def __getslice__(self, i, j): |
593 | 357 """Return a slice of the attributes list. |
358 | |
359 >>> attrs = Attrs([('href', '#'), ('title', 'Foo')]) | |
360 >>> attrs[1:] | |
361 Attrs([('title', 'Foo')]) | |
362 """ | |
345 | 363 return Attrs(tuple.__getslice__(self, i, j)) |
364 | |
365 def __or__(self, attrs): | |
366 """Return a new instance that contains the attributes in `attrs` in | |
367 addition to any already existing attributes. | |
498 | 368 |
369 :return: a new instance with the merged attributes | |
370 :rtype: `Attrs` | |
345 | 371 """ |
372 repl = dict([(an, av) for an, av in attrs if an in self]) | |
373 return Attrs([(sn, repl.get(sn, sv)) for sn, sv in self] + | |
374 [(an, av) for an, av in attrs if an not in self]) | |
375 | |
326
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
376 def __repr__(self): |
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
377 if not self: |
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
378 return 'Attrs()' |
345 | 379 return 'Attrs([%s])' % ', '.join([repr(item) for item in self]) |
380 | |
381 def __sub__(self, names): | |
382 """Return a new instance with all attributes with a name in `names` are | |
383 removed. | |
498 | 384 |
385 :param names: the names of the attributes to remove | |
386 :return: a new instance with the attribute removed | |
387 :rtype: `Attrs` | |
345 | 388 """ |
389 if isinstance(names, basestring): | |
390 names = (names,) | |
391 return Attrs([(name, val) for name, val in self if name not in names]) | |
326
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
392 |
1 | 393 def get(self, name, default=None): |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
394 """Return the value of the attribute with the specified name, or the |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
395 value of the `default` parameter if no such attribute is found. |
435 | 396 |
397 :param name: the name of the attribute | |
398 :param default: the value to return when the attribute does not exist | |
399 :return: the attribute value, or the `default` value if that attribute | |
400 does not exist | |
498 | 401 :rtype: `object` |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
402 """ |
1 | 403 for attr, value in self: |
404 if attr == name: | |
405 return value | |
406 return default | |
407 | |
77
f1aa49c759b2
* Simplify implementation of the individual XPath tests (use closures instead of callable classes)
cmlenz
parents:
73
diff
changeset
|
408 def totuple(self): |
161
a25f9fc5787d
Various docstring additions and other cosmetic changes.
cmlenz
parents:
147
diff
changeset
|
409 """Return the attributes as a markup event. |
a25f9fc5787d
Various docstring additions and other cosmetic changes.
cmlenz
parents:
147
diff
changeset
|
410 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
411 The returned event is a `TEXT` event, the data is the value of all |
161
a25f9fc5787d
Various docstring additions and other cosmetic changes.
cmlenz
parents:
147
diff
changeset
|
412 attributes joined together. |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
413 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
414 >>> Attrs([('href', '#'), ('title', 'Foo')]).totuple() |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
415 ('TEXT', u'#Foo', (None, -1, -1)) |
498 | 416 |
417 :return: a `TEXT` event | |
418 :rtype: `tuple` | |
161
a25f9fc5787d
Various docstring additions and other cosmetic changes.
cmlenz
parents:
147
diff
changeset
|
419 """ |
77
f1aa49c759b2
* Simplify implementation of the individual XPath tests (use closures instead of callable classes)
cmlenz
parents:
73
diff
changeset
|
420 return TEXT, u''.join([x[1] for x in self]), (None, -1, -1) |
f1aa49c759b2
* Simplify implementation of the individual XPath tests (use closures instead of callable classes)
cmlenz
parents:
73
diff
changeset
|
421 |
1 | 422 |
423 class Markup(unicode): | |
424 """Marks a string as being safe for inclusion in HTML/XML output without | |
425 needing to be escaped. | |
426 """ | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
427 __slots__ = [] |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
428 |
1 | 429 def __add__(self, other): |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
430 return Markup(unicode(self) + unicode(escape(other))) |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
431 |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
432 def __radd__(self, other): |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
433 return Markup(unicode(escape(other)) + unicode(self)) |
1 | 434 |
435 def __mod__(self, args): | |
713
a58a50e89d04
The `Markup` class now supports mappings for right hand of the `%` (modulo) operator in the same way the Python string classes do, except that the substituted values are escape. Also, the special constructor which took positional arguments that would be substituted was removed. Thus the `Markup` class now supports the same arguments as that of its `unicode` base class. Closes #211. Many thanks to Christian Boos for the patch!
cmlenz
parents:
688
diff
changeset
|
436 if isinstance(args, dict): |
a58a50e89d04
The `Markup` class now supports mappings for right hand of the `%` (modulo) operator in the same way the Python string classes do, except that the substituted values are escape. Also, the special constructor which took positional arguments that would be substituted was removed. Thus the `Markup` class now supports the same arguments as that of its `unicode` base class. Closes #211. Many thanks to Christian Boos for the patch!
cmlenz
parents:
688
diff
changeset
|
437 args = dict(zip(args.keys(), map(escape, args.values()))) |
a58a50e89d04
The `Markup` class now supports mappings for right hand of the `%` (modulo) operator in the same way the Python string classes do, except that the substituted values are escape. Also, the special constructor which took positional arguments that would be substituted was removed. Thus the `Markup` class now supports the same arguments as that of its `unicode` base class. Closes #211. Many thanks to Christian Boos for the patch!
cmlenz
parents:
688
diff
changeset
|
438 elif isinstance(args, (list, tuple)): |
a58a50e89d04
The `Markup` class now supports mappings for right hand of the `%` (modulo) operator in the same way the Python string classes do, except that the substituted values are escape. Also, the special constructor which took positional arguments that would be substituted was removed. Thus the `Markup` class now supports the same arguments as that of its `unicode` base class. Closes #211. Many thanks to Christian Boos for the patch!
cmlenz
parents:
688
diff
changeset
|
439 args = tuple(map(escape, args)) |
a58a50e89d04
The `Markup` class now supports mappings for right hand of the `%` (modulo) operator in the same way the Python string classes do, except that the substituted values are escape. Also, the special constructor which took positional arguments that would be substituted was removed. Thus the `Markup` class now supports the same arguments as that of its `unicode` base class. Closes #211. Many thanks to Christian Boos for the patch!
cmlenz
parents:
688
diff
changeset
|
440 else: |
a58a50e89d04
The `Markup` class now supports mappings for right hand of the `%` (modulo) operator in the same way the Python string classes do, except that the substituted values are escape. Also, the special constructor which took positional arguments that would be substituted was removed. Thus the `Markup` class now supports the same arguments as that of its `unicode` base class. Closes #211. Many thanks to Christian Boos for the patch!
cmlenz
parents:
688
diff
changeset
|
441 args = escape(args) |
a58a50e89d04
The `Markup` class now supports mappings for right hand of the `%` (modulo) operator in the same way the Python string classes do, except that the substituted values are escape. Also, the special constructor which took positional arguments that would be substituted was removed. Thus the `Markup` class now supports the same arguments as that of its `unicode` base class. Closes #211. Many thanks to Christian Boos for the patch!
cmlenz
parents:
688
diff
changeset
|
442 return Markup(unicode.__mod__(self, args)) |
1 | 443 |
444 def __mul__(self, num): | |
445 return Markup(unicode(self) * num) | |
446 | |
204
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
447 def __rmul__(self, num): |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
448 return Markup(num * unicode(self)) |
516a6cae0aa8
* Implement reverse add/mul operators for `Markup` class, so that the result is also a `Markup` instance.
cmlenz
parents:
200
diff
changeset
|
449 |
17
ad63ad459524
Refactoring to address #6: all match templates are now processed by a single filter, which means that match templates added by included templates are properly applied. A side effect of this refactoring is that `Context` objects may not be reused across multiple template processing runs.
cmlenz
parents:
10
diff
changeset
|
450 def __repr__(self): |
382
d7da3fba7faf
* Added documentation for the various stream event kinds.
cmlenz
parents:
377
diff
changeset
|
451 return '<%s %r>' % (self.__class__.__name__, unicode(self)) |
17
ad63ad459524
Refactoring to address #6: all match templates are now processed by a single filter, which means that match templates added by included templates are properly applied. A side effect of this refactoring is that `Context` objects may not be reused across multiple template processing runs.
cmlenz
parents:
10
diff
changeset
|
452 |
54 | 453 def join(self, seq, escape_quotes=True): |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
454 """Return a `Markup` object which is the concatenation of the strings |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
455 in the given sequence, where this `Markup` object is the separator |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
456 between the joined elements. |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
457 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
458 Any element in the sequence that is not a `Markup` instance is |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
459 automatically escaped. |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
460 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
461 :param seq: the sequence of strings to join |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
462 :param escape_quotes: whether double quote characters in the elements |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
463 should be escaped |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
464 :return: the joined `Markup` object |
498 | 465 :rtype: `Markup` |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
466 :see: `escape` |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
467 """ |
54 | 468 return Markup(unicode(self).join([escape(item, quotes=escape_quotes) |
34 | 469 for item in seq])) |
1 | 470 |
822
ce5ad2d540b3
Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents:
793
diff
changeset
|
471 @classmethod |
1 | 472 def escape(cls, text, quotes=True): |
473 """Create a Markup instance from a string and escape special characters | |
474 it may contain (<, >, & and \"). | |
475 | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
476 >>> escape('"1 < 2"') |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
477 <Markup u'"1 < 2"'> |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
478 |
1 | 479 If the `quotes` parameter is set to `False`, the \" character is left |
480 as is. Escaping quotes is generally only required for strings that are | |
481 to be used in attribute values. | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
482 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
483 >>> escape('"1 < 2"', quotes=False) |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
484 <Markup u'"1 < 2"'> |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
485 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
486 :param text: the text to escape |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
487 :param quotes: if ``True``, double quote characters are escaped in |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
488 addition to the other special characters |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
489 :return: the escaped `Markup` string |
498 | 490 :rtype: `Markup` |
1 | 491 """ |
73 | 492 if not text: |
493 return cls() | |
494 if type(text) is cls: | |
1 | 495 return text |
737
686bbeecb9ac
Implement the `__html__` protocol as suggested in #202. This would allow Genshi to be used in combination with other markup generating tools, as long as they support the same protocol.
cmlenz
parents:
719
diff
changeset
|
496 if hasattr(text, '__html__'): |
686bbeecb9ac
Implement the `__html__` protocol as suggested in #202. This would allow Genshi to be used in combination with other markup generating tools, as long as they support the same protocol.
cmlenz
parents:
719
diff
changeset
|
497 return Markup(text.__html__()) |
686bbeecb9ac
Implement the `__html__` protocol as suggested in #202. This would allow Genshi to be used in combination with other markup generating tools, as long as they support the same protocol.
cmlenz
parents:
719
diff
changeset
|
498 |
73 | 499 text = unicode(text).replace('&', '&') \ |
500 .replace('<', '<') \ | |
501 .replace('>', '>') | |
1 | 502 if quotes: |
503 text = text.replace('"', '"') | |
504 return cls(text) | |
505 | |
506 def unescape(self): | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
507 """Reverse-escapes &, <, >, and \" and returns a `unicode` object. |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
508 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
509 >>> Markup('1 < 2').unescape() |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
510 u'1 < 2' |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
511 |
498 | 512 :return: the unescaped string |
513 :rtype: `unicode` | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
514 :see: `genshi.core.unescape` |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
515 """ |
1 | 516 if not self: |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
517 return u'' |
1 | 518 return unicode(self).replace('"', '"') \ |
519 .replace('>', '>') \ | |
520 .replace('<', '<') \ | |
521 .replace('&', '&') | |
522 | |
116 | 523 def stripentities(self, keepxmlentities=False): |
524 """Return a copy of the text with any character or numeric entities | |
525 replaced by the equivalent UTF-8 characters. | |
526 | |
527 If the `keepxmlentities` parameter is provided and evaluates to `True`, | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
528 the core XML entities (``&``, ``'``, ``>``, ``<`` and |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
529 ``"``) are not stripped. |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
530 |
498 | 531 :return: a `Markup` instance with entities removed |
532 :rtype: `Markup` | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
533 :see: `genshi.util.stripentities` |
6 | 534 """ |
116 | 535 return Markup(stripentities(self, keepxmlentities=keepxmlentities)) |
536 | |
537 def striptags(self): | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
538 """Return a copy of the text with all XML/HTML tags removed. |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
539 |
498 | 540 :return: a `Markup` instance with all tags removed |
541 :rtype: `Markup` | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
542 :see: `genshi.util.striptags` |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
543 """ |
116 | 544 return Markup(striptags(self)) |
1 | 545 |
546 | |
541 | 547 try: |
548 from genshi._speedups import Markup | |
549 except ImportError: | |
550 pass # just use the Python implementation | |
551 | |
1 | 552 escape = Markup.escape |
553 | |
554 def unescape(text): | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
555 """Reverse-escapes &, <, >, and \" and returns a `unicode` object. |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
556 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
557 >>> unescape(Markup('1 < 2')) |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
558 u'1 < 2' |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
559 |
498 | 560 If the provided `text` object is not a `Markup` instance, it is returned |
561 unchanged. | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
562 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
563 >>> unescape('1 < 2') |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
564 '1 < 2' |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
565 |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
566 :param text: the text to unescape |
498 | 567 :return: the unescsaped string |
568 :rtype: `unicode` | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
569 """ |
1 | 570 if not isinstance(text, Markup): |
571 return text | |
572 return text.unescape() | |
573 | |
574 | |
575 class Namespace(object): | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
576 """Utility class creating and testing elements with a namespace. |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
577 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
578 Internally, namespace URIs are encoded in the `QName` of any element or |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
579 attribute, the namespace URI being enclosed in curly braces. This class |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
580 helps create and test these strings. |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
581 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
582 A `Namespace` object is instantiated with the namespace URI. |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
583 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
584 >>> html = Namespace('http://www.w3.org/1999/xhtml') |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
585 >>> html |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
586 <Namespace "http://www.w3.org/1999/xhtml"> |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
587 >>> html.uri |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
588 u'http://www.w3.org/1999/xhtml' |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
589 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
590 The `Namespace` object can than be used to generate `QName` objects with |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
591 that namespace: |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
592 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
593 >>> html.body |
326
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
594 QName(u'http://www.w3.org/1999/xhtml}body') |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
595 >>> html.body.localname |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
596 u'body' |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
597 >>> html.body.namespace |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
598 u'http://www.w3.org/1999/xhtml' |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
599 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
600 The same works using item access notation, which is useful for element or |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
601 attribute names that are not valid Python identifiers: |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
602 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
603 >>> html['body'] |
326
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
604 QName(u'http://www.w3.org/1999/xhtml}body') |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
605 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
606 A `Namespace` object can also be used to test whether a specific `QName` |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
408
diff
changeset
|
607 belongs to that namespace using the ``in`` operator: |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
608 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
609 >>> qname = html.body |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
610 >>> qname in html |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
611 True |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
612 >>> qname in Namespace('http://www.w3.org/2002/06/xhtml2') |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
613 False |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
614 """ |
224
e4dad1145f84
Implement support for namespace prefixes in XPath expressions.
cmlenz
parents:
204
diff
changeset
|
615 def __new__(cls, uri): |
e4dad1145f84
Implement support for namespace prefixes in XPath expressions.
cmlenz
parents:
204
diff
changeset
|
616 if type(uri) is cls: |
e4dad1145f84
Implement support for namespace prefixes in XPath expressions.
cmlenz
parents:
204
diff
changeset
|
617 return uri |
685 | 618 return object.__new__(cls) |
224
e4dad1145f84
Implement support for namespace prefixes in XPath expressions.
cmlenz
parents:
204
diff
changeset
|
619 |
279
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
620 def __getnewargs__(self): |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
621 return (self.uri,) |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
622 |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
623 def __getstate__(self): |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
624 return self.uri |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
625 |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
626 def __setstate__(self, uri): |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
627 self.uri = uri |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
628 |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
629 def __init__(self, uri): |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
630 self.uri = unicode(uri) |
1 | 631 |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
632 def __contains__(self, qname): |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
633 return qname.namespace == self.uri |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
634 |
278
8de2620504b9
Fix the handling of namespace context for match templates.
cmlenz
parents:
230
diff
changeset
|
635 def __ne__(self, other): |
8de2620504b9
Fix the handling of namespace context for match templates.
cmlenz
parents:
230
diff
changeset
|
636 return not self == other |
8de2620504b9
Fix the handling of namespace context for match templates.
cmlenz
parents:
230
diff
changeset
|
637 |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
638 def __eq__(self, other): |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
639 if isinstance(other, Namespace): |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
640 return self.uri == other.uri |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
641 return self.uri == other |
1 | 642 |
643 def __getitem__(self, name): | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
644 return QName(self.uri + u'}' + name) |
1 | 645 __getattr__ = __getitem__ |
646 | |
793 | 647 def __hash__(self): |
648 return hash(self.uri) | |
649 | |
1 | 650 def __repr__(self): |
651 return '<Namespace "%s">' % self.uri | |
652 | |
653 def __str__(self): | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
654 return self.uri.encode('utf-8') |
1 | 655 |
656 def __unicode__(self): | |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
657 return self.uri |
1 | 658 |
659 | |
147
f7fb556f2678
Use `xmlcharrefreplace` when encoding the output in `Stream.render()`, so that encoding the output to legacy encodings such as ASCII or ISO-8859-1 should always work.
cmlenz
parents:
145
diff
changeset
|
660 # The namespace used by attributes such as xml:lang and xml:space |
141
b3ceaa35fb6b
* No escaping of `<script>` or `<style>` tags in HTML output (see #24)
cmlenz
parents:
140
diff
changeset
|
661 XML_NAMESPACE = Namespace('http://www.w3.org/XML/1998/namespace') |
b3ceaa35fb6b
* No escaping of `<script>` or `<style>` tags in HTML output (see #24)
cmlenz
parents:
140
diff
changeset
|
662 |
b3ceaa35fb6b
* No escaping of `<script>` or `<style>` tags in HTML output (see #24)
cmlenz
parents:
140
diff
changeset
|
663 |
1 | 664 class QName(unicode): |
665 """A qualified element or attribute name. | |
666 | |
667 The unicode value of instances of this class contains the qualified name of | |
666
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
668 the element or attribute, in the form ``{namespace-uri}local-name``. The |
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
669 namespace URI can be obtained through the additional `namespace` attribute, |
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
670 while the local name can be accessed through the `localname` attribute. |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
671 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
672 >>> qname = QName('foo') |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
673 >>> qname |
326
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
674 QName(u'foo') |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
675 >>> qname.localname |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
676 u'foo' |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
677 >>> qname.namespace |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
678 |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
679 >>> qname = QName('http://www.w3.org/1999/xhtml}body') |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
680 >>> qname |
326
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
681 QName(u'http://www.w3.org/1999/xhtml}body') |
18
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
682 >>> qname.localname |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
683 u'body' |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
684 >>> qname.namespace |
4cbebb15a834
Actually make use of the `markup.core.Namespace` class, and add a couple of doctests.
cmlenz
parents:
17
diff
changeset
|
685 u'http://www.w3.org/1999/xhtml' |
1 | 686 """ |
687 __slots__ = ['namespace', 'localname'] | |
688 | |
689 def __new__(cls, qname): | |
666
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
690 """Create the `QName` instance. |
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
691 |
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
692 :param qname: the qualified name as a string of the form |
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
693 ``{namespace-uri}local-name``, where the leading curly |
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
694 brace is optional |
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
695 """ |
100 | 696 if type(qname) is cls: |
1 | 697 return qname |
698 | |
666
9729855cacf4
`QName` can now be constructed from a string with a leading curly brace, and some doc improvements. Closes #164.
cmlenz
parents:
634
diff
changeset
|
699 parts = qname.lstrip(u'{').split(u'}', 1) |
100 | 700 if len(parts) > 1: |
136 | 701 self = unicode.__new__(cls, u'{%s' % qname) |
702 self.namespace, self.localname = map(unicode, parts) | |
1 | 703 else: |
704 self = unicode.__new__(cls, qname) | |
136 | 705 self.namespace, self.localname = None, unicode(qname) |
1 | 706 return self |
279
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
707 |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
708 def __getnewargs__(self): |
4b5b4653d41e
Some adjustments to make core data structures picklable (requires protocol 2).
cmlenz
parents:
278
diff
changeset
|
709 return (self.lstrip('{'),) |
326
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
710 |
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
711 def __repr__(self): |
08ada6b4b767
Fixed `__repr__` of the `QName`, `Attrs`, and `Expression` classes so that the output can be used as code to instantiate the object again.
cmlenz
parents:
279
diff
changeset
|
712 return 'QName(%s)' % unicode.__repr__(self.lstrip('{')) |