diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dcb7f8c7..0c496255 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,16 @@ Change log ================================================================================ +0.7.3 - 12.04.2025 +-------------------------------------------------------------------------------- + +**Fixed** + +#. `#263 `_: support pathlib from + python 3.4 +#. `#267 `_: better error message + for file_name + 0.7.2 - 23.03.2025 -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index 7dfe9a69..e3a01256 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,13 @@ name: pyexcel organisation: pyexcel releases: +- changes: + - action: Fixed + details: + - "`#263`: support pathlib from python 3.4" + - "`#267`: better error message for file_name" + version: 0.7.3 + date: 12.04.2025 - changes: - action: Fixed details: diff --git a/docs/source/conf.py b/docs/source/conf.py index f127d9e6..f048e857 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,9 +26,9 @@ copyright = '2014-2025 Onni Software Ltd.' author = 'C.W.' # The short X.Y version -version = '0.7.2' +version = '0.7.3' # The full version, including alpha/beta/rc tags -release = '0.7.2' +release = '0.7.3' # -- General configuration --------------------------------------------------- diff --git a/pyexcel.yml b/pyexcel.yml index eb387614..58c3bbba 100644 --- a/pyexcel.yml +++ b/pyexcel.yml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel" nick_name: pyexcel -version: 0.7.2 -current_version: 0.7.2 -release: 0.7.2 +version: 0.7.3 +current_version: 0.7.3 +release: 0.7.3 copyright_year: 2014-2025 branch: master is_on_conda: true diff --git a/pyexcel/__init__.py b/pyexcel/__init__.py index f53fc807..ae254e57 100644 --- a/pyexcel/__init__.py +++ b/pyexcel/__init__.py @@ -1,14 +1,15 @@ """ - pyexcel - ~~~~~~~~~~~~~~~~~~~ +pyexcel +~~~~~~~~~~~~~~~~~~~ - **pyexcel** is a wrapper library to read, manipulate and - write data in different excel formats: csv, ods, xls, xlsx - and xlsm. It does not support formulas, styles and charts. +**pyexcel** is a wrapper library to read, manipulate and +write data in different excel formats: csv, ods, xls, xlsx +and xlsm. It does not support formulas, styles and charts. - :copyright: (c) 2014-2025 by Onni Software Ltd. - :license: New BSD License, see LICENSE for more details +:copyright: (c) 2014-2025 by Onni Software Ltd. +:license: New BSD License, see LICENSE for more details """ + from .book import Book from .core import ( save_as, @@ -23,15 +24,16 @@ iget_records, save_book_as, get_book_dict, - isave_book_as + isave_book_as, ) from .sheet import Sheet + # flake8: noqa from .cookbook import ( split_a_book, merge_all_to_a_book, merge_csv_to_a_book, - extract_a_sheet_from_a_book + extract_a_sheet_from_a_book, ) from .deprecated import ( Reader, @@ -43,7 +45,7 @@ load_from_dict, load_from_memory, load_from_records, - load_book_from_memory + load_book_from_memory, ) from .__version__ import __author__, __version__ from .internal.garbagecollector import free_resources diff --git a/pyexcel/__version__.py b/pyexcel/__version__.py index a16fdd69..50cd9438 100644 --- a/pyexcel/__version__.py +++ b/pyexcel/__version__.py @@ -1,2 +1,2 @@ -__version__ = '0.7.2' +__version__ = '0.7.3' __author__ = 'C.W.' diff --git a/pyexcel/_compact.py b/pyexcel/_compact.py index 95eed449..1e814920 100644 --- a/pyexcel/_compact.py +++ b/pyexcel/_compact.py @@ -1,12 +1,13 @@ """ - pyexcel._compact - ~~~~~~~~~~~~~~~~~~~ +pyexcel._compact +~~~~~~~~~~~~~~~~~~~ - Compatibles +Compatibles - :copyright: (c) 2014-2025 by Onni Software Ltd. - :license: New BSD License, see LICENSE for more details +:copyright: (c) 2014-2025 by Onni Software Ltd. +:license: New BSD License, see LICENSE for more details """ + # flake8: noqa # pylint: disable=unused-import # pylint: disable=import-error @@ -18,9 +19,9 @@ import warnings from io import BytesIO, StringIO from urllib import request +from pathlib import Path from textwrap import dedent from itertools import zip_longest - from collections import OrderedDict PY2 = sys.version_info[0] == 2 @@ -72,3 +73,9 @@ def _doc(func): return func return _doc + + +def get_string_file_name(file_name): + if isinstance(file_name, Path): + file_name = str(file_name.resolve()) + return file_name diff --git a/pyexcel/book.py b/pyexcel/book.py index 2876c037..49ce4945 100644 --- a/pyexcel/book.py +++ b/pyexcel/book.py @@ -1,16 +1,17 @@ """ - pyexcel.book - ~~~~~~~~~~~~~~~~~~~ +pyexcel.book +~~~~~~~~~~~~~~~~~~~ - Excel book +Excel book - :copyright: (c) 2014-2025 by Onni Software Ltd. - :license: New BSD License, see LICENSE for more details +:copyright: (c) 2014-2025 by Onni Software Ltd. +:license: New BSD License, see LICENSE for more details """ + from pyexcel.sheet import Sheet +from pyexcel._compact import OrderedDict from pyexcel.internal.meta import BookMeta from pyexcel.internal.common import SheetIterator -from pyexcel._compact import OrderedDict LOCAL_UUID = 0 diff --git a/pyexcel/constants.py b/pyexcel/constants.py index fdde31d2..d0c75fea 100644 --- a/pyexcel/constants.py +++ b/pyexcel/constants.py @@ -1,12 +1,13 @@ """ - pyexcel.constants - ~~~~~~~~~~~~~~~~~~~ +pyexcel.constants +~~~~~~~~~~~~~~~~~~~ - Constants appeared in pyexcel +Constants appeared in pyexcel - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + # flake8: noqa DEFAULT_NA = "" DEFAULT_NAME = "pyexcel sheet" diff --git a/pyexcel/cookbook.py b/pyexcel/cookbook.py index a9a972d7..a9260580 100644 --- a/pyexcel/cookbook.py +++ b/pyexcel/cookbook.py @@ -1,17 +1,18 @@ """ - pyexcel.cookbook - ~~~~~~~~~~~~~~~~~~~ +pyexcel.cookbook +~~~~~~~~~~~~~~~~~~~ - Cookbook for pyexcel +Cookbook for pyexcel - :copyright: (c) 2014-2025 by Onni Software Ltd. - :license: New BSD License, see LICENSE for more details +:copyright: (c) 2014-2025 by Onni Software Ltd. +:license: New BSD License, see LICENSE for more details """ + import os from pyexcel.book import Book from pyexcel.core import save_as, get_book, get_sheet -from pyexcel._compact import OrderedDict +from pyexcel._compact import OrderedDict, get_string_file_name from pyexcel.constants import MESSAGE_WARNING DEFAULT_OUT_FILE = "pyexcel_merged.csv" @@ -19,24 +20,25 @@ OUT_FILE_FORMATTER = "pyexcel_%s" -def update_columns(infilename, column_dicts, outfilename=None): +def update_columns(in_file_name, column_dicts, out_file_name=None): """Update one or more columns of a data file with series The data structure of column_dicts should be: key should be first row of the column the rest of the value should an array - :param str infilename: an accessible file name + :param str in_file_name: an accessible file name :param dict column_dicts: dictionaries of columns - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ - default_out_file = OUT_FILE_FORMATTER % infilename - if outfilename: - default_out_file = outfilename + in_file_name = get_string_file_name(in_file_name) + default_out_file = OUT_FILE_FORMATTER % in_file_name + if out_file_name: + default_out_file = get_string_file_name(out_file_name) if os.path.exists(default_out_file): raise NotImplementedError(MESSAGE_WARNING) - sheet = get_sheet(file_name=infilename, name_columns_by_row=0) + sheet = get_sheet(file_name=in_file_name, name_columns_by_row=0) series = sheet.colnames for k in column_dicts.keys(): index = series.index(str(k)) @@ -44,21 +46,22 @@ def update_columns(infilename, column_dicts, outfilename=None): sheet.save_as(default_out_file) -def update_rows(infilename, row_dicts, outfilename=None): +def update_rows(in_file_name, row_dicts, out_file_name=None): """Update one or more rows of a data file with series - datastucture: key should an integer of the row to be updated + data stucture: key should an integer of the row to be updated value should be an array of the data - :param str infilename: an accessible file name + :param str in_file_name: an accessible file name :param dict row_dicts: dictionaries of rows - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ - default_out_file = OUT_FILE_FORMATTER % infilename - if outfilename: - default_out_file = outfilename + in_file_name = get_string_file_name(in_file_name) + default_out_file = OUT_FILE_FORMATTER % in_file_name + if out_file_name: + default_out_file = get_string_file_name(out_file_name) if os.path.exists(default_out_file): raise NotImplementedError(MESSAGE_WARNING) - sheet = get_sheet(file_name=infilename, name_rows_by_column=0) + sheet = get_sheet(file_name=in_file_name, name_rows_by_column=0) series = sheet.rownames for k in row_dicts.keys(): index = series.index(str(k)) @@ -66,11 +69,12 @@ def update_rows(infilename, row_dicts, outfilename=None): sheet.save_as(default_out_file) -def merge_files(file_array, outfilename=DEFAULT_OUT_FILE): +def merge_files(file_array, out_file_name=DEFAULT_OUT_FILE): """merge many files horizontally column after column - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ - if os.path.exists(outfilename): + out_file_name = get_string_file_name(out_file_name) + if os.path.exists(out_file_name): raise NotImplementedError(MESSAGE_WARNING) content = [] for file_name in file_array: @@ -78,54 +82,56 @@ def merge_files(file_array, outfilename=DEFAULT_OUT_FILE): content.extend(list(sheet.columns())) merged_sheet = get_sheet(array=content) merged_sheet.transpose() - merged_sheet.save_as(outfilename) - return outfilename + merged_sheet.save_as(out_file_name) + return out_file_name -def merge_two_files(file1, file2, outfilename=DEFAULT_OUT_FILE): +def merge_two_files(file1, file2, out_file_name=DEFAULT_OUT_FILE): """merge two files :param str file1: an accessible file name :param str file2: an accessible file name - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ - if os.path.exists(outfilename): + out_file_name = get_string_file_name(out_file_name) + if os.path.exists(out_file_name): raise NotImplementedError(MESSAGE_WARNING) files = [file1, file2] - merge_files(files, outfilename) + merge_files(files, out_file_name) -def merge_readers(reader_array, outfilename=DEFAULT_OUT_FILE): +def merge_readers(reader_array, out_file_name=DEFAULT_OUT_FILE): """merge many readers With FilterableReader and SeriesReader, you can do custom filtering - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ - if os.path.exists(outfilename): + out_file_name = get_string_file_name(out_file_name) + if os.path.exists(out_file_name): raise NotImplementedError(MESSAGE_WARNING) content = OrderedDict() for reader in reader_array: content.update(reader.dict) - save_as(dest_file_name=outfilename, adict=content) + save_as(dest_file_name=out_file_name, adict=content) -def merge_two_readers(reader1, reader2, outfilename=DEFAULT_OUT_FILE): +def merge_two_readers(reader1, reader2, out_file_name=DEFAULT_OUT_FILE): """merge two readers - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ - if os.path.exists(outfilename): + if os.path.exists(out_file_name): raise NotImplementedError(MESSAGE_WARNING) reader_array = [reader1, reader2] - merge_readers(reader_array, outfilename) + merge_readers(reader_array, out_file_name) -def merge_csv_to_a_book(filelist, outfilename=DEFAULT_OUT_XLS_FILE): +def merge_csv_to_a_book(filelist, out_file_name=DEFAULT_OUT_XLS_FILE): """merge a list of csv files into a excel book :param list filelist: a list of accessible file path - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ merged = Book() for file_name in filelist: @@ -133,30 +139,30 @@ def merge_csv_to_a_book(filelist, outfilename=DEFAULT_OUT_XLS_FILE): _, tail = os.path.split(file_name) sheet.name = tail merged += sheet - merged.save_as(outfilename) + merged.save_as(out_file_name) -def merge_all_to_a_book(filelist, outfilename=DEFAULT_OUT_XLS_FILE): +def merge_all_to_a_book(filelist, out_file_name=DEFAULT_OUT_XLS_FILE): """merge a list of excel files into a excel book :param list filelist: a list of accessible file path - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ merged = Book() for file_name in filelist: merged += get_book(file_name=file_name) - merged.save_as(outfilename) + merged.save_as(out_file_name) -def split_a_book(file_name, outfilename=None): +def split_a_book(file_name, out_file_name=None): """Split a file into separate sheets :param str file_name: an accessible file name - :param str outfilename: save the sheets with file suffix + :param str out_file_name: save the sheets with file suffix """ book = get_book(file_name=file_name) - if outfilename: - saveas = outfilename + if out_file_name: + saveas = out_file_name else: saveas = file_name for sheet in book: @@ -164,16 +170,16 @@ def split_a_book(file_name, outfilename=None): sheet.save_as(filename) -def extract_a_sheet_from_a_book(file_name, sheetname, outfilename=None): +def extract_a_sheet_from_a_book(file_name, sheetname, out_file_name=None): """Extract a sheet from a excel book :param str file_name: an accessible file name :param str sheetname: a valid sheet name - :param str outfilename: save the sheet as + :param str out_file_name: save the sheet as """ book = get_book(file_name=file_name) - if outfilename: - saveas = outfilename + if out_file_name: + saveas = out_file_name else: saveas = file_name sheet = book[sheetname] diff --git a/pyexcel/core.py b/pyexcel/core.py index 22e518a8..b39b0d3a 100644 --- a/pyexcel/core.py +++ b/pyexcel/core.py @@ -1,12 +1,13 @@ """ - pyexcel.core - ~~~~~~~~~~~~~~~~~~~ +pyexcel.core +~~~~~~~~~~~~~~~~~~~ - A list of pyexcel signature functions +A list of pyexcel signature functions - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + import re from pyexcel import constants diff --git a/pyexcel/deprecated.py b/pyexcel/deprecated.py index c663ced7..7aa831b0 100644 --- a/pyexcel/deprecated.py +++ b/pyexcel/deprecated.py @@ -1,12 +1,13 @@ """ - pyexcel.deprecated - ~~~~~~~~~~~~~~~~~~~ +pyexcel.deprecated +~~~~~~~~~~~~~~~~~~~ - List of apis that become deprecated but was kept for backward compatibility +List of APIs that become deprecated but was kept for backward compatibility - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from functools import partial from pyexcel.core import get_book, get_sheet @@ -66,7 +67,9 @@ def load(file_name, sheetname=None, **keywords): ) else: sheet = get_sheet( - file_name=file_name, sheet_name=sheetname, **keywords, + file_name=file_name, + sheet_name=sheetname, + **keywords, ) return sheet diff --git a/pyexcel/docstrings/__init__.py b/pyexcel/docstrings/__init__.py index cba9bd34..c82fe8fc 100644 --- a/pyexcel/docstrings/__init__.py +++ b/pyexcel/docstrings/__init__.py @@ -1,12 +1,13 @@ """ - pyexcel.docstrings - ~~~~~~~~~~~~~~~~~~~ +pyexcel.docstrings +~~~~~~~~~~~~~~~~~~~ - Reusible docstrings +Reusible docstrings - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + # flake8: noqa from .core import ( SAVE_AS, @@ -21,7 +22,7 @@ IGET_RECORDS, SAVE_BOOK_AS, GET_BOOK_DICT, - ISAVE_BOOK_AS + ISAVE_BOOK_AS, ) from .meta import SAVE_AS_OPTIONS from .garbagecollector import FREE_RESOURCES diff --git a/pyexcel/docstrings/core.py b/pyexcel/docstrings/core.py index f23656b7..49a4ed7a 100644 --- a/pyexcel/docstrings/core.py +++ b/pyexcel/docstrings/core.py @@ -1,12 +1,13 @@ """ - pyexcel.docstrings.core - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.docstrings.core +~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Reusible docstrings for pyexcel.core +Reusable docstrings for pyexcel.core - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from . import keywords __GET_ARRAY__ = ( diff --git a/pyexcel/docstrings/keywords.py b/pyexcel/docstrings/keywords.py index d5c9a219..75460f04 100644 --- a/pyexcel/docstrings/keywords.py +++ b/pyexcel/docstrings/keywords.py @@ -1,12 +1,13 @@ """ - pyexcel.docstrings.keywords - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.docstrings.keywords +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Reusible docstrings for keywords in signature functions +Reusable docstrings for keywords in signature functions - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + CSV_PARAMS = """ **Parameters related to csv file format** diff --git a/pyexcel/docstrings/meta.py b/pyexcel/docstrings/meta.py index 077d2876..4005f1f0 100644 --- a/pyexcel/docstrings/meta.py +++ b/pyexcel/docstrings/meta.py @@ -1,12 +1,13 @@ """ - pyexcel.docstrings.meta - ~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.docstrings.meta +~~~~~~~~~~~~~~~~~~~~~~~~~ - Reusible docstrings for pyexcel.internal.meta +Reusable docstrings for pyexcel.internal.meta - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from .keywords import CSV_PARAMS SAVE_AS_OPTIONS = ( diff --git a/pyexcel/exceptions.py b/pyexcel/exceptions.py index 05c12db2..12f41df7 100644 --- a/pyexcel/exceptions.py +++ b/pyexcel/exceptions.py @@ -1,11 +1,11 @@ """ - pyexcel.exceptions - ~~~~~~~~~~~~~~~~~~~ +pyexcel.exceptions +~~~~~~~~~~~~~~~~~~~ - Exceptions appeared in pyexcel +Exceptions appeared in pyexcel - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ diff --git a/pyexcel/internal/__init__.py b/pyexcel/internal/__init__.py index 67990720..392473ed 100644 --- a/pyexcel/internal/__init__.py +++ b/pyexcel/internal/__init__.py @@ -1,12 +1,13 @@ """ - pyexcel.internal - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Pyexcel internals that subjected to change +Pyexcel internals that subjected to change - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from lml.loader import scan_plugins_regex from pyexcel.internal.plugins import PARSER, RENDERER # noqa from pyexcel.internal.generators import BookStream, SheetStream # noqa diff --git a/pyexcel/internal/attributes.py b/pyexcel/internal/attributes.py index d7965894..351f285c 100644 --- a/pyexcel/internal/attributes.py +++ b/pyexcel/internal/attributes.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.attributes - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Book and sheet attributes +Book and sheet attributes - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel import constants ATTRIBUTE_REGISTRY = { diff --git a/pyexcel/internal/common.py b/pyexcel/internal/common.py index 37e84075..bdfbe00f 100644 --- a/pyexcel/internal/common.py +++ b/pyexcel/internal/common.py @@ -1,16 +1,17 @@ """ - pyexcel.internal.common - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.common +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defintion for the shared objects +Definition for the shared objects - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + NO_COLUMN_NAMES = "Only sheet with column names is accepted" -class SheetIterator(): +class SheetIterator: """ Sheet Iterator """ diff --git a/pyexcel/internal/core.py b/pyexcel/internal/core.py index 1749d748..e6ffd08b 100644 --- a/pyexcel/internal/core.py +++ b/pyexcel/internal/core.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.core - ~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.core +~~~~~~~~~~~~~~~~~~~~~~ - elementary functions to read and write generic excel content +elementary functions to read and write generic excel content - :copyright: (c) 2015-2021 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2021 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.internal import SOURCE from pyexcel.constants import DEFAULT_NO_DATA from pyexcel.internal.generators import BookStream, SheetStream diff --git a/pyexcel/internal/garbagecollector.py b/pyexcel/internal/garbagecollector.py index 76cf5fe9..02f6b8a3 100644 --- a/pyexcel/internal/garbagecollector.py +++ b/pyexcel/internal/garbagecollector.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.garbagecollector - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.garbagecollector +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Simple garbage collector +Simple garbage collector - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel import docstrings as docs from pyexcel._compact import append_doc @@ -17,7 +18,6 @@ def append(item): """ add garbage to the global list of garbages """ - global GARBAGE GARBAGE.append(item) @@ -36,5 +36,4 @@ def reset(): """ After everything has been closed, reset the array """ - global GARBAGE - GARBAGE = [] + GARBAGE.clear() diff --git a/pyexcel/internal/generators.py b/pyexcel/internal/generators.py index c52e0b5d..cf34af9e 100644 --- a/pyexcel/internal/generators.py +++ b/pyexcel/internal/generators.py @@ -1,17 +1,18 @@ """ - pyexcel.internal.generators - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.generators +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defintion for the sheet and book generators. +Defintion for the sheet and book generators. - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel._compact import OrderedDict from pyexcel.internal.common import SheetIterator -class SheetStream(): +class SheetStream: """ Memory efficient sheet representation @@ -47,7 +48,7 @@ def get_internal_array(self): return self.payload -class BookStream(): +class BookStream: """ Memory efficient book representation diff --git a/pyexcel/internal/meta.py b/pyexcel/internal/meta.py index 3b399fa6..313e3f05 100644 --- a/pyexcel/internal/meta.py +++ b/pyexcel/internal/meta.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.meta - ~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.meta +~~~~~~~~~~~~~~~~~~~~~~ - Annotate sheet and book class' attributes +Annotate sheet and book class' attributes - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + import sys from functools import partial @@ -143,7 +144,7 @@ def attribute( ) -class StreamAttribute(): +class StreamAttribute: """Provide access to get_*_stream methods""" def __init__(self, cls): @@ -154,7 +155,7 @@ def __getattr__(self, name): return getter(file_type=name) -class PyexcelObject(): +class PyexcelObject: """parent class for pyexcel.Sheet and pyexcel.Book""" @property @@ -261,12 +262,19 @@ def save_as(self, filename, **keywords): def save_to_memory(self, file_type, stream=None, **keywords): stream = save_sheet( - self, file_type=file_type, file_stream=stream, **keywords, + self, + file_type=file_type, + file_stream=stream, + **keywords, ) return stream def save_to_django_model( - self, model, initializer=None, mapdict=None, batch_size=None, + self, + model, + initializer=None, + mapdict=None, + batch_size=None, ): """Save to database table through django model @@ -285,7 +293,12 @@ def save_to_django_model( ) def save_to_database( - self, session, table, initializer=None, mapdict=None, auto_commit=True, + self, + session, + table, + initializer=None, + mapdict=None, + auto_commit=True, ): """Save data in sheet to database table @@ -330,12 +343,19 @@ def save_to_memory(self, file_type, stream=None, **keywords): xlsx, and ods, an instance of BytesIO. """ stream = save_book( - self, file_type=file_type, file_stream=stream, **keywords, + self, + file_type=file_type, + file_stream=stream, + **keywords, ) return stream def save_to_django_models( - self, models, initializers=None, mapdicts=None, **keywords, + self, + models, + initializers=None, + mapdicts=None, + **keywords, ): """ Save to database table through django model diff --git a/pyexcel/internal/plugins.py b/pyexcel/internal/plugins.py index 2e2bd54d..8bf7ead4 100644 --- a/pyexcel/internal/plugins.py +++ b/pyexcel/internal/plugins.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.plugins - ~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.plugins +~~~~~~~~~~~~~~~~~~~~~~~~~~ - Renderer and parser plugin manager +Renderer and parser plugin manager - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from lml.plugin import PluginManager diff --git a/pyexcel/internal/sheets/__init__.py b/pyexcel/internal/sheets/__init__.py index 1b095f64..a3758d80 100644 --- a/pyexcel/internal/sheets/__init__.py +++ b/pyexcel/internal/sheets/__init__.py @@ -1,11 +1,12 @@ """ - pyexcel.internal.sheets - ~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.sheets +~~~~~~~~~~~~~~~~~~~~~~~~ - Core functionality of pyexcel, data model +Core functionality of pyexcel, data model - :copyright: (c) 2014-2025 by Onni Software Ltd. - :license: New BSD License, see LICENSE for more details +:copyright: (c) 2014-2025 by Onni Software Ltd. +:license: New BSD License, see LICENSE for more details """ + # flake8: noqa from .matrix import Row, Column, Matrix, transpose diff --git a/pyexcel/internal/sheets/_shared.py b/pyexcel/internal/sheets/_shared.py index 4668bf70..5932893a 100644 --- a/pyexcel/internal/sheets/_shared.py +++ b/pyexcel/internal/sheets/_shared.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.sheets._shared - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.sheets._shared +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Locally shared utility functions +Locally shared utility functions - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + import re import types from typing import Tuple @@ -17,7 +18,7 @@ from .formatters import to_format -class CommonPropertyAmongRowNColumn(): +class CommonPropertyAmongRowNColumn: """ Group reusable functions from row and column """ diff --git a/pyexcel/internal/sheets/column.py b/pyexcel/internal/sheets/column.py index 29067d5f..49535532 100644 --- a/pyexcel/internal/sheets/column.py +++ b/pyexcel/internal/sheets/column.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.sheets.column - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.sheets.column +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Generic table column +Generic table column - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + import copy import types @@ -159,7 +160,8 @@ def __delitem__(self, aslice): """ is_sheet = compact.is_string(type(aslice)) and hasattr( - self._ref, "delete_named_column_at", + self._ref, + "delete_named_column_at", ) if is_sheet: self._ref.delete_named_column_at(aslice) @@ -168,7 +170,8 @@ def __delitem__(self, aslice): self._ref.delete_columns(indices) elif isinstance(aslice, slice): my_range = utils.analyse_slice( - aslice, self._ref.number_of_columns(), + aslice, + self._ref.number_of_columns(), ) self._ref.delete_columns(my_range) elif isinstance(aslice, str): @@ -200,13 +203,15 @@ def _delete_columns_by_content(self, locator): def __setitem__(self, aslice, a_column): """Override the operator to set items""" is_sheet = compact.is_string(type(aslice)) and hasattr( - self._ref, "set_named_column_at", + self._ref, + "set_named_column_at", ) if is_sheet: self._ref.set_named_column_at(aslice, a_column) elif isinstance(aslice, slice): my_range = utils.analyse_slice( - aslice, self._ref.number_of_columns(), + aslice, + self._ref.number_of_columns(), ) for i in my_range: self._ref.set_column_at(i, a_column) @@ -223,14 +228,16 @@ def __getitem__(self, aslice): from left to right""" index = aslice is_sheet = compact.is_string(type(aslice)) and hasattr( - self._ref, "named_column_at", + self._ref, + "named_column_at", ) if is_sheet: return self._ref.named_column_at(aslice) if isinstance(aslice, slice): my_range = utils.analyse_slice( - aslice, self._ref.number_of_columns(), + aslice, + self._ref.number_of_columns(), ) results = [] for i in my_range: diff --git a/pyexcel/internal/sheets/formatters.py b/pyexcel/internal/sheets/formatters.py index 6893d156..97a1070b 100644 --- a/pyexcel/internal/sheets/formatters.py +++ b/pyexcel/internal/sheets/formatters.py @@ -1,12 +1,13 @@ """ - pyexcel.formatters - ~~~~~~~~~~~~~~~~~~~ +pyexcel.formatters +~~~~~~~~~~~~~~~~~~~ - These utilities help format the content +These utilities help format the content - :copyright: (c) 2014-2025 by Onni Software Ltd. - :license: New BSD License, see LICENSE for more details +:copyright: (c) 2014-2025 by Onni Software Ltd. +:license: New BSD License, see LICENSE for more details """ + import json import datetime from decimal import Decimal diff --git a/pyexcel/internal/sheets/matrix.py b/pyexcel/internal/sheets/matrix.py index b3388193..07d2ab22 100644 --- a/pyexcel/internal/sheets/matrix.py +++ b/pyexcel/internal/sheets/matrix.py @@ -1,13 +1,14 @@ """ - pyexcel.internal.sheets.matrix - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.sheets.matrix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Matrix, a data model that accepts any types, spread sheet style - of lookup. +Matrix, a data model that accepts any types, spread sheet style +of lookup. - :copyright: (c) 2014-2025 by Onni Software Ltd. - :license: New BSD License, see LICENSE for more details +:copyright: (c) 2014-2025 by Onni Software Ltd. +:license: New BSD License, see LICENSE for more details """ + import copy import types from typing import Tuple, Union @@ -437,7 +438,9 @@ def _paste_columns(self, topleft_corner, columns): set_index = starting_column + index if set_index < number_of_columns: self.set_column_at( - set_index, column, starting=topleft_corner[0], + set_index, + column, + starting=topleft_corner[0], ) else: real_column = [constants.DEFAULT_NA] * topleft_corner[0] diff --git a/pyexcel/internal/sheets/row.py b/pyexcel/internal/sheets/row.py index 054cb840..1c25095e 100644 --- a/pyexcel/internal/sheets/row.py +++ b/pyexcel/internal/sheets/row.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.sheets.row - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.sheets.row +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Generic table row +Generic table row - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + import copy import types diff --git a/pyexcel/internal/source_plugin.py b/pyexcel/internal/source_plugin.py index a0ca499e..7d870e48 100644 --- a/pyexcel/internal/source_plugin.py +++ b/pyexcel/internal/source_plugin.py @@ -1,12 +1,13 @@ """ - pyexcel.internal.source_plugin - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.internal.source_plugin +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Second level abstraction +Second level abstraction - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel import constants, exceptions from lml.plugin import PluginManager from pyexcel.internal.attributes import ( @@ -55,7 +56,11 @@ def register_a_plugin(self, plugin_cls, plugin_info): self._register_a_plugin_info(plugin_info) def get_a_plugin( - self, target=None, action=None, source_library=None, **keywords, + self, + target=None, + action=None, + source_library=None, + **keywords, ): """obtain a source plugin for signature functions""" key = REGISTRY_KEY_FORMAT % (target, action) @@ -64,7 +69,10 @@ def get_a_plugin( if "library" in keywords: io_library = keywords.pop("library") source_cls = self.load_me_now( - key, action=action, library=source_library, **keywords, + key, + action=action, + library=source_library, + **keywords, ) if io_library is not None: keywords["library"] = io_library @@ -74,25 +82,33 @@ def get_a_plugin( def get_source(self, **keywords): """obtain a sheet read source plugin for signature functions""" return self.get_a_plugin( - target=constants.SHEET, action=constants.READ_ACTION, **keywords, + target=constants.SHEET, + action=constants.READ_ACTION, + **keywords, ) def get_book_source(self, **keywords): """obtain a book read source plugin for signature functions""" return self.get_a_plugin( - target=constants.BOOK, action=constants.READ_ACTION, **keywords, + target=constants.BOOK, + action=constants.READ_ACTION, + **keywords, ) def get_writable_source(self, **keywords): """obtain a sheet write source plugin for signature functions""" return self.get_a_plugin( - target=constants.SHEET, action=constants.WRITE_ACTION, **keywords, + target=constants.SHEET, + action=constants.WRITE_ACTION, + **keywords, ) def get_writable_book_source(self, **keywords): """obtain a book write source plugin for signature functions""" return self.get_a_plugin( - target=constants.BOOK, action=constants.WRITE_ACTION, **keywords, + target=constants.BOOK, + action=constants.WRITE_ACTION, + **keywords, ) def get_keyword_for_parameter(self, key): diff --git a/pyexcel/parser.py b/pyexcel/parser.py index 3987e4ec..87678221 100644 --- a/pyexcel/parser.py +++ b/pyexcel/parser.py @@ -1,16 +1,17 @@ """ - pyexcel.parser - ~~~~~~~~~~~~~~~~~~~ +pyexcel.parser +~~~~~~~~~~~~~~~~~~~ - Extract tabular data from external file, stream or content +Extract tabular data from external file, stream or content - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.internal import garbagecollector as gc -class AbstractParser(): +class AbstractParser: """ Parsing data from tabular data such as excel file """ diff --git a/pyexcel/plugins/__init__.py b/pyexcel/plugins/__init__.py index 899dff2f..838c31e8 100644 --- a/pyexcel/plugins/__init__.py +++ b/pyexcel/plugins/__init__.py @@ -1,18 +1,19 @@ """ - pyexcel.plugins - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Public interface for plugins +Public interface for plugins - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + import types from itertools import product from pyexcel import constants from lml.plugin import PluginInfo, PluginInfoChain -from pyexcel._compact import is_string +from pyexcel._compact import is_string, get_string_file_name from pyexcel.exceptions import FileTypeNotSupported from pyexcel.internal.plugins import PARSER, RENDERER @@ -44,16 +45,19 @@ def is_my_business(self, action, **keywords): status = SourceInfo.is_my_business(self, action, **keywords) if status: file_name = keywords.get("file_name", None) + file_name = get_string_file_name(file_name) if file_name: file_type = keywords.get("force_file_type") if file_type is None: if is_string(type(file_name)): file_type = find_file_type_from_file_name( - file_name, action, + file_name, + action, ) else: - raise IOError("Unsupported file type") + message = f"Unsupported file type, {type(file_name)}" + raise IOError(message) else: file_type = keywords.get("file_type") @@ -142,7 +146,8 @@ def add_a_source(self, relative_plugin_class_path=None, **keywords): default.update(keywords) self.add_a_plugin_instance( SourceInfo( - self._get_abs_path(relative_plugin_class_path), **default, + self._get_abs_path(relative_plugin_class_path), + **default, ), ) return self @@ -155,7 +160,8 @@ def add_an_input_source(self, relative_plugin_class_path=None, **keywords): default.update(keywords) self.add_a_plugin_instance( InputSourceInfo( - self._get_abs_path(relative_plugin_class_path), **default, + self._get_abs_path(relative_plugin_class_path), + **default, ), ) return self @@ -168,7 +174,8 @@ def add_a_output_source(self, relative_plugin_class_path=None, **keywords): default.update(keywords) self.add_a_plugin_instance( OutputSourceInfo( - self._get_abs_path(relative_plugin_class_path), **default, + self._get_abs_path(relative_plugin_class_path), + **default, ), ) return self diff --git a/pyexcel/plugins/parsers/__init__.py b/pyexcel/plugins/parsers/__init__.py index a4ca0b60..c7308261 100644 --- a/pyexcel/plugins/parsers/__init__.py +++ b/pyexcel/plugins/parsers/__init__.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.parsers - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.parsers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - A list of built-in parsers +A list of built-in parsers - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.plugins import PyexcelPluginChain from pyexcel_io.plugins import READERS @@ -19,5 +20,6 @@ relative_plugin_class_path="sqlalchemy.SQLAlchemyExporter", file_types=[DB_SQL], ).add_a_parser( - relative_plugin_class_path="django.DjangoExporter", file_types=[DB_DJANGO], + relative_plugin_class_path="django.DjangoExporter", + file_types=[DB_DJANGO], ) diff --git a/pyexcel/plugins/parsers/django.py b/pyexcel/plugins/parsers/django.py index 645a9956..9f0321e4 100644 --- a/pyexcel/plugins/parsers/django.py +++ b/pyexcel/plugins/parsers/django.py @@ -1,12 +1,13 @@ """ - pyexcel.plugin.parsers.django - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugin.parsers.django +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Export data into database datables +Export data into database datables - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.parser import DbParser from pyexcel_io import get_data, iget_data @@ -17,7 +18,11 @@ class DjangoExporter(DbParser): """Export data from django model""" def parse_db( - self, argument, export_columns_list=None, on_demand=True, **keywords, + self, + argument, + export_columns_list=None, + on_demand=True, + **keywords, ): models = argument exporter = django.DjangoModelExporter() @@ -28,7 +33,9 @@ def parse_db( exporter.append(adapter) if on_demand: sheets, _ = iget_data( - exporter, file_type=self._file_type, **keywords, + exporter, + file_type=self._file_type, + **keywords, ) else: sheets = get_data(exporter, file_type=self._file_type, **keywords) diff --git a/pyexcel/plugins/parsers/excel.py b/pyexcel/plugins/parsers/excel.py index 461b97aa..758cfc27 100644 --- a/pyexcel/plugins/parsers/excel.py +++ b/pyexcel/plugins/parsers/excel.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.parsers.excel - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.parsers.excel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Parsing excel sources +Parsing excel sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.parser import AbstractParser from pyexcel_io import get_data, iget_data @@ -20,20 +21,30 @@ def parse_file(self, file_name, **keywords): def parse_file_stream(self, file_stream, **keywords): return self._parse_any( - file_stream, file_type=self._file_type, **keywords, + file_stream, + file_type=self._file_type, + **keywords, ) def parse_file_content(self, file_content, **keywords): return self._parse_any( - file_content, file_type=self._file_type, **keywords, + file_content, + file_type=self._file_type, + **keywords, ) def _parse_any( - self, anything, on_demand=False, file_type=None, **keywords, + self, + anything, + on_demand=False, + file_type=None, + **keywords, ): if on_demand: sheets, reader = iget_data( - anything, file_type=file_type, **keywords, + anything, + file_type=file_type, + **keywords, ) self._free_me_up_later(reader) else: diff --git a/pyexcel/plugins/parsers/sqlalchemy.py b/pyexcel/plugins/parsers/sqlalchemy.py index 05b1d4bd..f1b48af2 100644 --- a/pyexcel/plugins/parsers/sqlalchemy.py +++ b/pyexcel/plugins/parsers/sqlalchemy.py @@ -1,12 +1,13 @@ """ - pyexcel.plugin.parsers.sqlalchemy - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugin.parsers.sqlalchemy +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Export data into database datables +Export data into database datables - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.parser import DbParser from pyexcel_io import get_data, iget_data @@ -17,7 +18,11 @@ class SQLAlchemyExporter(DbParser): """export data via sqlalchemy""" def parse_db( - self, argument, export_columns_list=None, on_demand=False, **keywords, + self, + argument, + export_columns_list=None, + on_demand=False, + **keywords, ): session, tables = argument exporter = sql.SQLTableExporter(session) @@ -28,7 +33,9 @@ def parse_db( exporter.append(adapter) if on_demand: sheets, _ = iget_data( - exporter, file_type=self._file_type, **keywords, + exporter, + file_type=self._file_type, + **keywords, ) else: sheets = get_data(exporter, file_type=self._file_type, **keywords) diff --git a/pyexcel/plugins/renderers/__init__.py b/pyexcel/plugins/renderers/__init__.py index d089d357..8f0b8aca 100644 --- a/pyexcel/plugins/renderers/__init__.py +++ b/pyexcel/plugins/renderers/__init__.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.renderers - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.renderers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - A list of built-in renderers +A list of built-in renderers - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.plugins import PyexcelPluginChain from pyexcel_io.plugins import WRITERS @@ -16,7 +17,8 @@ relative_plugin_class_path="sqlalchemy.SQLAlchemyRenderer", file_types=[DB_SQL], ).add_a_renderer( - relative_plugin_class_path="django.DjangoRenderer", file_types=[DB_DJANGO], + relative_plugin_class_path="django.DjangoRenderer", + file_types=[DB_DJANGO], ).add_a_renderer( relative_plugin_class_path="excel.ExcelRenderer", file_types=WRITERS.get_all_formats(), diff --git a/pyexcel/plugins/renderers/_texttable.py b/pyexcel/plugins/renderers/_texttable.py index b98d1b6f..82d5fbc5 100644 --- a/pyexcel/plugins/renderers/_texttable.py +++ b/pyexcel/plugins/renderers/_texttable.py @@ -1,13 +1,14 @@ """ - pyexcel.plugin.renderers._texttable - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugin.renderers._texttable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Export data into texttable format. It also serves the default - presentation of pyexcel sheet and book. +Export data into texttable format. It also serves the default +presentation of pyexcel sheet and book. - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from types import GeneratorType from pyexcel import constants diff --git a/pyexcel/plugins/renderers/django.py b/pyexcel/plugins/renderers/django.py index 7c495c3e..4cb426d4 100644 --- a/pyexcel/plugins/renderers/django.py +++ b/pyexcel/plugins/renderers/django.py @@ -1,12 +1,13 @@ """ - pyexcel.plugin.renderers.django - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugin.renderers.django +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Export data into django models +Export data into django models - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel._compact import OrderedDict from pyexcel.internal import common from pyexcel.renderer import DbRenderer @@ -21,7 +22,12 @@ class DjangoRenderer(DbRenderer): """Import data into database""" def render_sheet_to_stream( - self, model, sheet, init=None, mapdict=None, **keywords, + self, + model, + sheet, + init=None, + mapdict=None, + **keywords, ): headers = common.get_sheet_headers(sheet) importer = django.DjangoModelImporter() diff --git a/pyexcel/plugins/renderers/excel.py b/pyexcel/plugins/renderers/excel.py index d4618b97..5e127a4e 100644 --- a/pyexcel/plugins/renderers/excel.py +++ b/pyexcel/plugins/renderers/excel.py @@ -1,12 +1,14 @@ """ - pyexcel.plugin.renderers.excel - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugin.renderers.excel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Export data into excel files +Export data into excel files - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + +from pyexcel._compact import get_string_file_name from pyexcel.renderer import AbstractRenderer from pyexcel.constants import DEFAULT_SHEET_NAME @@ -20,6 +22,7 @@ def get_io(self): return manager.get_io(self._file_type) def render_sheet_to_file(self, file_name, sheet, **keywords): + file_name = get_string_file_name(file_name) sheet_name = DEFAULT_SHEET_NAME if sheet.name: sheet_name = sheet.name @@ -27,14 +30,21 @@ def render_sheet_to_file(self, file_name, sheet, **keywords): save_data(file_name, data, **keywords) def render_book_to_file(self, file_name, book, **keywords): + file_name = get_string_file_name(file_name) save_data(file_name, book.to_dict(), **keywords) def render_sheet_to_stream(self, file_stream, sheet, **keywords): self.render_sheet_to_file( - file_stream, sheet, file_type=self._file_type, **keywords, + file_stream, + sheet, + file_type=self._file_type, + **keywords, ) def render_book_to_stream(self, file_stream, book, **keywords): self.render_book_to_file( - file_stream, book, file_type=self._file_type, **keywords, + file_stream, + book, + file_type=self._file_type, + **keywords, ) diff --git a/pyexcel/plugins/renderers/sqlalchemy.py b/pyexcel/plugins/renderers/sqlalchemy.py index 528f6356..00025867 100644 --- a/pyexcel/plugins/renderers/sqlalchemy.py +++ b/pyexcel/plugins/renderers/sqlalchemy.py @@ -1,12 +1,13 @@ """ - pyexcel.plugin.renderers.sqlalchemy - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugin.renderers.sqlalchemy +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Export data into database datables +Export data into database datables - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel._compact import OrderedDict from pyexcel.internal import common from pyexcel.renderer import DbRenderer @@ -19,7 +20,12 @@ class SQLAlchemyRenderer(DbRenderer): """Import data into database""" def render_sheet_to_stream( - self, file_stream, sheet, init=None, mapdict=None, **keywords, + self, + file_stream, + sheet, + init=None, + mapdict=None, + **keywords, ): headers = common.get_sheet_headers(sheet) importer = sql.SQLTableImporter(file_stream[0]) @@ -36,7 +42,12 @@ def render_sheet_to_stream( ) def render_book_to_stream( - self, file_stream, book, inits=None, mapdicts=None, **keywords, + self, + file_stream, + book, + inits=None, + mapdicts=None, + **keywords, ): session, tables = file_stream thebook = book diff --git a/pyexcel/plugins/sources/__init__.py b/pyexcel/plugins/sources/__init__.py index 17005395..647c13e3 100644 --- a/pyexcel/plugins/sources/__init__.py +++ b/pyexcel/plugins/sources/__init__.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - A list of built-in sources +A list of built-in sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.plugins import PyexcelPluginChain from pyexcel.internal import PARSER, RENDERER diff --git a/pyexcel/plugins/sources/db_sources.py b/pyexcel/plugins/sources/db_sources.py index 828fee94..29cdac4c 100644 --- a/pyexcel/plugins/sources/db_sources.py +++ b/pyexcel/plugins/sources/db_sources.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.db_sources - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.db_sources +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Generic database sources +Generic database sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource from pyexcel._compact import PY2 from pyexcel.internal import PARSER, RENDERER @@ -76,7 +77,11 @@ class BookDbSource(AbstractSource): """ def __init__( - self, db_type, parser_library=None, renderer_library=None, **keywords, + self, + db_type, + parser_library=None, + renderer_library=None, + **keywords, ): self.__db_type = db_type self.__parser_library = parser_library @@ -98,7 +103,8 @@ def get_source_info(self): def write_data(self, book): arender = RENDERER.get_a_plugin( - self.__db_type, self.__renderer_library, + self.__db_type, + self.__renderer_library, ) init_funcs, map_dicts = _transcode_book_db_keywords(self._keywords) diff --git a/pyexcel/plugins/sources/django.py b/pyexcel/plugins/sources/django.py index 07d9572b..deeb5176 100644 --- a/pyexcel/plugins/sources/django.py +++ b/pyexcel/plugins/sources/django.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.django - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.django +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of django sources +Representation of django sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel_io.constants import DB_DJANGO from .db_sources import BookDbSource, SheetDbSource @@ -17,7 +18,11 @@ class SheetDjangoSource(SheetDbSource): """ def __init__( - self, model=None, export_columns=None, sheet_name=None, **keywords, + self, + model=None, + export_columns=None, + sheet_name=None, + **keywords, ): self.__model = model SheetDbSource.__init__( diff --git a/pyexcel/plugins/sources/file_input.py b/pyexcel/plugins/sources/file_input.py index 8cfd2ced..ee2bc5ad 100644 --- a/pyexcel/plugins/sources/file_input.py +++ b/pyexcel/plugins/sources/file_input.py @@ -1,15 +1,17 @@ """ - pyexcel.plugins.sources.file_input - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.file_input +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of input file sources +Representation of input file sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + import os from pyexcel.source import AbstractSource +from pyexcel._compact import get_string_file_name from pyexcel.internal import PARSER @@ -18,7 +20,7 @@ class ReadExcelFromFile(AbstractSource): """Pick up 'file_name' field and do single sheet based read and write""" def __init__(self, file_name=None, parser_library=None, **keywords): - self.__file_name = file_name + self.__file_name = get_string_file_name(file_name) if "force_file_type" in keywords: file_type = keywords.get("force_file_type") diff --git a/pyexcel/plugins/sources/file_output.py b/pyexcel/plugins/sources/file_output.py index 36354d4e..c6adc03f 100644 --- a/pyexcel/plugins/sources/file_output.py +++ b/pyexcel/plugins/sources/file_output.py @@ -1,14 +1,16 @@ """ - pyexcel.plugins.sources.file_output - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.file_output +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of output file sources +Representation of output file sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource from pyexcel.plugins import find_file_type_from_file_name +from pyexcel._compact import get_string_file_name from pyexcel.internal import RENDERER @@ -18,18 +20,20 @@ class WriteSheetToFile(AbstractSource): def __init__(self, file_name=None, renderer_library=None, **keywords): AbstractSource.__init__(self, **keywords) - self._file_name = file_name + self._file_name = get_string_file_name(file_name) if "force_file_type" in keywords: file_type = keywords.get("force_file_type") else: - file_type = find_file_type_from_file_name(file_name, "write") + file_type = find_file_type_from_file_name(self._file_name, "write") self._renderer = RENDERER.get_a_plugin(file_type, renderer_library) def write_data(self, sheet): self._renderer.render_sheet_to_file( - self._file_name, sheet, **self._keywords, + self._file_name, + sheet, + **self._keywords, ) @@ -39,5 +43,7 @@ class WriteBookToFile(WriteSheetToFile): def write_data(self, book): self._renderer.render_book_to_file( - self._file_name, book, **self._keywords, + self._file_name, + book, + **self._keywords, ) diff --git a/pyexcel/plugins/sources/http.py b/pyexcel/plugins/sources/http.py index 7dcc3472..6f88f1ec 100644 --- a/pyexcel/plugins/sources/http.py +++ b/pyexcel/plugins/sources/http.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.http - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.http +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of http sources +Representation of http sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel import constants from pyexcel.source import AbstractSource from pyexcel._compact import PY2, request diff --git a/pyexcel/plugins/sources/memory_input.py b/pyexcel/plugins/sources/memory_input.py index 3f2be3c2..aa35d0e4 100644 --- a/pyexcel/plugins/sources/memory_input.py +++ b/pyexcel/plugins/sources/memory_input.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.memory_input - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.memory_input +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of input file sources +Representation of input file sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource from pyexcel.internal import PARSER @@ -34,11 +35,13 @@ def __init__( def get_data(self): if self.__file_stream is not None: sheets = self.__parser.parse_file_stream( - self.__file_stream, **self._keywords, + self.__file_stream, + **self._keywords, ) else: sheets = self.__parser.parse_file_content( - self.__file_content, **self._keywords, + self.__file_content, + **self._keywords, ) return sheets diff --git a/pyexcel/plugins/sources/output_to_memory.py b/pyexcel/plugins/sources/output_to_memory.py index 7c0b6fbe..1874b0bc 100644 --- a/pyexcel/plugins/sources/output_to_memory.py +++ b/pyexcel/plugins/sources/output_to_memory.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.output_to_memory - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.output_to_memory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of output file sources +Representation of output file sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource, MemorySourceMixin from pyexcel.internal import RENDERER @@ -35,7 +36,9 @@ def __init__( def write_data(self, sheet): self._renderer.render_sheet_to_stream( - self._content, sheet, **self._keywords, + self._content, + sheet, + **self._keywords, ) @@ -47,5 +50,7 @@ class WriteBookToMemory(WriteSheetToMemory): def write_data(self, book): self._renderer.render_book_to_stream( - self._content, book, **self._keywords, + self._content, + book, + **self._keywords, ) diff --git a/pyexcel/plugins/sources/params.py b/pyexcel/plugins/sources/params.py index 439b22fa..9ec389b5 100644 --- a/pyexcel/plugins/sources/params.py +++ b/pyexcel/plugins/sources/params.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.params - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.params +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Local magic workds +Local magic workds - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + # keywords MEMORY = "memory" FILE_TYPE = "file_type" diff --git a/pyexcel/plugins/sources/pydata/arraysource.py b/pyexcel/plugins/sources/pydata/arraysource.py index f25fad5d..9c7515f4 100644 --- a/pyexcel/plugins/sources/pydata/arraysource.py +++ b/pyexcel/plugins/sources/pydata/arraysource.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.pydata.arraysource - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.pydata.arraysource +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of array source +Representation of array source - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource, MemorySourceMixin from pyexcel.constants import DEFAULT_SHEET_NAME from pyexcel.plugins.sources import params diff --git a/pyexcel/plugins/sources/pydata/bookdict.py b/pyexcel/plugins/sources/pydata/bookdict.py index c966c241..7eee5af6 100644 --- a/pyexcel/plugins/sources/pydata/bookdict.py +++ b/pyexcel/plugins/sources/pydata/bookdict.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.pydata.bookdictsource - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.pydata.bookdictsource +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of book dict source +Representation of book dict source - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource, MemorySourceMixin from pyexcel._compact import PY2, OrderedDict from pyexcel.plugins.sources import params diff --git a/pyexcel/plugins/sources/pydata/common.py b/pyexcel/plugins/sources/pydata/common.py index 9c30a60f..ad05184b 100644 --- a/pyexcel/plugins/sources/pydata/common.py +++ b/pyexcel/plugins/sources/pydata/common.py @@ -1,19 +1,20 @@ """ - pyexcel.plugins.sources.pydata - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.pydata +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of array, dict, records and book dict sources +Representation of array, dict, records and book dict sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel import constants from pyexcel._compact import PY2, OrderedDict, zip_longest from pyexcel_io.sheet import SheetReader -class _FakeIO(): +class _FakeIO: """emulates a stream object""" def __init__(self): @@ -91,7 +92,8 @@ def row_iterator(self): if isinstance(self._native_sheet[keys[0]], list): sorted_values = (self._native_sheet[key] for key in keys) for row in zip_longest( - *sorted_values, fillvalue=constants.DEFAULT_NA, + *sorted_values, + fillvalue=constants.DEFAULT_NA, ): yield row else: diff --git a/pyexcel/plugins/sources/pydata/dictsource.py b/pyexcel/plugins/sources/pydata/dictsource.py index 8ee278bc..48dac3c2 100644 --- a/pyexcel/plugins/sources/pydata/dictsource.py +++ b/pyexcel/plugins/sources/pydata/dictsource.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.pydata.dictsource - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.pydata.dictsource +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of dict sources +Representation of dict sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource, MemorySourceMixin from pyexcel.constants import DEFAULT_SHEET_NAME from pyexcel.plugins.sources import params @@ -20,7 +21,11 @@ class DictSource(AbstractSource, MemorySourceMixin): """ def __init__( - self, adict, with_keys=True, sheet_name=DEFAULT_SHEET_NAME, **keywords, + self, + adict, + with_keys=True, + sheet_name=DEFAULT_SHEET_NAME, + **keywords, ): self.__adict = adict self.__with_keys = with_keys @@ -30,7 +35,9 @@ def __init__( def get_data(self): dict_reader = DictReader( - self.__adict, with_keys=self.__with_keys, **self._keywords, + self.__adict, + with_keys=self.__with_keys, + **self._keywords, ) return {self.__sheet_name: dict_reader.to_array()} diff --git a/pyexcel/plugins/sources/pydata/records.py b/pyexcel/plugins/sources/pydata/records.py index c55640eb..9a2242e1 100644 --- a/pyexcel/plugins/sources/pydata/records.py +++ b/pyexcel/plugins/sources/pydata/records.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.pydata.recordssource - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.pydata.recordssource +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of records source +Representation of records source - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource, MemorySourceMixin from pyexcel.constants import DEFAULT_SHEET_NAME from pyexcel.plugins.sources import params diff --git a/pyexcel/plugins/sources/querysets.py b/pyexcel/plugins/sources/querysets.py index d1688a8c..eaeb6786 100644 --- a/pyexcel/plugins/sources/querysets.py +++ b/pyexcel/plugins/sources/querysets.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.querysets - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.querysets +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of querysets +Representation of querysets - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel import constants from pyexcel.source import AbstractSource diff --git a/pyexcel/plugins/sources/sheet_stream_source.py b/pyexcel/plugins/sources/sheet_stream_source.py index 2ae77c9d..1d089866 100644 --- a/pyexcel/plugins/sources/sheet_stream_source.py +++ b/pyexcel/plugins/sources/sheet_stream_source.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.sheet_stream_source - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.sheet_stream_source +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of array source +Representation of array source - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel.source import AbstractSource, MemorySourceMixin from pyexcel.plugins.sources import params diff --git a/pyexcel/plugins/sources/sqlalchemy.py b/pyexcel/plugins/sources/sqlalchemy.py index e6c3af7c..e1ca1279 100644 --- a/pyexcel/plugins/sources/sqlalchemy.py +++ b/pyexcel/plugins/sources/sqlalchemy.py @@ -1,12 +1,13 @@ """ - pyexcel.plugins.sources.sqlalchemy - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.plugins.sources.sqlalchemy +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Representation of sqlalchemy sources +Representation of sqlalchemy sources - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel_io.constants import DB_SQL from .db_sources import BookDbSource, SheetDbSource @@ -17,7 +18,12 @@ class SheetSQLAlchemySource(SheetDbSource): """ def __init__( - self, session, table, export_columns=None, sheet_name=None, **keywords, + self, + session, + table, + export_columns=None, + sheet_name=None, + **keywords, ): self.__session = session self.__table = table diff --git a/pyexcel/renderer.py b/pyexcel/renderer.py index d67bf289..204276f4 100644 --- a/pyexcel/renderer.py +++ b/pyexcel/renderer.py @@ -1,16 +1,17 @@ """ - pyexcel.renderer - ~~~~~~~~~~~~~~~~~~~ +pyexcel.renderer +~~~~~~~~~~~~~~~~~~~ - Renders pyexcel.Book and pyexcel.Sheet to any format +Renders pyexcel.Book and pyexcel.Sheet to any format - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel import _compact as compact -class AbstractRenderer(): +class AbstractRenderer: """ Close some functions that will not be used """ @@ -79,22 +80,35 @@ def get_io(self): return compact.StringIO() def render_sheet_to_file( - self, file_name, sheet, write_title=True, **keywords, + self, + file_name, + sheet, + write_title=True, + **keywords, ): self.set_write_title(write_title) + file_name = compact.get_string_file_name(file_name) with open(file_name, self.WRITE_FLAG, encoding="utf-8") as outfile: self.set_output_stream(outfile) self.render_sheet(sheet, **keywords) def render_sheet_to_stream( - self, file_stream, sheet, write_title=True, **keywords, + self, + file_stream, + sheet, + write_title=True, + **keywords, ): self.set_write_title(write_title) self.set_output_stream(file_stream) self.render_sheet(sheet, **keywords) def render_book_to_file( - self, file_name, book, write_title=True, **keywords, + self, + file_name, + book, + write_title=True, + **keywords, ): self.set_write_title(write_title) with open(file_name, self.WRITE_FLAG, encoding="utf-8") as outfile: @@ -102,7 +116,11 @@ def render_book_to_file( self.render_book(book, **keywords) def render_book_to_stream( - self, file_stream, book, write_title=True, **keywords, + self, + file_stream, + book, + write_title=True, + **keywords, ): self.set_write_title(write_title) self.set_output_stream(file_stream) diff --git a/pyexcel/sheet.py b/pyexcel/sheet.py index a91f0cda..1a180a42 100644 --- a/pyexcel/sheet.py +++ b/pyexcel/sheet.py @@ -1,12 +1,13 @@ """ - pyexcel.sheet - ~~~~~~~~~~~~~~~~~~~~~ +pyexcel.sheet +~~~~~~~~~~~~~~~~~~~~~ - Building on top of matrix, adding named columns and rows support +Building on top of matrix, adding named columns and rows support - :copyright: (c) 2014-2025 by Onni Software Ltd. - :license: New BSD License, see LICENSE for more details +:copyright: (c) 2014-2025 by Onni Software Ltd. +:license: New BSD License, see LICENSE for more details """ + import copy from collections import defaultdict @@ -613,7 +614,7 @@ def __len__(self): return self.number_of_rows() -class _RepresentedString(): +class _RepresentedString: """present in text""" def __init__(self, text): diff --git a/pyexcel/source.py b/pyexcel/source.py index 49dd3582..f9848da9 100644 --- a/pyexcel/source.py +++ b/pyexcel/source.py @@ -1,16 +1,17 @@ """ - pyexcel.source - ~~~~~~~~~~~~~~~~~~~~~~~~ +pyexcel.source +~~~~~~~~~~~~~~~~~~~~~~~~ - Generic data source definition +Generic data source definition - :copyright: (c) 2015-2022 by Onni Software Ltd. - :license: New BSD License +:copyright: (c) 2015-2025 by Onni Software Ltd. +:license: New BSD License """ + from pyexcel import constants -class AbstractSource(): +class AbstractSource: """ Define a data source for use with the signature functions @@ -52,7 +53,7 @@ def get_data(self): raise NotImplementedError("") -class MemorySourceMixin(): +class MemorySourceMixin: """A memory source should an internal memory stream And it is desirable to get its internal stream diff --git a/setup.py b/setup.py index aeafdefb..3e6a1d34 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ NAME = "pyexcel" AUTHOR = "C.W." -VERSION = "0.7.2" +VERSION = "0.7.3" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" DESCRIPTION = ( @@ -40,7 +40,7 @@ "data in different excel formats" ) URL = "https://github.com/pyexcel/pyexcel" -DOWNLOAD_URL = "%s/archive/0.7.2.tar.gz" % URL +DOWNLOAD_URL = "%s/archive/0.7.3.tar.gz" % URL FILES = ["README.rst", "CONTRIBUTORS.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", @@ -88,8 +88,8 @@ PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) HERE = os.path.abspath(os.path.dirname(__file__)) -GS_COMMAND = ("gease pyexcel v0.7.2 " + - "Find 0.7.2 in changelog for more details") +GS_COMMAND = ("gease pyexcel v0.7.3 " + + "Find 0.7.3 in changelog for more details") NO_GS_MESSAGE = ("Automatic github release is disabled. " + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 197da603..0f797c3c 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -234,7 +234,9 @@ def test_issue_76(): tsv_stream.write("1\t2\t3\t4\n") tsv_stream.seek(0) sheet = p.get_sheet( - file_stream=tsv_stream, file_type="csv", delimiter="\t", + file_stream=tsv_stream, + file_type="csv", + delimiter="\t", ) data = [[1, 2, 3, 4], [1, 2, 3, 4]] eq_(sheet.array, data) @@ -544,7 +546,8 @@ def test_issue_241(): from pyexcel import get_book, merge_all_to_a_book merge_all_to_a_book( - glob.glob("tests/fixtures/issue_241/*.csv"), "issue_241.xlsx", + glob.glob("tests/fixtures/issue_241/*.csv"), + "issue_241.xlsx", ) book = get_book(file_name="issue_241.xlsx") book.sort_sheets() diff --git a/tests/test_cookbook.py b/tests/test_cookbook.py index 58b28fd7..dd2a6df0 100644 --- a/tests/test_cookbook.py +++ b/tests/test_cookbook.py @@ -31,7 +31,9 @@ def test_split_a_book_2(self): def test_extract_a_book(self): pe.cookbook.extract_a_sheet_from_a_book( - self.testfile4, "Sheet1", "extracted.csv", + self.testfile4, + "Sheet1", + "extracted.csv", ) assert os.path.exists("Sheet1_extracted.csv") diff --git a/tests/test_examples.py b/tests/test_examples.py index b5f948dc..55ca7021 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -1,8 +1,8 @@ import os +import imp import sys import glob import json -import imp from unittest import TestCase import pyexcel as pe @@ -51,7 +51,9 @@ class x(TestCase): def setUp(self): app = load_from_file( - os.path.join("examples", "memoryfile"), "pyexcel_server.py", "app", + os.path.join("examples", "memoryfile"), + "pyexcel_server.py", + "app", ) self.app = app.test_client() @@ -82,7 +84,8 @@ def test_upload(self): # for the same reason, python 3 socket receve bytes # to convert bytes to str is to do a decode self.assertEqual( - json.loads(response.data.decode("utf-8")), expected, + json.loads(response.data.decode("utf-8")), + expected, ) def test_download(self): diff --git a/tests/test_exploitation.py b/tests/test_exploitation.py index a5eb77d5..9c4d445f 100644 --- a/tests/test_exploitation.py +++ b/tests/test_exploitation.py @@ -164,7 +164,9 @@ def test_number_of_columns(self): class TestNonUniformCSVFile: def setUp(self): self.testfile = os.path.join( - "tests", "fixtures", "non-uniform-rows.csv", + "tests", + "fixtures", + "non-uniform-rows.csv", ) def test_number_of_columns(self): @@ -185,10 +187,14 @@ def test_number_of_columns(self): class TestMergeFiles: def test_merge_two_csv_files(self): file1 = os.path.join( - "tests", "fixtures", "test_cook_book_merge_numbers.csv", + "tests", + "fixtures", + "test_cook_book_merge_numbers.csv", ) file2 = os.path.join( - "tests", "fixtures", "test_cook_book_merge_alphabets.csv", + "tests", + "fixtures", + "test_cook_book_merge_alphabets.csv", ) file_list = [file1, file2] pe.cookbook.merge_files(file_list) @@ -202,10 +208,14 @@ def test_merge_two_csv_files(self): def test_merge_two_csv_files_2(self): file1 = os.path.join( - "tests", "fixtures", "test_cook_book_merge_numbers_2.csv", + "tests", + "fixtures", + "test_cook_book_merge_numbers_2.csv", ) file2 = os.path.join( - "tests", "fixtures", "test_cook_book_merge_alphabets_2.csv", + "tests", + "fixtures", + "test_cook_book_merge_alphabets_2.csv", ) file_list = [file1, file2] pe.cookbook.merge_files(file_list) diff --git a/tests/test_fileio.py b/tests/test_fileio.py index 31ca76e7..86fff10b 100644 --- a/tests/test_fileio.py +++ b/tests/test_fileio.py @@ -1,5 +1,6 @@ import os from textwrap import dedent +from pathlib import Path import pyexcel as pe @@ -17,7 +18,24 @@ def test_write_texttable(): +---+---+""", ).strip("\n") pe.save_as(array=content, dest_file_name=test_file) - with open(test_file, "r", encoding='utf-8') as f: + with open(test_file, "r", encoding="utf-8") as f: + written = f.read() + eq_(written, expected) + os.unlink(test_file) + + +def test_write_texttable_using_pathlib(): + content = [[1, 2]] + test_file = "test.texttable" + expected = dedent( + """ + pyexcel_sheet1: + +---+---+ + | 1 | 2 | + +---+---+""", + ).strip("\n") + pe.save_as(array=content, dest_file_name=Path(test_file)) + with open(test_file, "r", encoding="utf-8") as f: written = f.read() eq_(written, expected) os.unlink(test_file) @@ -34,7 +52,24 @@ def test_write_texttable_book(): +---+---+""", ).strip("\n") pe.save_book_as(bookdict=content, dest_file_name=test_file) - with open(test_file, "r", encoding='utf-8') as f: + with open(test_file, "r", encoding="utf-8") as f: + written = f.read() + eq_(written, expected) + os.unlink(test_file) + + +def test_write_texttable_book_using_pathlib(): + content = {"Sheet": [[1, 2]]} + test_file = "test.texttable" + expected = dedent( + """ + Sheet: + +---+---+ + | 1 | 2 | + +---+---+""", + ).strip("\n") + pe.save_book_as(bookdict=content, dest_file_name=Path(test_file)) + with open(test_file, "r", encoding="utf-8") as f: written = f.read() eq_(written, expected) os.unlink(test_file) diff --git a/tests/test_gabagecollector.py b/tests/test_gabagecollector.py index 41c6f6ad..4263cc6a 100644 --- a/tests/test_gabagecollector.py +++ b/tests/test_gabagecollector.py @@ -19,8 +19,9 @@ def test_gc(): def test_gc_custom(): gc.free_resources() - f = open(os.path.join("tests", "fixtures", - "bug_01.csv"), "r", encoding="utf-8") + f = open( + os.path.join("tests", "fixtures", "bug_01.csv"), "r", encoding="utf-8" + ) gc.append(f) eq_(len(gc.GARBAGE), 1) gc.free_resources() diff --git a/tests/test_pathlib_path.py b/tests/test_pathlib_path.py new file mode 100644 index 00000000..4c8c78c1 --- /dev/null +++ b/tests/test_pathlib_path.py @@ -0,0 +1,29 @@ +import os +from pathlib import Path + +import pyexcel as pe + +from nose.tools import eq_ + + +class TestPath: + def setUp(self): + self.test_data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] + + def tearDown(self): + pe.free_resources() + + def test_get_array_from_file(self): + sheet = pe.Sheet(self.test_data) + testfile = "testfile.xls" + sheet.save_as(testfile) + result = pe.iget_array(file_name=Path(testfile)) + eq_(list(result), self.test_data) + os.unlink(testfile) + + def test_get_sheet_from_file(self): + sheet = pe.Sheet(self.test_data) + testfile = "testfile.xls" + sheet.save_as(testfile) + pe.get_sheet(file_name=Path(testfile)) + os.unlink(testfile) diff --git a/tests/test_reader.py b/tests/test_reader.py index 354d07fb..4563a8ed 100644 --- a/tests/test_reader.py +++ b/tests/test_reader.py @@ -142,11 +142,13 @@ def setUp(self): array = [i + 1, i + 2, i + 3, i + 4] table.append(array) p.save_as( - dest_file_name=self.testfile, dest_delimiter=":", array=table, + dest_file_name=self.testfile, + dest_delimiter=":", + array=table, ) def test_delimiter(self): - with open(self.testfile, encoding='utf-8') as test_file: + with open(self.testfile, encoding="utf-8") as test_file: content = "1:2:3:45:6:7:89:10:11:12" expected = "" for line in test_file: diff --git a/tests/test_sheet_stream.py b/tests/test_sheet_stream.py index 066c1f3e..fbbefaf9 100644 --- a/tests/test_sheet_stream.py +++ b/tests/test_sheet_stream.py @@ -13,7 +13,9 @@ def test_save_to(): io = manager.get_io(file_type) g = (i for i in [[1, 2], [3, 4]]) ss = WriteSheetToMemory( - file_type=file_type, file_stream=io, lineterminator="\n", + file_type=file_type, + file_stream=io, + lineterminator="\n", ) sheet_stream = SheetStream("test", g) ss.write_data(sheet_stream) diff --git a/tests/test_signature_fuction.py b/tests/test_signature_fuction.py index ded5bfa7..ac262753 100644 --- a/tests/test_signature_fuction.py +++ b/tests/test_signature_fuction.py @@ -1,5 +1,6 @@ import os from types import GeneratorType +from pathlib import Path import pyexcel as pe @@ -112,6 +113,12 @@ def test_get_sheet_from_txt(self): expected = [[1, 2, 3]] eq_(sheet.to_array(), expected) + def test_get_sheet_from_txt_via_pathlib(self): + test_file = os.path.join("tests", "fixtures", "force_type.txt") + sheet = pe.get_sheet(file_name=Path(test_file), force_file_type="csv") + expected = [[1, 2, 3]] + eq_(sheet.to_array(), expected) + class TestGetArray: def setUp(self): @@ -190,6 +197,15 @@ def test_get_dict_from_file(self): assert result == {"X": [1, 4], "Y": [2, 5], "Z": [3, 6]} os.unlink(testfile) + def test_get_dict_from_file_via_path(self): + data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] + sheet = pe.Sheet(data) + testfile = "testfile.xls" + sheet.save_as(testfile) + result = pe.get_dict(file_name=Path(testfile)) + assert result == {"X": [1, 4], "Y": [2, 5], "Z": [3, 6]} + os.unlink(testfile) + def test_get_dict_from_memory(self): data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] content = pe.save_as(dest_file_type="xls", array=data) @@ -223,11 +239,21 @@ def test_get_records_from_file(self): eq_(result, [{"X": 1, "Y": 2, "Z": 3}, {"X": 4, "Y": 5, "Z": 6}]) os.unlink(testfile) + def test_get_records_from_file_path(self): + data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] + sheet = pe.Sheet(data) + testfile = "testfile.xls" + sheet.save_as(testfile) + result = pe.get_records(file_name=Path(testfile)) + eq_(result, [{"X": 1, "Y": 2, "Z": 3}, {"X": 4, "Y": 5, "Z": 6}]) + os.unlink(testfile) + def test_get_records_from_memory(self): data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] content = pe.save_as(dest_file_type="xls", array=data) records = pe.get_records( - file_content=content.getvalue(), file_type="xls", + file_content=content.getvalue(), + file_type="xls", ) eq_(records, [{"X": 1, "Y": 2, "Z": 3}, {"X": 4, "Y": 5, "Z": 6}]) @@ -260,29 +286,38 @@ def test_get_records_from_file(self): eq_(list(result), [{"X": 1, "Y": 2, "Z": 3}, {"X": 4, "Y": 5, "Z": 6}]) os.unlink(testfile) + def test_get_records_from_file_path(self): + data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] + sheet = pe.Sheet(data) + testfile = "testfile.xls" + sheet.save_as(testfile) + result = pe.iget_records(file_name=Path(testfile)) + eq_(list(result), [{"X": 1, "Y": 2, "Z": 3}, {"X": 4, "Y": 5, "Z": 6}]) + os.unlink(testfile) + def test_get_records_from_memory(self): data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] content = pe.save_as(dest_file_type="xls", array=data) records = pe.get_records( - file_content=content.getvalue(), file_type="xls", + file_content=content.getvalue(), + file_type="xls", ) eq_( - list(records), [{"X": 1, "Y": 2, "Z": 3}, - {"X": 4, "Y": 5, "Z": 6}], + list(records), + [{"X": 1, "Y": 2, "Z": 3}, {"X": 4, "Y": 5, "Z": 6}], ) def test_get_records_from_array(self): data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] result = pe.iget_records(array=data) - eq_(list(result), [{"X": 1, "Y": 2, "Z": 3}, - {"X": 4, "Y": 5, "Z": 6}]) + eq_(list(result), [{"X": 1, "Y": 2, "Z": 3}, {"X": 4, "Y": 5, "Z": 6}]) def test_get_records_from_irregular_array(self): data = [["X", "Y", "Z"], [1, 2, 3], [4, 5]] result = pe.iget_records(array=data) eq_( - list(result), [{"X": 1, "Y": 2, "Z": 3}, - {"X": 4, "Y": 5, "Z": ""}], + list(result), + [{"X": 1, "Y": 2, "Z": 3}, {"X": 4, "Y": 5, "Z": ""}], ) def test_get_records_from_dict(self): @@ -317,7 +352,9 @@ def test_save_a_dict2(self): sheet = pe.get_sheet(adict=adict, name_columns_by_row=0) sheet.save_to_database(self.session, Signature) result = pe.get_dict( - session=self.session, table=Signature, name_columns_by_row=0, + session=self.session, + table=Signature, + name_columns_by_row=0, ) print(result) assert adict == result @@ -376,7 +413,9 @@ def make_signature(row): return Signature(X=row["X"], Y=row["Y"], Z=row["Z"]) sheet.save_to_database( - self.session, Signature, initializer=make_signature, + self.session, + Signature, + initializer=make_signature, ) result = pe.get_dict(session=self.session, table=Signature) assert result == {"X": [1, 4], "Y": [2, 5], "Z": [3, 6]} @@ -478,7 +517,8 @@ def test_get_records_from_sql(self): def test_get_book_from_sql(self): book_dict = pe.get_book_dict( - session=Session(), tables=[Signature, Signature2], + session=Session(), + tables=[Signature, Signature2], ) expected = OrderedDict() expected.update({"signature": [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]]}) @@ -519,7 +559,8 @@ def test_save_book_to_memory_from_sql(self): tables=[Signature, Signature2], ) book_dict = pe.get_book_dict( - file_content=test_file.getvalue(), file_type="xls", + file_content=test_file.getvalue(), + file_type="xls", ) expected = OrderedDict() expected.update({"signature": [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]]}) @@ -545,6 +586,16 @@ def test_get_book_from_file(self): assert book2.to_dict() == content os.unlink(test_file) + def test_get_book_from_file_path(self): + test_file = "test_get_book.xls" + content = _produce_ordered_dict() + + book = pe.Book(content) + book.save_as(test_file) + book2 = pe.get_book(file_name=Path(test_file)) + assert book2.to_dict() == content + os.unlink(test_file) + def test_get_book_from_memory(self): content = _produce_ordered_dict() io = pe.save_book_as(dest_file_type="xls", bookdict=content) @@ -612,6 +663,18 @@ def test_get_book_from_file(self): eq_(book3.to_dict(), content) os.unlink(test_file) + def test_get_book_from_file_path(self): + test_file = "test_get_book.xls" + content = _produce_ordered_dict() + + book = pe.Book(content) + book.save_as(test_file) + book_stream = pe.iget_book(file_name=Path(test_file)) + assert book_stream.to_dict() != content + book3 = pe.Book(book_stream.to_dict()) + eq_(book3.to_dict(), content) + os.unlink(test_file) + def test_get_book_from_memory(self): content = _produce_ordered_dict() io = pe.save_book_as(dest_file_type="xls", bookdict=content) @@ -685,12 +748,24 @@ def test_look_at_sheet_names_decides_to_read_seond_one(self): class TestSaveAs: def test_force_file_type(self): pe.save_as( - array=[[1, 2]], dest_file_name="a.txt", dest_force_file_type="csv", + array=[[1, 2]], + dest_file_name="a.txt", + dest_force_file_type="csv", ) actual = pe.get_array(file_name="a.txt", force_file_type="csv") eq_([[1, 2]], actual) os.unlink("a.txt") + def test_force_file_type_with_pathlib(self): + pe.save_as( + array=[[1, 2]], + dest_file_name="a.txt", + dest_force_file_type="csv", + ) + actual = pe.get_array(file_name=Path("a.txt"), force_file_type="csv") + eq_([[1, 2]], actual) + os.unlink("a.txt") + def test_force_file_type_for_save_book_as(self): pe.save_as( bookdict={"sheet1": [[1, 2]]}, @@ -714,6 +789,19 @@ def test_save_file_as_another_one(self): os.unlink(testfile) os.unlink(testfile2) + def test_save_file_as_another_one_using_path(self): + data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] + sheet = pe.Sheet(data) + testfile = "testfile.xls" + testfile2 = "testfile2.csv" + sheet.save_as(testfile) + pe.save_as(file_name=Path(testfile), dest_file_name=Path(testfile2)) + sheet = pe.get_sheet(file_name=testfile2) + sheet.format(int) + eq_(sheet.to_array(), data) + os.unlink(testfile) + os.unlink(testfile2) + def test_save_as_and_append_colnames(self): data = [[1, 2, 3], [4, 5, 6]] sheet = pe.Sheet(data) @@ -745,6 +833,18 @@ def test_save_file_as_another_one(self): os.unlink(testfile) os.unlink(testfile2) + def test_save_file_as_another_one_using_pathlib(self): + data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] + sheet = pe.Sheet(data) + testfile = "testfile.xls" + testfile2 = "testfile2.csv" + sheet.save_as(testfile) + pe.isave_as(file_name=Path(testfile), dest_file_name=Path(testfile2)) + sheet = pe.get_sheet(file_name=testfile2) + eq_(sheet.to_array(), data) + os.unlink(testfile) + os.unlink(testfile2) + @raises(Exception) def test_save_as_invalid_params(self): data = [["X", "Y", "Z"], [1, 2, 3], [4, 5, 6]] diff --git a/tests/test_sources.py b/tests/test_sources.py index a0cbe442..4f4ea4c3 100644 --- a/tests/test_sources.py +++ b/tests/test_sources.py @@ -43,6 +43,9 @@ def can_i_handle(self, action, file_type): info = CustomInfo("apth") expected = info.is_my_business( - "READ", test="unit", file_name="unknow.file", force_file_type="csv", + "READ", + test="unit", + file_name="unknow.file", + force_file_type="csv", ) assert expected diff --git a/tests/test_sql.py b/tests/test_sql.py index e7fd64a3..0a5e4f37 100644 --- a/tests/test_sql.py +++ b/tests/test_sql.py @@ -13,13 +13,17 @@ def setUp(self): Base.metadata.drop_all(engine) Base.metadata.create_all(engine) p1 = Pyexcel( - id=0, name="Adam", weight=11.25, + id=0, + name="Adam", + weight=11.25, birth=datetime.date(2014, 11, 11), ) session = Session() session.add(p1) p1 = Pyexcel( - id=1, name="Smith", weight=12.25, + id=1, + name="Smith", + weight=12.25, birth=datetime.date(2014, 11, 12), ) session.add(p1)