# HG changeset patch # User cmlenz # Date 1174597923 0 # Node ID bc430fd7c54da09df7293d7c8087847bc16f0e7a # Parent 4069157548708a9da33c704a3aece8b5729daa64 More API docs. diff --git a/genshi/builder.py b/genshi/builder.py --- a/genshi/builder.py +++ b/genshi/builder.py @@ -70,7 +70,7 @@ from genshi.core import Attrs, Namespace, QName, Stream, START, END, TEXT -__all__ = ['Fragment', 'Element', 'tag'] +__all__ = ['Fragment', 'Element', 'ElementFactory', 'tag'] __docformat__ = 'restructuredtext en' @@ -81,12 +81,17 @@ __slots__ = ['children'] def __init__(self): + """Create a new fragment.""" self.children = [] def __add__(self, other): return Fragment()(self, other) def __call__(self, *args): + """Append any positional arguments as child nodes. + + :see: `append` + """ map(self.append, args) return self @@ -103,7 +108,11 @@ return unicode(self.generate()) def append(self, node): - """Append an element or string as child node.""" + """Append an element or string as child node. + + :param node: the node to append; can be an `Element`, `Fragment`, or a + `Stream`, or a Python string or number + """ if isinstance(node, (Stream, Element, basestring, int, float, long)): # For objects of a known/primitive type, we avoid the check for # whether it is iterable for better performance @@ -231,6 +240,11 @@ self.attrib = Attrs(_kwargs_to_attrs(attrib)) def __call__(self, *args, **kwargs): + """Append any positional arguments as child nodes, and keyword arguments + as attributes. + + :see: `Fragment.append` + """ self.attrib |= Attrs(_kwargs_to_attrs(kwargs)) Fragment.__call__(self, *args) return self @@ -295,15 +309,30 @@ self.namespace = namespace def __call__(self, *args): + """Create a fragment that has the given positional arguments as child + nodes. + + :return: the created `Fragment` + """ return Fragment()(*args) def __getitem__(self, namespace): - """Return a new factory that is bound to the specified namespace.""" + """Return a new factory that is bound to the specified namespace. + + :param namespace: the namespace URI or `Namespace` object + :return: an `ElementFactory` that produces elements bound to the given + namespace + """ return ElementFactory(namespace) def __getattr__(self, name): - """Create an `Element` with the given name.""" + """Create an `Element` with the given name. + + :param name: the tag name of the element to create + :return: an `Element` with the specified name + """ return Element(self.namespace and self.namespace[name] or name) tag = ElementFactory() +"""Global `ElementFactory` bound to the default namespace.""" diff --git a/genshi/input.py b/genshi/input.py --- a/genshi/input.py +++ b/genshi/input.py @@ -34,7 +34,11 @@ __docformat__ = 'restructuredtext en' def ET(element): - """Convert a given ElementTree element to a markup stream.""" + """Convert a given ElementTree element to a markup stream. + + :param element: an ElementTree element + :return: a markup stream + """ tag_name = QName(element.tag.lstrip('{')) attrs = Attrs([(QName(attr), value) for attr, value in element.items()]) @@ -51,9 +55,17 @@ class ParseError(Exception): """Exception raised when fatal syntax errors are found in the input being - parsed.""" + parsed. + """ def __init__(self, message, filename=None, lineno=-1, offset=-1): + """Exception initializer. + + :param message: the error message from the parser + :param filename: the path to the file that was parsed + :param lineno: the number of the line on which the error was encountered + :param offset: the column number where the error was encountered + """ self.msg = message if filename: message += ', in ' + os.path.basename(filename) @@ -128,6 +140,11 @@ self._queue = [] def parse(self): + """Generator that parses the XML source, yielding markup events. + + :return: a markup event stream + :raises ParseError: if the XML text is not well formed + """ def _generate(): try: bufsize = 4 * 1024 # 4K @@ -237,6 +254,23 @@ def XML(text): + """Parse the given XML source and return a markup stream. + + Unlike with `XMLParser`, the returned stream is reusable, meaning it can be + iterated over multiple times: + + >>> xml = XML('FooBar') + >>> print xml + FooBar + >>> print xml.select('elem') + FooBar + >>> print xml.select('elem/text()') + FooBar + + :param text: the XML source + :return: the parsed XML event stream + :raises ParseError: if the XML text is not well-formed + """ return Stream(list(XMLParser(StringIO(text)))) @@ -277,6 +311,11 @@ self._open_tags = [] def parse(self): + """Generator that parses the HTML source, yielding markup events. + + :return: a markup event stream + :raises ParseError: if the HTML text is not well formed + """ def _generate(): try: bufsize = 4 * 1024 # 4K @@ -368,6 +407,24 @@ def HTML(text, encoding='utf-8'): + """Parse the given HTML source and return a markup stream. + + Unlike with `HTMLParser`, the returned stream is reusable, meaning it can be + iterated over multiple times: + + >>> html = HTML('

Foo

') + >>> print html +

Foo

+ >>> print html.select('h1') +

Foo

+ >>> print html.select('h1/text()') + Foo + + :param text: the HTML source + :return: the parsed XML event stream + :raises ParseError: if the HTML text is not well-formed, and error recovery + fails + """ return Stream(list(HTMLParser(StringIO(text), encoding=encoding))) def _coalesce(stream): diff --git a/genshi/util.py b/genshi/util.py --- a/genshi/util.py +++ b/genshi/util.py @@ -139,7 +139,9 @@ def flatten(items): - """Flattens a potentially nested sequence into a flat list: + """Flattens a potentially nested sequence into a flat list. + + :param items: the sequence to flatten >>> flatten((1, 2)) [1, 2] @@ -159,6 +161,21 @@ def plaintext(text, keeplinebreaks=True): """Returns the text as a `unicode` string with all entities and tags removed. + + >>> plaintext('1 < 2') + u'1 < 2' + + The `keeplinebreaks` parameter can be set to ``False`` to replace any line + breaks by simple spaces: + + >>> plaintext('''1 + ... < + ... 2''', keeplinebreaks=False) + u'1 < 2' + + :param text: the text to convert to plain text + :param keeplinebreaks: whether line breaks in the text should be kept intact + :return: the text with tags and entities removed """ text = stripentities(striptags(text)) if not keeplinebreaks: @@ -208,7 +225,7 @@ _STRIPTAGS_RE = re.compile(r'<[^>]*?>') def striptags(text): - """Return a copy of the text with all XML/HTML tags removed. + """Return a copy of the text with any XML/HTML tags removed. >>> striptags('Foo bar') 'Foo bar' @@ -216,5 +233,8 @@ 'Foo' >>> striptags('Foo
') 'Foo' + + :param text: the string to remove tags from + :return: the text with tags removed """ return _STRIPTAGS_RE.sub('', text)