Initial commit

This commit is contained in:
2020-05-08 14:39:22 +01:00
commit 57828567af
1662 changed files with 248701 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2006, 2010, 2012-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2012-2014 Google, Inc.
# Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
# Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014 Brett Cannon <brett@python.org>
# Copyright (c) 2014 Ricardo Gemignani <ricardo.gemignani@gmail.com>
# Copyright (c) 2014 Arun Persaud <arun@nubati.net>
# Copyright (c) 2015 Simu Toni <simutoni@gmail.com>
# Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
# Copyright (c) 2017 Kári Tristan Helgason <kthelgason@gmail.com>
# Copyright (c) 2018 ssolanki <sushobhitsolanki@gmail.com>
# Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
# Copyright (c) 2019 Pierre Sassoulas <pierre.sassoulas@gmail.com>
# Copyright (c) 2020 Anthony Sottile <asottile@umich.edu>
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
"""utilities methods and classes for reporters"""
from pylint import utils
from pylint.reporters.base_reporter import BaseReporter
from pylint.reporters.collecting_reporter import CollectingReporter
from pylint.reporters.json_reporter import JSONReporter
from pylint.reporters.reports_handler_mix_in import ReportsHandlerMixIn
def initialize(linter):
"""initialize linter with reporters in this package """
utils.register_plugins(linter, __path__[0])
__all__ = ["BaseReporter", "ReportsHandlerMixIn", "JSONReporter", "CollectingReporter"]

View File

@@ -0,0 +1,64 @@
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
import os
import sys
class BaseReporter:
"""base class for reporters
symbols: show short symbolic names for messages.
"""
extension = ""
def __init__(self, output=None):
self.linter = None
self.section = 0
self.out = None
self.out_encoding = None
self.set_output(output)
# Build the path prefix to strip to get relative paths
self.path_strip_prefix = os.getcwd() + os.sep
def handle_message(self, msg):
"""Handle a new message triggered on the current file."""
def set_output(self, output=None):
"""set output stream"""
self.out = output or sys.stdout
def writeln(self, string=""):
"""write a line in the output buffer"""
print(string, file=self.out)
def display_reports(self, layout):
"""display results encapsulated in the layout tree"""
self.section = 0
if hasattr(layout, "report_id"):
layout.children[0].children[0].data += " (%s)" % layout.report_id
self._display(layout)
def _display(self, layout):
"""display the layout"""
raise NotImplementedError()
def display_messages(self, layout):
"""Hook for displaying the messages of the reporter
This will be called whenever the underlying messages
needs to be displayed. For some reporters, it probably
doesn't make sense to display messages as soon as they
are available, so some mechanism of storing them could be used.
This method can be implemented to display them after they've
been aggregated.
"""
# Event callbacks
def on_set_current_module(self, module, filepath):
"""Hook called when a module starts to be analysed."""
def on_close(self, stats, previous_stats):
"""Hook called when a module finished analyzing."""

View File

@@ -0,0 +1,19 @@
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
from pylint.reporters.base_reporter import BaseReporter
class CollectingReporter(BaseReporter):
"""collects messages"""
name = "collector"
def __init__(self):
BaseReporter.__init__(self)
self.messages = []
def handle_message(self, msg):
self.messages.append(msg)
_display = None

View File

@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2014 Vlad Temian <vladtemian@gmail.com>
# Copyright (c) 2015-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
# Copyright (c) 2017 guillaume2 <guillaume.peillex@gmail.col>
# Copyright (c) 2019-2020 Pierre Sassoulas <pierre.sassoulas@gmail.com>
# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
# Copyright (c) 2020 Clément Pit-Claudel <cpitclaudel@users.noreply.github.com>
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
"""JSON reporter"""
import json
import sys
from pylint.interfaces import IReporter
from pylint.reporters.base_reporter import BaseReporter
class JSONReporter(BaseReporter):
"""Report messages and layouts in JSON."""
__implements__ = IReporter
name = "json"
extension = "json"
def __init__(self, output=None):
BaseReporter.__init__(self, output or sys.stdout)
self.messages = []
def handle_message(self, msg):
"""Manage message of different type and in the context of path."""
self.messages.append(
{
"type": msg.category,
"module": msg.module,
"obj": msg.obj,
"line": msg.line,
"column": msg.column,
"path": msg.path,
"symbol": msg.symbol,
"message": msg.msg or "",
"message-id": msg.msg_id,
}
)
def display_messages(self, layout):
"""Launch layouts display"""
print(json.dumps(self.messages, indent=4), file=self.out)
def display_reports(self, layout):
"""Don't do anything in this reporter."""
def _display(self, layout):
"""Do nothing."""
def register(linter):
"""Register the reporter classes with the linter."""
linter.register_reporter(JSONReporter)

