annotate genshi/core.py @ 793:7cf2407671c2

Get rid of a couple more -3 warnings.
author cmlenz
date Mon, 08 Dec 2008 21:15:19 +0000
parents a64cfc8f6fc9
children ce5ad2d540b3
rev   line source
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
2 #
719
09a90feb9269 Fix copyright years.
cmlenz
parents: 713
diff changeset
3 # Copyright (C) 2006-2008 Edgewall Software
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
4 # All rights reserved.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
5 #
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
230
24757b771651 Renamed Markup to Genshi in repository.
cmlenz
parents: 224
diff changeset
8 # are also available at http://genshi.edgewall.org/wiki/License.
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
9 #
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
230
24757b771651 Renamed Markup to Genshi in repository.
cmlenz
parents: 224
diff changeset
12 # history and logs, available at http://genshi.edgewall.org/log/.
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
13
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
14 """Core classes for markup processing."""
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
28
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
37
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
38
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
39 class Stream(object):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
40 """Represents a stream of markup events.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
41
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
42 This class is basically an iterator over the events.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
54 Also provided are ways to serialize the stream to text. The `serialize()`
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
55 method will return an iterator over generated strings, while `render()`
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
56 returns the complete generated text at once. Both accept various parameters
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
57 that impact the way the stream is serialized.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
60
427
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
61 START = StreamEventKind('START') #: a start tag
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
62 END = StreamEventKind('END') #: an end tag
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
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
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
65 DOCTYPE = StreamEventKind('DOCTYPE') #: doctype declaration
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
66 START_NS = StreamEventKind('START_NS') #: start namespace mapping
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
67 END_NS = StreamEventKind('END_NS') #: end namespace mapping
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
68 START_CDATA = StreamEventKind('START_CDATA') #: start CDATA section
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
69 END_CDATA = StreamEventKind('END_CDATA') #: end CDATA section
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
70 PI = StreamEventKind('PI') #: processing instruction
68a8308309b9 More API documentation.
cmlenz
parents: 425
diff changeset
71 COMMENT = StreamEventKind('COMMENT') #: comment
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
74 """Initialize the stream with a sequence of markup events.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
81 """
498
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
84
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
85 def __iter__(self):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
86 return iter(self.events)
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
24757b771651 Renamed Markup to Genshi in repository.
cmlenz
parents: 224
diff changeset
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
24757b771651 Renamed Markup to Genshi in repository.
cmlenz
parents: 224
diff changeset
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
24757b771651 Renamed Markup to Genshi in repository.
cmlenz
parents: 224
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
127
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
128 :param function: the callable object that should be applied as a filter
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
129 :return: the filtered stream
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
148
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
149 :param filters: one or more callable objects that should be applied as
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
150 filters
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
151 :return: the filtered stream
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
157 """Return a string representation of the stream.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
158
498
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
159 Any additional keyword arguments are passed to the serializer, and thus
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
160 depend on the `method` parameter value.
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
178 """
462
c107f6f4c558 Add lower-level serialization functions.
cmlenz
parents: 460
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
186 """Return a new stream that contains the events matching the given
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
187 XPath expression.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
188
576
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
189 >>> from genshi import HTML
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
190 >>> stream = HTML('<doc><elem>foo</elem><elem>bar</elem></doc>')
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
191 >>> print stream.select('elem')
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
192 <elem>foo</elem><elem>bar</elem>
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
193 >>> print stream.select('elem/text()')
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
194 foobar
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
195
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
196 Note that the outermost element of the stream becomes the *context
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
197 node* for the XPath test. That means that the expression "doc" would
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
198 not match anything in the example above, because it only tests against
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
199 child elements of the outermost element:
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
200
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
201 >>> print stream.select('doc')
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
202 <BLANKLINE>
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
203
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
204 You can use the "." expression to match the context node itself
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
205 (although that usually makes little sense):
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
206
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
207 >>> print stream.select('.')
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
208 <doc><elem>foo</elem><elem>bar</elem></doc>
53f4088e1e3b Improve docs on `Stream.select()` for #135.
cmlenz
parents: 541
diff changeset
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
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
211 :param namespaces: mapping of namespace prefixes used in the path
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
212 :param variables: mapping of variable names to values
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
213 :return: the selected substream
498
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
214 :rtype: `Stream`
435
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
215 :raises PathSyntaxError: if the given path expression is invalid or not
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
216 supported
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
217 """
230
24757b771651 Renamed Markup to Genshi in repository.
cmlenz
parents: 224
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
222 """Generate strings corresponding to a specific serialization of the
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
223 stream.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
226 the serialized output incrementally, as opposed to returning a single
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
227 string.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
228
498
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
229 Any additional keyword arguments are passed to the serializer, and thus
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
230 depend on the `method` parameter value.
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
236 :return: an iterator over the serialization results (`Markup` or
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
237 `unicode` objects, depending on the serialization method)
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
238 :rtype: ``iterator``
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
239 :see: XMLSerializer, XHTMLSerializer, HTMLSerializer, TextSerializer
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
240 """
462
c107f6f4c558 Add lower-level serialization functions.
cmlenz
parents: 460
diff changeset
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
c107f6f4c558 Add lower-level serialization functions.
cmlenz
parents: 460
diff changeset
244 return get_serializer(method, **kwargs)(_ensure(self))
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
245
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
246 def __str__(self):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
247 return self.render()
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
248
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
249 def __unicode__(self):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
250 return self.render(encoding=None)
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
255
69
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
256 START = Stream.START
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
257 END = Stream.END
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
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
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
260 DOCTYPE = Stream.DOCTYPE
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
261 START_NS = Stream.START_NS
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
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
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
265 PI = Stream.PI
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
266 COMMENT = Stream.COMMENT
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
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
e9a3930f8823 A couple of minor performance improvements.
cmlenz
parents: 66
diff changeset
290
345
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
291 class Attrs(tuple):
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
310 added, replaced or removed.
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
313 either a string or a set/sequence of strings, identifying the name(s) of
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
314 the attribute(s) to remove:
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
315
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
318 >>> attrs - ('title', 'href')
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
319 Attrs()
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
320
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
321 The original instance is not modified, but the operator can of course be
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
322 used with an assignment:
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
337 If the attributes already contain an attribute with a given name, the value
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
344
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
348
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
349 :return: `True` if the list includes the attribute
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
355
345
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
356 def __getslice__(self, i, j):
593
aa5762c7b7f1 Minor, cosmetic tweaks.
cmlenz
parents: 576
diff changeset
357 """Return a slice of the attributes list.
aa5762c7b7f1 Minor, cosmetic tweaks.
cmlenz
parents: 576
diff changeset
358
aa5762c7b7f1 Minor, cosmetic tweaks.
cmlenz
parents: 576
diff changeset
359 >>> attrs = Attrs([('href', '#'), ('title', 'Foo')])
aa5762c7b7f1 Minor, cosmetic tweaks.
cmlenz
parents: 576
diff changeset
360 >>> attrs[1:]
aa5762c7b7f1 Minor, cosmetic tweaks.
cmlenz
parents: 576
diff changeset
361 Attrs([('title', 'Foo')])
aa5762c7b7f1 Minor, cosmetic tweaks.
cmlenz
parents: 576
diff changeset
362 """
345
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
363 return Attrs(tuple.__getslice__(self, i, j))
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
364
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
365 def __or__(self, attrs):
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
366 """Return a new instance that contains the attributes in `attrs` in
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
367 addition to any already existing attributes.
498
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
368
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
369 :return: a new instance with the merged attributes
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
370 :rtype: `Attrs`
345
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
371 """
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
372 repl = dict([(an, av) for an, av in attrs if an in self])
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
373 return Attrs([(sn, repl.get(sn, sv)) for sn, sv in self] +
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
374 [(an, av) for an, av in attrs if an not in self])
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
379 return 'Attrs([%s])' % ', '.join([repr(item) for item in self])
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
380
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
381 def __sub__(self, names):
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
382 """Return a new instance with all attributes with a name in `names` are
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
383 removed.
498
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
384
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
385 :param names: the names of the attributes to remove
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
386 :return: a new instance with the attribute removed
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
387 :rtype: `Attrs`
345
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
388 """
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
389 if isinstance(names, basestring):
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
390 names = (names,)
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 326
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
396
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
397 :param name: the name of the attribute
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
398 :param default: the value to return when the attribute does not exist
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
399 :return: the attribute value, or the `default` value if that attribute
7800a61eae43 More API doc enhancements.
cmlenz
parents: 434
diff changeset
400 does not exist
498
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
403 for attr, value in self:
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
404 if attr == name:
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
405 return value
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
406 return default
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
416
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
417 :return: a `TEXT` event
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
422
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
423 class Markup(unicode):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
424 """Marks a string as being safe for inclusion in HTML/XML output without
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
425 needing to be escaped.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
434
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
443
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
444 def __mul__(self, num):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
445 return Markup(unicode(self) * num)
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
01981cbc7575 Fix a number of escaping problems:
cmlenz
parents: 34
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
01981cbc7575 Fix a number of escaping problems:
cmlenz
parents: 34
diff changeset
468 return Markup(unicode(self).join([escape(item, quotes=escape_quotes)
34
ae293292cbb1 quotes should not be escaped inside text nodes
mgood
parents: 27
diff changeset
469 for item in seq]))
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
470
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
471 def escape(cls, text, quotes=True):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
472 """Create a Markup instance from a string and escape special characters
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
473 it may contain (<, >, & and \").
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
474
434
e065d7906b68 * Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents: 427
diff changeset
475 >>> 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
476 <Markup u'&#34;1 &lt; 2&#34;'>
e065d7906b68 * Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents: 427
diff changeset
477
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
478 If the `quotes` parameter is set to `False`, the \" character is left
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
479 as is. Escaping quotes is generally only required for strings that are
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
480 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
481
e065d7906b68 * Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents: 427
diff changeset
482 >>> 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
483 <Markup u'"1 &lt; 2"'>
e065d7906b68 * Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents: 427
diff changeset
484
e065d7906b68 * Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents: 427
diff changeset
485 :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
486 :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
487 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
488 :return: the escaped `Markup` string
498
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
489 :rtype: `Markup`
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
490 """
73
b0fd16111f2e Some more performance tweaks.
cmlenz
parents: 69
diff changeset
491 if not text:
b0fd16111f2e Some more performance tweaks.
cmlenz
parents: 69
diff changeset
492 return cls()
b0fd16111f2e Some more performance tweaks.
cmlenz
parents: 69
diff changeset
493 if type(text) is cls:
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
494 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
495 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
496 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
497
73
b0fd16111f2e Some more performance tweaks.
cmlenz
parents: 69
diff changeset
498 text = unicode(text).replace('&', '&amp;') \
b0fd16111f2e Some more performance tweaks.
cmlenz
parents: 69
diff changeset
499 .replace('<', '&lt;') \
b0fd16111f2e Some more performance tweaks.
cmlenz
parents: 69
diff changeset
500 .replace('>', '&gt;')
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
501 if quotes:
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
502 text = text.replace('"', '&#34;')
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
503 return cls(text)
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
504 escape = classmethod(escape)
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
505
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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 &lt; 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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
512 :return: the unescaped string
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
518 return unicode(self).replace('&#34;', '"') \
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
519 .replace('&gt;', '>') \
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
520 .replace('&lt;', '<') \
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
521 .replace('&amp;', '&')
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
522
116
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
523 def stripentities(self, keepxmlentities=False):
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
524 """Return a copy of the text with any character or numeric entities
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
525 replaced by the equivalent UTF-8 characters.
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
526
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
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 (``&amp;``, ``&apos;``, ``&gt;``, ``&lt;`` and
e065d7906b68 * Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents: 427
diff changeset
529 ``&quot;``) 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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
531 :return: a `Markup` instance with entities removed
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
5da45906dda7 Simplified implementation of `py:content` directive.
cmlenz
parents: 5
diff changeset
534 """
116
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
535 return Markup(stripentities(self, keepxmlentities=keepxmlentities))
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
536
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
540 :return: a `Markup` instance with all tags removed
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
88ac4c680120 Merged [135:138/branches/experimental/cspeedups].
cmlenz
parents: 115
diff changeset
544 return Markup(striptags(self))
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
545
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
546
541
4a53763b3948 Merged cspeedups branch into trunk.
cmlenz
parents: 498
diff changeset
547 try:
4a53763b3948 Merged cspeedups branch into trunk.
cmlenz
parents: 498
diff changeset
548 from genshi._speedups import Markup
4a53763b3948 Merged cspeedups branch into trunk.
cmlenz
parents: 498
diff changeset
549 except ImportError:
4a53763b3948 Merged cspeedups branch into trunk.
cmlenz
parents: 498
diff changeset
550 pass # just use the Python implementation
4a53763b3948 Merged cspeedups branch into trunk.
cmlenz
parents: 498
diff changeset
551
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
552 escape = Markup.escape
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
553
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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 &lt; 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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
560 If the provided `text` object is not a `Markup` instance, it is returned
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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 &lt; 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 &lt; 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
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
567 :return: the unescsaped string
5b42b341185a A couple of minor doc refinements.
cmlenz
parents: 462
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
570 if not isinstance(text, Markup):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
571 return text
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
572 return text.unescape()
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
573
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
574
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
3e8d0c061ac7 Fix #180 (py2.6 warning).
cmlenz
parents: 666
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
642
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
645 __getattr__ = __getitem__
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
646
793
7cf2407671c2 Get rid of a couple more -3 warnings.
cmlenz
parents: 792
diff changeset
647 def __hash__(self):
7cf2407671c2 Get rid of a couple more -3 warnings.
cmlenz
parents: 792
diff changeset
648 return hash(self.uri)
7cf2407671c2 Get rid of a couple more -3 warnings.
cmlenz
parents: 792
diff changeset
649
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
650 def __repr__(self):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
651 return '<Namespace "%s">' % self.uri
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
652
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
655
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
658
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
664 class QName(unicode):
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
665 """A qualified element or attribute name.
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
666
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
686 """
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
687 __slots__ = ['namespace', 'localname']
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
688
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
5e9987f34e6c Ported [111] to trunk.
cmlenz
parents: 96
diff changeset
696 if type(qname) is cls:
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
697 return qname
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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
5e9987f34e6c Ported [111] to trunk.
cmlenz
parents: 96
diff changeset
700 if len(parts) > 1:
136
636e0100fcaf Minor performance improvements in serialization.
cmlenz
parents: 133
diff changeset
701 self = unicode.__new__(cls, u'{%s' % qname)
636e0100fcaf Minor performance improvements in serialization.
cmlenz
parents: 133
diff changeset
702 self.namespace, self.localname = map(unicode, parts)
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
703 else:
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
704 self = unicode.__new__(cls, qname)
136
636e0100fcaf Minor performance improvements in serialization.
cmlenz
parents: 133
diff changeset
705 self.namespace, self.localname = None, unicode(qname)
1
821114ec4f69 Initial import.
cmlenz
parents:
diff changeset
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('{'))
Copyright (C) 2012-2017 Edgewall Software