|
@@ -1,33 +1,36 @@
|
|
|
-"""
|
|
|
-Copyright (c) Bojan Mihelac and individual contributors.
|
|
|
-All rights reserved.
|
|
|
-
|
|
|
-Redistribution and use in source and binary forms, with or without modification,
|
|
|
-are permitted provided that the following conditions are met:
|
|
|
-
|
|
|
- 1. Redistributions of source code must retain the above copyright notice,
|
|
|
- this list of conditions and the following disclaimer.
|
|
|
-
|
|
|
- 2. 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.
|
|
|
-
|
|
|
-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.
|
|
|
-"""
|
|
|
-# https://raw.githubusercontent.com/django-import-export/django-import-export/main/import_export/formats/base_formats.py
|
|
|
-from io import BytesIO
|
|
|
+import csv
|
|
|
+from io import BytesIO, StringIO
|
|
|
|
|
|
import openpyxl
|
|
|
-import tablib
|
|
|
+
|
|
|
+
|
|
|
+class Dataset(list):
|
|
|
+ def __init__(self, rows=(), headers=None):
|
|
|
+ super().__init__(rows)
|
|
|
+ self.headers = headers or (self.pop(0) if len(self) > 0 else [])
|
|
|
+
|
|
|
+ def __str__(self):
|
|
|
+ """Print a table"""
|
|
|
+ result = [[]]
|
|
|
+ widths = []
|
|
|
+
|
|
|
+ for col in self.headers:
|
|
|
+ value = str(col) if col is not None else ""
|
|
|
+ result[0].append(value)
|
|
|
+ widths.append(len(value) + 1)
|
|
|
+
|
|
|
+ for row in self:
|
|
|
+ result.append([])
|
|
|
+ for idx, col in enumerate(row):
|
|
|
+ value = str(col) if col is not None else ""
|
|
|
+ result[-1].append(value)
|
|
|
+ widths[idx] = max(widths[idx], len(value) + 1)
|
|
|
+
|
|
|
+ row_formatter = (
|
|
|
+ "| ".join(f"{{{idx}:{width}}}" for idx, width in enumerate(widths))
|
|
|
+ ).format
|
|
|
+
|
|
|
+ return "\n".join(row_formatter(*row) for row in result)
|
|
|
|
|
|
|
|
|
class CSV:
|
|
@@ -37,13 +40,19 @@ class CSV:
|
|
|
def get_read_mode(self):
|
|
|
return "r"
|
|
|
|
|
|
- def create_dataset(self, in_stream):
|
|
|
- return tablib.import_set(in_stream, format="csv")
|
|
|
+ def create_dataset(self, data, delimiter=","):
|
|
|
+ """
|
|
|
+ Create dataset from csv data.
|
|
|
+ """
|
|
|
+ return Dataset(csv.reader(StringIO(data), delimiter=delimiter))
|
|
|
|
|
|
|
|
|
class TSV(CSV):
|
|
|
- def create_dataset(self, in_stream):
|
|
|
- return tablib.import_set(in_stream, format="tsv")
|
|
|
+ def create_dataset(self, data):
|
|
|
+ """
|
|
|
+ Create dataset from tsv data.
|
|
|
+ """
|
|
|
+ return super().create_dataset(data, delimiter="\t")
|
|
|
|
|
|
|
|
|
class XLSX:
|
|
@@ -53,23 +62,16 @@ class XLSX:
|
|
|
def get_read_mode(self):
|
|
|
return "rb"
|
|
|
|
|
|
- def create_dataset(self, in_stream):
|
|
|
+ def create_dataset(self, data):
|
|
|
"""
|
|
|
- Create dataset from first sheet.
|
|
|
+ Create dataset from the first sheet of a xlsx workbook.
|
|
|
"""
|
|
|
- xlsx_book = openpyxl.load_workbook(BytesIO(in_stream), read_only=True)
|
|
|
-
|
|
|
- dataset = tablib.Dataset()
|
|
|
- sheet = xlsx_book.active
|
|
|
-
|
|
|
- # obtain generator
|
|
|
- rows = sheet.rows
|
|
|
- dataset.headers = [cell.value for cell in next(rows)]
|
|
|
-
|
|
|
- for row in rows:
|
|
|
- row_values = [cell.value for cell in row]
|
|
|
- dataset.append(row_values)
|
|
|
- return dataset
|
|
|
+ workbook = openpyxl.load_workbook(BytesIO(data), read_only=True, data_only=True)
|
|
|
+ sheet = workbook.worksheets[0]
|
|
|
+ try:
|
|
|
+ return Dataset(tuple(cell.value for cell in row) for row in sheet.rows)
|
|
|
+ finally:
|
|
|
+ workbook.close()
|
|
|
|
|
|
|
|
|
DEFAULT_FORMATS = [
|