New style reader writer (#39)

* 🎉 new style ods reader written

* This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst

*  new style ods writer

Co-authored-by: chfw <chfw@users.noreply.github.com>
This commit is contained in:
jaska 2020-10-03 14:27:56 +01:00 committed by GitHub
parent 07ee703b59
commit 24813b2d34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 81 additions and 89 deletions

View File

@ -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

View File

@ -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
--------------------------------------------------------------------------------

View File

@ -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:

View File

@ -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'

View File

@ -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

View File

@ -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",
)

View File

@ -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

View File

@ -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):

View File

@ -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 = (

View File

@ -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])

View File

@ -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])