View File

@@ -0,0 +1,77 @@
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
import collections
from pylint.exceptions import EmptyReportError
from pylint.reporters.ureports.nodes import Section
class ReportsHandlerMixIn:
"""a mix-in class containing all the reports and stats manipulation
related methods for the main lint class
"""
def __init__(self):
self._reports = collections.defaultdict(list)
self._reports_state = {}
def report_order(self):
""" Return a list of reports, sorted in the order
in which they must be called.
"""
return list(self._reports)
def register_report(self, reportid, r_title, r_cb, checker):
"""register a report
reportid is the unique identifier for the report
r_title the report's title
r_cb the method to call to make the report
checker is the checker defining the report
"""
reportid = reportid.upper()
self._reports[checker].append((reportid, r_title, r_cb))
def enable_report(self, reportid):
"""disable the report of the given id"""
reportid = reportid.upper()
self._reports_state[reportid] = True
def disable_report(self, reportid):
"""disable the report of the given id"""
reportid = reportid.upper()
self._reports_state[reportid] = False
def report_is_enabled(self, reportid):
"""return true if the report associated to the given identifier is
enabled
"""
return self._reports_state.get(reportid, True)
def make_reports(self, stats, old_stats):
"""render registered reports"""
sect = Section("Report", "%s statements analysed." % (self.stats["statement"]))
for checker in self.report_order():
for reportid, r_title, r_cb in self._reports[checker]:
if not self.report_is_enabled(reportid):
continue
report_sect = Section(r_title)
try:
r_cb(report_sect, stats, old_stats)
except EmptyReportError:
continue
report_sect.report_id = reportid
sect.append(report_sect)
return sect
def add_stats(self, **kwargs):
"""add some stats entries to the statistic dictionary
raise an AssertionError if there is a key conflict
"""
for key, value in kwargs.items():
if key[-1] == "_":
key = key[:-1]
assert key not in self.stats
self.stats[key] = value
return self.stats

View File

