diff --git a/.isort.cfg b/.isort.cfg index f5332c5..9d0ef8b 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,6 +1,6 @@ [settings] line_length=79 -known_first_party=lml, pyexcel, odfpy +known_first_party=lml, pyexcel_io, odf known_third_party=nose indent=' ' multi_line_output=3 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9ef21e4..fc86868 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,13 @@ Change log ================================================================================ +0.6.0 - 2020 +-------------------------------------------------------------------------------- + +**added** + +#. new style reader and writer plugins. works with pyexcel-io v0.6.0 + 0.5.6 - 19.03.2019 -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index d15f3f6..8bb7c9d 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-ods organisation: pyexcel releases: +- changes: + - action: added + details: + - 'new style reader and writer plugins. works with pyexcel-io v0.6.0' + date: 2020 + version: 0.6.0 - changes: - action: added details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 67e8ad3..664ab82 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,7 +25,7 @@ project = 'pyexcel-ods' copyright = '2015-2020 Onni Software Ltd.' author = 'chfw' # The short X.Y version -version = '0.5.6' +version = '0.6.0' # The full version, including alpha/beta/rc tags release = '0.5.6' diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index e8235c8..94a0235 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.5.6 -current_version: 0.5.6 +version: 0.6.0 +current_version: 0.6.0 release: 0.5.6 copyright_year: 2015-2020 file_type: ods diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index 60fd4f2..63b02a0 100644 --- a/pyexcel_ods/__init__.py +++ b/pyexcel_ods/__init__.py @@ -2,7 +2,7 @@ pyexcel_ods ~~~~~~~~~~~~~~~~~~~ The lower level ods file format handler using odfpy - :copyright: (c) 2015-2017 by Onni Software Ltd & its contributors + :copyright: (c) 2015-2020 by Onni Software Ltd & its contributors :license: New BSD License """ @@ -13,15 +13,23 @@ from pyexcel_io.io import store_data as write_data # this line has to be place above all else # because of dynamic import -from pyexcel_io.plugins import IOPluginInfoChain +from pyexcel_io.plugins import IOPluginInfoChain, IOPluginInfoChainV2 __FILE_TYPE__ = "ods" -IOPluginInfoChain(__name__).add_a_reader( +IOPluginInfoChain(__name__) +IOPluginInfoChainV2(__name__).add_a_reader( relative_plugin_class_path="odsr.ODSBook", + locations=["file", "memory"], + file_types=[__FILE_TYPE__], + stream_type="binary", +).add_a_reader( + relative_plugin_class_path="odsr.ODSBookInContent", + locations=["content"], file_types=[__FILE_TYPE__], stream_type="binary", ).add_a_writer( relative_plugin_class_path="odsw.ODSWriter", + locations=["file", "memory"], file_types=[__FILE_TYPE__], stream_type="binary", ) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 5cd5113..ecc4aa7 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -4,7 +4,7 @@ ods reader - :copyright: (c) 2014-2017 by Onni Software Ltd. + :copyright: (c) 2014-2020 by Onni Software Ltd. :license: New BSD License, see LICENSE for more details """ # Copyright 2011 Marco Conti @@ -20,6 +20,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from io import BytesIO import pyexcel_io.service as service from odf.text import P @@ -28,17 +29,17 @@ from odf.table import Table, TableRow, TableCell # Thanks to grt for the fixes from odf.teletype import extractText from odf.namespaces import OFFICENS -from pyexcel_io.book import BookReader from odf.opendocument import load -from pyexcel_io.sheet import SheetReader -from pyexcel_io._compact import OrderedDict +from pyexcel_io.plugin_api.abstract_sheet import ISheet +from pyexcel_io.plugin_api.abstract_reader import IReader -class ODSSheet(SheetReader): +class ODSSheet(ISheet): """native ods sheet""" def __init__(self, sheet, auto_detect_int=True, **keywords): - SheetReader.__init__(self, sheet, **keywords) + self._native_sheet = sheet + self._keywords = keywords self.__auto_detect_int = auto_detect_int @property @@ -99,62 +100,38 @@ class ODSSheet(SheetReader): return "\n".join(text_content) -class ODSBook(BookReader): +class ODSBook(IReader): """read ods book""" - def open(self, file_name, **keywords): - """open ods file""" - BookReader.open(self, file_name, **keywords) - self._load_from_file() - - def open_stream(self, file_stream, **keywords): - """open ods file stream""" - BookReader.open_stream(self, file_stream, **keywords) - self._load_from_memory() - - def read_sheet_by_name(self, sheet_name): - """read a named sheet""" - tables = self._native_book.spreadsheet.getElementsByType(Table) - rets = [ - table - for table in tables - if table.getAttribute("name") == sheet_name + def __init__(self, file_alike_object, _, **keywords): + self._native_book = load(file_alike_object) + self._keywords = keywords + self.content_array = [ + NameObject(table.getAttribute("name"), table) + for table in self._native_book.spreadsheet.getElementsByType(Table) ] - if len(rets) == 0: - raise ValueError("%s cannot be found" % sheet_name) - else: - return self.read_sheet(rets[0]) - def read_sheet_by_index(self, sheet_index): + def read_sheet(self, sheet_index): """read a sheet at a specified index""" - tables = self._native_book.spreadsheet.getElementsByType(Table) - length = len(tables) - if sheet_index < length: - return self.read_sheet(tables[sheet_index]) - else: - raise IndexError( - "Index %d of out bound %d" % (sheet_index, length) - ) - - def read_all(self): - """read all sheets""" - result = OrderedDict() - for sheet in self._native_book.spreadsheet.getElementsByType(Table): - ods_sheet = ODSSheet(sheet, **self._keywords) - result[ods_sheet.name] = ods_sheet.to_array() - - return result - - def read_sheet(self, native_sheet): - """read one native sheet""" - sheet = ODSSheet(native_sheet, **self._keywords) - return {sheet.name: sheet.to_array()} + table = self.content_array[sheet_index].sheet + sheet = ODSSheet(table, **self._keywords) + return sheet def close(self): self._native_book = None - def _load_from_memory(self): - self._native_book = load(self._file_stream) - def _load_from_file(self): - self._native_book = load(self._file_name) +class ODSBookInContent(ODSBook): + """ + Open xlsx as read only mode + """ + + def __init__(self, file_content, file_type, **keywords): + io = BytesIO(file_content) + super().__init__(io, file_type, **keywords) + + +class NameObject(object): + def __init__(self, name, sheet): + self.name = name + self.sheet = sheet diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index 429bd42..b13e3f6 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -4,7 +4,7 @@ ods writer - :copyright: (c) 2014-2017 by Onni Software Ltd. + :copyright: (c) 2014-2020 by Onni Software Ltd. :license: New BSD License, see LICENSE for more details """ import sys @@ -13,27 +13,23 @@ import pyexcel_io.service as converter from odf.text import P from odf.table import Table, TableRow, TableCell from odf.namespaces import OFFICENS -from pyexcel_io.book import BookWriter from odf.opendocument import OpenDocumentSpreadsheet -from pyexcel_io.sheet import SheetWriter +from pyexcel_io.plugin_api.abstract_sheet import ISheetWriter +from pyexcel_io.plugin_api.abstract_writer import IWriter PY2 = sys.version_info[0] == 2 PY27_BELOW = PY2 and sys.version_info[1] < 7 -class ODSSheetWriter(SheetWriter): +class ODSSheetWriter(ISheetWriter): """ ODS sheet writer """ - def set_sheet_name(self, name): - """initialize the native table""" - self._native_sheet = Table(name=name) - - def set_size(self, size): - """not used in this class but used in ods3""" - pass + def __init__(self, ods_book, ods_sheet, sheet_name, **keywords): + self._native_book = ods_book + self._native_sheet = Table(name=sheet_name) def write_cell(self, row, cell): """write a native cell""" @@ -77,14 +73,14 @@ class ODSSheetWriter(SheetWriter): self._native_book.spreadsheet.addElement(self._native_sheet) -class ODSWriter(BookWriter): +class ODSWriter(IWriter): """ open document spreadsheet writer """ - def __init__(self): - BookWriter.__init__(self) + def __init__(self, file_alike_object, file_type, **keywords): + self._file_alike_object = file_alike_object self._native_book = OpenDocumentSpreadsheet() def create_sheet(self, name): diff --git a/setup.py b/setup.py index 4a2482c..d2f1740 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ except (ValueError, UnicodeError, locale.Error): NAME = "pyexcel-ods" AUTHOR = "chfw" -VERSION = "0.5.6" +VERSION = "0.6.0" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" DESCRIPTION = ( diff --git a/tests/test_ods_reader.py b/tests/test_ods_reader.py index 69bb030..384da20 100644 --- a/tests/test_ods_reader.py +++ b/tests/test_ods_reader.py @@ -7,8 +7,9 @@ from pyexcel_ods.odsw import ODSWriter class TestODSReader(ODSCellTypes): def setUp(self): - r = ODSBook() - r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) + r = ODSBook( + os.path.join("tests", "fixtures", "ods_formats.ods"), "ods" + ) self.data = r.read_all() for key in self.data.keys(): self.data[key] = list(self.data[key]) @@ -17,16 +18,15 @@ class TestODSReader(ODSCellTypes): class TestODSWriter(ODSCellTypes): def setUp(self): - r = ODSBook() - r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) + r = ODSBook( + os.path.join("tests", "fixtures", "ods_formats.ods"), "ods" + ) self.data1 = r.read_all() self.testfile = "odswriter.ods" - w = ODSWriter() - w.open(self.testfile) + w = ODSWriter(self.testfile, "ods") w.write(self.data1) w.close() - r2 = ODSBook() - r2.open(self.testfile) + r2 = ODSBook(self.testfile, "ods") self.data = r2.read_all() for key in self.data.keys(): self.data[key] = list(self.data[key]) diff --git a/tests/test_writer.py b/tests/test_writer.py index ae3a300..73c32aa 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -13,12 +13,10 @@ class TestNativeODSWriter: "Sheet3": [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]], } self.testfile = "writer.ods" - writer = Writer() - writer.open(self.testfile) + writer = Writer(self.testfile, "ods") writer.write(self.content) writer.close() - reader = Reader() - reader.open(self.testfile) + reader = Reader(self.testfile, "ods") content = reader.read_all() for key in content.keys(): content[key] = list(content[key])