Source code for gemseo.third_party.prettytable.factory

# -*- coding: utf-8 -*-
# Copyright (c) 2009-2014, Luke Maurits <luke@maurits.id.au>
# All rights reserved.
# With contributions from:
# * Chris Clark
#  * Klein Stephane
#  * John Filleau
# PTable is forked from original Google Code page in April, 2015, and now
# maintained by Kane Blueriver <kxxoling@gmail.com>.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
#   this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
# * The name of the author may not be used to endorse or promote products
#   derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Taken from :
# https://github.com/kxxoling/PTable
# https://pypi.python.org/pypi/PTable
"""
Pretty table factory
********************
"""
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

from builtins import int, map, next, range
import csv

from future import standard_library

from ._compact import HTMLParser
from .prettytable import PrettyTable


standard_library.install_aliases()


[docs]def from_csv(filepath, field_names=None, **kwargs): """Loads table from CSV file :param filepath: param field_names: (Default value = None) :param field_names: (Default value = None) """ fmtparams = {} for param in ["delimiter", "doublequote", "escapechar", "lineterminator", "quotechar", "quoting", "skipinitialspace", "strict"]: if param in kwargs: fmtparams[param] = kwargs.pop(param) if fmtparams: reader = csv.reader(filepath, **fmtparams) else: dialect = csv.Sniffer().sniff(filepath.read(1024)) filepath.seek(0) reader = csv.reader(filepath, dialect) table = PrettyTable(**kwargs) if field_names: table.field_names = field_names next(reader) else: table.field_names = [x.strip() for x in next(reader)] for row in reader: table.add_row([x.strip() for x in row if len(x.strip()) > 0]) return table
[docs]def from_db_cursor(cursor, **kwargs): """ :param cursor: :param kwargs: """ if cursor.description: table = PrettyTable(**kwargs) table.field_names = [col[0] for col in cursor.description] for row in cursor.fetchall(): table.add_row(row) return table return None
[docs]class TableHandler(HTMLParser): """TableHandler""" def __init__(self, **kwargs): HTMLParser.__init__(self) self.kwargs = kwargs self.tables = [] self.last_row = [] self.rows = [] self.max_row_width = 0 self.active = None self.last_content = "" self.is_last_row_header = False self.colspan = 0
[docs] def handle_starttag(self, tag, attrs): """ :param tag: param attrs: :param attrs: """ self.active = tag if tag == "th": self.is_last_row_header = True for (key, value) in attrs: if key == "colspan": self.colspan = int(value)
[docs] def handle_endtag(self, tag): """ :param tag: """ if tag in ["th", "td"]: stripped_content = self.last_content.strip() self.last_row.append(stripped_content) if self.colspan: for _ in range(1, self.colspan): self.last_row.append("") self.colspan = 0 if tag == "tr": self.rows.append( (self.last_row, self.is_last_row_header)) self.max_row_width = max(self.max_row_width, len(self.last_row)) self.last_row = [] self.is_last_row_header = False if tag == "table": table = self.generate_table(self.rows) self.tables.append(table) self.rows = [] self.last_content = " " self.active = None
[docs] def handle_data(self, data): """ :param data: """ self.last_content += data
[docs] def generate_table(self, rows): """Generates from a list of rows a PrettyTable object. :param rows: """ table = PrettyTable(**self.kwargs) for row in self.rows: if len(row[0]) < self.max_row_width: appends = self.max_row_width - len(row[0]) for _ in range(1, appends): row[0].append("-") if row[1] is True: self.make_fields_unique(row[0]) table.field_names = row[0] else: table.add_row(row[0]) return table
[docs] def make_fields_unique(self, fields): """iterates over the row and make each field unique :param fields: fields """ for i in range(0, len(fields)): for j in range(i + 1, len(fields)): if fields[i] == fields[j]: fields[j] += "'"
[docs]def from_html(html_code, **kwargs): """Generates a list of PrettyTables from a string of HTML code. Each <table> in the HTML becomes one PrettyTable object. :param html_code: HTML code :type html_code: str :param kwargs: additional arguments """ parser = TableHandler(**kwargs) parser.feed(html_code) return parser.tables
[docs]def from_html_one(html_code, **kwargs): """Generates a PrettyTables from a string of HTML code which contains only a single <table> :param html_code: HTML code :type html_code: str :param kwargs: additional arguments """ tables = from_html(html_code, **kwargs) try: assert len(tables) == 1 except AssertionError: raise Exception("More than one <table> in provided HTML code!" + " Use from_html instead.") return tables[0]
[docs]def from_md(markdown, **kwargs): """Generate PrettyTable from markdown string. :param markdown: markdown type string. :param kwargs: additional arguments :returns: a PrettyTable object. """ rows = markdown.split('\n') title_row = rows[0] content_rows = rows[2:] table = PrettyTable(**kwargs) table.field_names = split_md_row(title_row) list(map(table.add_row, list(map(split_md_row, [x for x in content_rows if x])))) return table
[docs]def strip_md_content(markdown): """Strip the blank space and `:` in markdown table content cell. :param markdown: a row of markdown table :returns: stripped content cell """ return markdown.strip().strip(':').strip()
[docs]def split_md_row(row): """Split markdown table. :param row: a row of markdown table :returns: Split content list """ return [strip_md_content(s) for s in row.strip('|').split('|')]