@@ -0,0 +1,249 @@
# Copyright (c) 2006-2007, 2010-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2012-2014 Google, Inc.
# Copyright (c) 2014 Brett Cannon <brett@python.org>
# Copyright (c) 2014 Arun Persaud <arun@nubati.net>
# Copyright (c) 2015-2018 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
# Copyright (c) 2015 Ionel Cristian Maries <contact@ionelmc.ro>
# Copyright (c) 2016 y2kbugger <y2kbugger@users.noreply.github.com>
# Copyright (c) 2018-2019 Nick Drozd <nicholasdrozd@gmail.com>
# Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
# Copyright (c) 2018 Jace Browning <jacebrowning@gmail.com>
# Copyright (c) 2019-2020 Pierre Sassoulas <pierre.sassoulas@gmail.com>
# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
"""Plain text reporters:
:text: the default one grouping messages by module
:colorized: an ANSI colorized text reporter
"""
import os
import sys
import warnings
from pylint import utils
from pylint.interfaces import IReporter
from pylint.reporters import BaseReporter
from pylint.reporters.ureports.text_writer import TextWriter
TITLE_UNDERLINES = ["", "=", "-", "."]
ANSI_PREFIX = "\033["
ANSI_END = "m"
ANSI_RESET = "\033[0m"
ANSI_STYLES = {
"reset": "0",
"bold": "1",
"italic": "3",
"underline": "4",
"blink": "5",
"inverse": "7",
"strike": "9",
}
ANSI_COLORS = {
"reset": "0",
"black": "30",
"red": "31",
"green": "32",
"yellow": "33",
"blue": "34",
"magenta": "35",
"cyan": "36",
"white": "37",
}
def _get_ansi_code(color=None, style=None):
"""return ansi escape code corresponding to color and style
:type color: str or None
:param color:
the color name (see `ANSI_COLORS` for available values)
or the color number when 256 colors are available
:type style: str or None
:param style:
style string (see `ANSI_COLORS` for available values). To get
several style effects at the same time, use a coma as separator.
:raise KeyError: if an unexistent color or style identifier is given
:rtype: str
:return: the built escape code
"""
ansi_code = []
if style:
style_attrs = utils._splitstrip(style)
for effect in style_attrs:
ansi_code.append(ANSI_STYLES[effect])
if color:
if color.isdigit():
ansi_code.extend(["38", "5"])
ansi_code.append(color)
else:
ansi_code.append(ANSI_COLORS[color])
if ansi_code:
return ANSI_PREFIX + ";".join(ansi_code) + ANSI_END
return ""
def colorize_ansi(msg, color=None, style=None):
"""colorize message by wrapping it with ansi escape codes
:type msg: str or unicode
:param msg: the message string to colorize
:type color: str or None
:param color:
the color identifier (see `ANSI_COLORS` for available values)
:type style: str or None
:param style:
style string (see `ANSI_COLORS` for available values). To get
several style effects at the same time, use a coma as separator.
:raise KeyError: if an unexistent color or style identifier is given
:rtype: str or unicode
:return: the ansi escaped string
"""
# If both color and style are not defined, then leave the text as is
if color is None and style is None:
return msg
escape_code = _get_ansi_code(color, style)
# If invalid (or unknown) color, don't wrap msg with ansi codes
if escape_code:
return "%s%s%s" % (escape_code, msg, ANSI_RESET)
return msg
class TextReporter(BaseReporter):
"""Reports messages and layouts in plain text"""
__implements__ = IReporter
name = "text"
extension = "txt"
line_format = "{path}:{line}:{column}: {msg_id}: {msg} ({symbol})"
def __init__(self, output=None):
BaseReporter.__init__(self, output)
self._modules = set()
self._template = None
def on_set_current_module(self, module, filepath):
self._template = str(self.linter.config.msg_template or self.line_format)
def write_message(self, msg):
"""Convenience method to write a formatted message with class default template"""
self.writeln(msg.format(self._template))
def handle_message(self, msg):
"""manage message of different type and in the context of path"""
if msg.module not in self._modules:
if msg.module:
self.writeln("************* Module %s" % msg.module)
self._modules.add(msg.module)
else:
self.writeln("************* ")
self.write_message(msg)
def _display(self, layout):
"""launch layouts display"""
print(file=self.out)
TextWriter().format(layout, self.out)
class ParseableTextReporter(TextReporter):
"""a reporter very similar to TextReporter, but display messages in a form
recognized by most text editors :
<filename>:<linenum>:<msg>
"""
name = "parseable"
line_format = "{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}"
def __init__(self, output=None):
warnings.warn(
"%s output format is deprecated. This is equivalent "
"to --msg-template=%s" % (self.name, self.line_format),
DeprecationWarning,
)
TextReporter.__init__(self, output)
class VSTextReporter(ParseableTextReporter):
"""Visual studio text reporter"""
name = "msvs"
line_format = "{path}({line}): [{msg_id}({symbol}){obj}] {msg}"
class ColorizedTextReporter(TextReporter):
"""Simple TextReporter that colorizes text output"""
name = "colorized"
COLOR_MAPPING = {
"I": ("green", None),
"C": (None, "bold"),
"R": ("magenta", "bold, italic"),
"W": ("magenta", None),
"E": ("red", "bold"),
"F": ("red", "bold, underline"),
"S": ("yellow", "inverse"), # S stands for module Separator
}
def __init__(self, output=None, color_mapping=None):
TextReporter.__init__(self, output)
self.color_mapping = color_mapping or dict(ColorizedTextReporter.COLOR_MAPPING)
ansi_terms = ["xterm-16color", "xterm-256color"]
if os.environ.get("TERM") not in ansi_terms:
if sys.platform == "win32":
# pylint: disable=import-error,import-outside-toplevel
import colorama
self.out = colorama.AnsiToWin32(self.out)
def _get_decoration(self, msg_id):
"""Returns the tuple color, style associated with msg_id as defined
in self.color_mapping
"""
try:
return self.color_mapping[msg_id[0]]
except KeyError:
return None, None
def handle_message(self, msg):
"""manage message of different types, and colorize output
using ansi escape codes
"""
if msg.module not in self._modules:
color, style = self._get_decoration("S")
if msg.module:
modsep = colorize_ansi(
"************* Module %s" % msg.module, color, style
)
else:
modsep = colorize_ansi("************* %s" % msg.module, color, style)
self.writeln(modsep)
self._modules.add(msg.module)
color, style = self._get_decoration(msg.C)
msg = msg._replace(
**{
attr: colorize_ansi(getattr(msg, attr), color, style)
for attr in ("msg", "symbol", "category", "C")
}
)
self.write_message(msg)
def register(linter):
"""Register the reporter classes with the linter."""
linter.register_reporter(TextReporter)
linter.register_reporter(ParseableTextReporter)
linter.register_reporter(VSTextReporter)
linter.register_reporter(ColorizedTextReporter)

