Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

nodes.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # Copyright (c) 2015-2016 Claudiu Popa <pcmanticore@gmail.com>
  2. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  3. # For details: https://github.com/PyCQA/pylint/blob/master/COPYING
  4. """Micro reports objects.
  5. A micro report is a tree of layout and content objects.
  6. """
  7. from six import string_types
  8. class VNode(object):
  9. def __init__(self, nid=None):
  10. self.id = nid
  11. # navigation
  12. self.parent = None
  13. self.children = []
  14. def __iter__(self):
  15. return iter(self.children)
  16. def append(self, child):
  17. """add a node to children"""
  18. self.children.append(child)
  19. child.parent = self
  20. def insert(self, index, child):
  21. """insert a child node"""
  22. self.children.insert(index, child)
  23. child.parent = self
  24. def _get_visit_name(self):
  25. """
  26. return the visit name for the mixed class. When calling 'accept', the
  27. method <'visit_' + name returned by this method> will be called on the
  28. visitor
  29. """
  30. try:
  31. return self.TYPE.replace('-', '_')
  32. except Exception:
  33. return self.__class__.__name__.lower()
  34. def accept(self, visitor, *args, **kwargs):
  35. func = getattr(visitor, 'visit_%s' % self._get_visit_name())
  36. return func(self, *args, **kwargs)
  37. def leave(self, visitor, *args, **kwargs):
  38. func = getattr(visitor, 'leave_%s' % self._get_visit_name())
  39. return func(self, *args, **kwargs)
  40. class BaseLayout(VNode):
  41. """base container node
  42. attributes
  43. * children : components in this table (i.e. the table's cells)
  44. """
  45. def __init__(self, children=(), **kwargs):
  46. super(BaseLayout, self).__init__(**kwargs)
  47. for child in children:
  48. if isinstance(child, VNode):
  49. self.append(child)
  50. else:
  51. self.add_text(child)
  52. def append(self, child):
  53. """overridden to detect problems easily"""
  54. assert child not in self.parents()
  55. VNode.append(self, child)
  56. def parents(self):
  57. """return the ancestor nodes"""
  58. assert self.parent is not self
  59. if self.parent is None:
  60. return []
  61. return [self.parent] + self.parent.parents()
  62. def add_text(self, text):
  63. """shortcut to add text data"""
  64. self.children.append(Text(text))
  65. # non container nodes #########################################################
  66. class Text(VNode):
  67. """a text portion
  68. attributes :
  69. * data : the text value as an encoded or unicode string
  70. """
  71. def __init__(self, data, escaped=True, **kwargs):
  72. super(Text, self).__init__(**kwargs)
  73. #if isinstance(data, unicode):
  74. # data = data.encode('ascii')
  75. assert isinstance(data, string_types), data.__class__
  76. self.escaped = escaped
  77. self.data = data
  78. class VerbatimText(Text):
  79. """a verbatim text, display the raw data
  80. attributes :
  81. * data : the text value as an encoded or unicode string
  82. """
  83. # container nodes #############################################################
  84. class Section(BaseLayout):
  85. """a section
  86. attributes :
  87. * BaseLayout attributes
  88. a title may also be given to the constructor, it'll be added
  89. as a first element
  90. a description may also be given to the constructor, it'll be added
  91. as a first paragraph
  92. """
  93. def __init__(self, title=None, description=None, **kwargs):
  94. super(Section, self).__init__(**kwargs)
  95. if description:
  96. self.insert(0, Paragraph([Text(description)]))
  97. if title:
  98. self.insert(0, Title(children=(title,)))
  99. class EvaluationSection(Section):
  100. def __init__(self, message, **kwargs):
  101. super(EvaluationSection, self).__init__(**kwargs)
  102. title = Paragraph()
  103. title.append(Text("-" * len(message)))
  104. self.append(title)
  105. message_body = Paragraph()
  106. message_body.append(Text(message))
  107. self.append(message_body)
  108. class Title(BaseLayout):
  109. """a title
  110. attributes :
  111. * BaseLayout attributes
  112. A title must not contains a section nor a paragraph!
  113. """
  114. class Paragraph(BaseLayout):
  115. """a simple text paragraph
  116. attributes :
  117. * BaseLayout attributes
  118. A paragraph must not contains a section !
  119. """
  120. class Table(BaseLayout):
  121. """some tabular data
  122. attributes :
  123. * BaseLayout attributes
  124. * cols : the number of columns of the table (REQUIRED)
  125. * rheaders : the first row's elements are table's header
  126. * cheaders : the first col's elements are table's header
  127. * title : the table's optional title
  128. """
  129. def __init__(self, cols, title=None,
  130. rheaders=0, cheaders=0,
  131. **kwargs):
  132. super(Table, self).__init__(**kwargs)
  133. assert isinstance(cols, int)
  134. self.cols = cols
  135. self.title = title
  136. self.rheaders = rheaders
  137. self.cheaders = cheaders