Source code for logilab.common.ureports.nodes

# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of logilab-common.
#
# logilab-common is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 2.1 of the License,
# or (at your option) any later version.
#
# logilab-common is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
"""Micro reports objects.

A micro report is a tree of layout and content objects.
"""
__docformat__ = "restructuredtext en"

from logilab.common.tree import VNode
from typing import Optional

# from logilab.common.ureports.nodes import List
# from logilab.common.ureports.nodes import Paragraph
# from logilab.common.ureports.nodes import Text
from typing import Any
from typing import List as TypingList
from typing import Tuple
from typing import Union


[docs]class BaseComponent(VNode): """base report component attributes * id : the component's optional id * klass : the component's optional klass """ def __init__(self, id: Optional[str] = None, klass: Optional[str] = None) -> None: VNode.__init__(self, id) self.klass = klass
[docs]class BaseLayout(BaseComponent): """base container node attributes * BaseComponent attributes * children : components in this table (i.e. the table's cells) """ def __init__( self, children: Union[ TypingList["Text"], Tuple[Union["Paragraph", str], Union[TypingList, str]], Tuple[str, ...], ] = (), **kwargs: Any, ) -> None: super(BaseLayout, self).__init__(**kwargs) for child in children: if isinstance(child, BaseComponent): self.append(child) else: # mypy: Argument 1 to "add_text" of "BaseLayout" has incompatible type # mypy: "Union[str, List[Any]]"; expected "str" # we check this situation in the if self.add_text(child) # type: ignore
[docs] def append(self, child: Any) -> None: """overridden to detect problems easily""" assert child not in self.parents() VNode.append(self, child)
[docs] def parents(self) -> TypingList: """return the ancestor nodes""" assert self.parent is not self if self.parent is None: return [] return [self.parent] + self.parent.parents()
[docs] def add_text(self, text: str) -> None: """shortcut to add text data""" self.children.append(Text(text))
# non container nodes #########################################################
[docs]class Text(BaseComponent): """a text portion attributes : * BaseComponent attributes * data : the text value as an encoded or unicode string """ def __init__(self, data: str, escaped: bool = True, **kwargs: Any) -> None: super(Text, self).__init__(**kwargs) # if isinstance(data, unicode): # data = data.encode('ascii') assert isinstance(data, str), data.__class__ self.escaped = escaped self.data = data
[docs]class VerbatimText(Text): """a verbatim text, display the raw data attributes : * BaseComponent attributes * data : the text value as an encoded or unicode string """
[docs]class Image(BaseComponent): """an embedded or a single image attributes : * BaseComponent attributes * filename : the image's filename (REQUIRED) * stream : the stream object containing the image data (REQUIRED) * title : the image's optional title """ def __init__(self, filename, stream, title=None, **kwargs): super(Image, self).__init__(**kwargs) assert filename assert stream self.filename = filename self.stream = stream self.title = title
# container nodes #############################################################
[docs]class Section(BaseLayout): """a section attributes : * BaseLayout attributes a title may also be given to the constructor, it'll be added as a first element a description may also be given to the constructor, it'll be added as a first paragraph """ def __init__(self, title: str = None, description: str = None, **kwargs: Any) -> None: super(Section, self).__init__(**kwargs) if description: self.insert(0, Paragraph([Text(description)])) if title: self.insert(0, Title(children=(title,)))
[docs]class Title(BaseLayout): """a title attributes : * BaseLayout attributes A title must not contains a section nor a paragraph! """
[docs]class Span(BaseLayout): """a title attributes : * BaseLayout attributes A span should only contains Text and Link nodes (in-line elements) """
[docs]class Paragraph(BaseLayout): """a simple text paragraph attributes : * BaseLayout attributes A paragraph must not contains a section ! """
[docs]class Table(BaseLayout): """some tabular data attributes : * BaseLayout attributes * cols : the number of columns of the table (REQUIRED) * rheaders : the first row's elements are table's header * cheaders : the first col's elements are table's header * title : the table's optional title """ def __init__( self, cols: int, title: Optional[Any] = None, rheaders: int = 0, cheaders: int = 0, rrheaders: int = 0, rcheaders: int = 0, **kwargs: Any, ) -> None: super(Table, self).__init__(**kwargs) assert isinstance(cols, int) self.cols = cols self.title = title self.rheaders = rheaders self.cheaders = cheaders self.rrheaders = rrheaders self.rcheaders = rcheaders
[docs]class List(BaseLayout): """some list data attributes : * BaseLayout attributes """