View File

@@ -0,0 +1,97 @@
# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2018 ssolanki <sushobhitsolanki@gmail.com>
# Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
# Copyright (c) 2019 Pierre Sassoulas <pierre.sassoulas@gmail.com>
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
"""Universal report objects and some formatting drivers.
A way to create simple reports using python objects, primarily designed to be
formatted as text and html.
"""
import os
import sys
from io import StringIO
class BaseWriter:
"""base class for ureport writers"""
def format(self, layout, stream=None, encoding=None):
"""format and write the given layout into the stream object
unicode policy: unicode strings may be found in the layout;
try to call stream.write with it, but give it back encoded using
the given encoding if it fails
"""
if stream is None:
stream = sys.stdout
if not encoding:
encoding = getattr(stream, "encoding", "UTF-8")
self.encoding = encoding or "UTF-8"
self.out = stream
self.begin_format()
layout.accept(self)
self.end_format()
def format_children(self, layout):
"""recurse on the layout children and call their accept method
(see the Visitor pattern)
"""
for child in getattr(layout, "children", ()):
child.accept(self)
def writeln(self, string=""):
"""write a line in the output buffer"""
self.write(string + os.linesep)
def write(self, string):
"""write a string in the output buffer"""
self.out.write(string)
def begin_format(self):
"""begin to format a layout"""
self.section = 0
def end_format(self):
"""finished to format a layout"""
def get_table_content(self, table):
"""trick to get table content without actually writing it
return an aligned list of lists containing table cells values as string
"""
result = [[]]
cols = table.cols
for cell in self.compute_content(table):
if cols == 0:
result.append([])
cols = table.cols
cols -= 1
result[-1].append(cell)
# fill missing cells
while len(result[-1]) < cols:
result[-1].append("")
return result
def compute_content(self, layout):
"""trick to compute the formatting of children layout before actually
writing it
return an iterator on strings (one for each child element)
"""
# Patch the underlying output stream with a fresh-generated stream,
# which is used to store a temporary representation of a child
# node.
out = self.out
try:
for child in layout.children:
stream = StringIO()
self.out = stream
child.accept(self)
yield stream.getvalue()
finally:
self.out = out

View File

@@ -0,0 +1,189 @@
# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2018 ssolanki <sushobhitsolanki@gmail.com>
# Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com>
# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
# Copyright (c) 2020 Anthony Sottile <asottile@umich.edu>
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
"""Micro reports objects.
A micro report is a tree of layout and content objects.
"""
class VNode:
def __init__(self, nid=None):
self.id = nid
# navigation
self.parent = None
self.children = []
def __iter__(self):
return iter(self.children)
def append(self, child):
"""add a node to children"""
self.children.append(child)
child.parent = self
def insert(self, index, child):
"""insert a child node"""
self.children.insert(index, child)
child.parent = self
def _get_visit_name(self):
"""
return the visit name for the mixed class. When calling 'accept', the
method <'visit_' + name returned by this method> will be called on the
visitor
"""
try:
# pylint: disable=no-member
return self.TYPE.replace("-", "_")
# pylint: disable=broad-except
except Exception:
return self.__class__.__name__.lower()
def accept(self, visitor, *args, **kwargs):
func = getattr(visitor, "visit_%s" % self._get_visit_name())
return func(self, *args, **kwargs)
def leave(self, visitor, *args, **kwargs):
func = getattr(visitor, "leave_%s" % self._get_visit_name())
return func(self, *args, **kwargs)
class BaseLayout(VNode):
"""base container node
attributes
* children : components in this table (i.e. the table's cells)
"""
def __init__(self, children=(), **kwargs):
super().__init__(**kwargs)
for child in children:
if isinstance(child, VNode):
self.append(child)
else:
self.add_text(child)
def append(self, child):
"""overridden to detect problems easily"""
assert child not in self.parents()
VNode.append(self, child)
def parents(self):
"""return the ancestor nodes"""
assert self.parent is not self
if self.parent is None:
return []
return [self.parent] + self.parent.parents()
def add_text(self, text):
"""shortcut to add text data"""
self.children.append(Text(text))
# non container nodes #########################################################
class Text(VNode):
"""a text portion
attributes :
* data : the text value as an encoded or unicode string
"""
def __init__(self, data, escaped=True, **kwargs):
super().__init__(**kwargs)
# if isinstance(data, unicode):
# data = data.encode('ascii')
assert isinstance(data, str), data.__class__
self.escaped = escaped
self.data = data
class VerbatimText(Text):
"""a verbatim text, display the raw data
attributes :
* data : the text value as an encoded or unicode string
"""
# container nodes #############################################################
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=None, description=None, **kwargs):
super().__init__(**kwargs)
if description:
self.insert(0, Paragraph([Text(description)]))
if title:
self.insert(0, Title(children=(title,)))
class EvaluationSection(Section):
def __init__(self, message, **kwargs):
super().__init__(**kwargs)
title = Paragraph()
title.append(Text("-" * len(message)))
self.append(title)
message_body = Paragraph()
message_body.append(Text(message))
self.append(message_body)
class Title(BaseLayout):
"""a title
attributes :
* BaseLayout attributes
A title must not contains a section nor a paragraph!
"""
class Paragraph(BaseLayout):
"""a simple text paragraph
attributes :
* BaseLayout attributes
A paragraph must not contains a section !
"""
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, title=None, rheaders=0, cheaders=0, **kwargs):
super().__init__(**kwargs)
assert isinstance(cols, int)
self.cols = cols
self.title = title
self.rheaders = rheaders
self.cheaders = cheaders

View File

@@ -0,0 +1,96 @@
# Copyright (c) 2015-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2018, 2020 Anthony Sottile <asottile@umich.edu>
# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
# Copyright (c) 2019 Pierre Sassoulas <pierre.sassoulas@gmail.com>
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
"""Text formatting drivers for ureports"""
from pylint.reporters.ureports import BaseWriter
TITLE_UNDERLINES = ["", "=", "-", "`", ".", "~", "^"]
BULLETS = ["*", "-"]
class TextWriter(BaseWriter):
"""format layouts as text
(ReStructured inspiration but not totally handled yet)
"""
def begin_format(self):
super().begin_format()
self.list_level = 0
def visit_section(self, layout):
"""display a section as text
"""
self.section += 1
self.writeln()
self.format_children(layout)
self.section -= 1
self.writeln()
def visit_evaluationsection(self, layout):
"""Display an evaluation section as a text."""
self.section += 1
self.format_children(layout)
self.section -= 1
self.writeln()
def visit_title(self, layout):
title = "".join(list(self.compute_content(layout)))
self.writeln(title)
try:
self.writeln(TITLE_UNDERLINES[self.section] * len(title))
except IndexError:
print("FIXME TITLE TOO DEEP. TURNING TITLE INTO TEXT")
def visit_paragraph(self, layout):
"""enter a paragraph"""
self.format_children(layout)
self.writeln()
def visit_table(self, layout):
"""display a table as text"""
table_content = self.get_table_content(layout)
# get columns width
cols_width = [0] * len(table_content[0])
for row in table_content:
for index, col in enumerate(row):
cols_width[index] = max(cols_width[index], len(col))
self.default_table(layout, table_content, cols_width)
self.writeln()
def default_table(self, layout, table_content, cols_width):
"""format a table"""
cols_width = [size + 1 for size in cols_width]
format_strings = " ".join(["%%-%ss"] * len(cols_width))
format_strings = format_strings % tuple(cols_width)
format_strings = format_strings.split(" ")
table_linesep = "\n+" + "+".join(["-" * w for w in cols_width]) + "+\n"
headsep = "\n+" + "+".join(["=" * w for w in cols_width]) + "+\n"
self.write(table_linesep)
for index, line in enumerate(table_content):
self.write("|")
for line_index, at_index in enumerate(line):
self.write(format_strings[line_index] % at_index)
self.write("|")
if index == 0 and layout.rheaders:
self.write(headsep)
else:
self.write(table_linesep)
def visit_verbatimtext(self, layout):
"""display a verbatim layout as text (so difficult ;)
"""
self.writeln("::\n")
for line in layout.data.splitlines():
self.writeln(" " + line)
self.writeln()
def visit_text(self, layout):
"""add some text"""
self.write("%s" % layout.data)