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:
parent
07ee703b59
commit
24813b2d34
|
@ -1,6 +1,6 @@
|
||||||
[settings]
|
[settings]
|
||||||
line_length=79
|
line_length=79
|
||||||
known_first_party=lml, pyexcel, odfpy
|
known_first_party=lml, pyexcel_io, odf
|
||||||
known_third_party=nose
|
known_third_party=nose
|
||||||
indent=' '
|
indent=' '
|
||||||
multi_line_output=3
|
multi_line_output=3
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
Change log
|
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
|
0.5.6 - 19.03.2019
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
name: pyexcel-ods
|
name: pyexcel-ods
|
||||||
organisation: pyexcel
|
organisation: pyexcel
|
||||||
releases:
|
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:
|
- changes:
|
||||||
- action: added
|
- action: added
|
||||||
details:
|
details:
|
||||||
|
|
|
@ -25,7 +25,7 @@ project = 'pyexcel-ods'
|
||||||
copyright = '2015-2020 Onni Software Ltd.'
|
copyright = '2015-2020 Onni Software Ltd.'
|
||||||
author = 'chfw'
|
author = 'chfw'
|
||||||
# The short X.Y version
|
# The short X.Y version
|
||||||
version = '0.5.6'
|
version = '0.6.0'
|
||||||
# The full version, including alpha/beta/rc tags
|
# The full version, including alpha/beta/rc tags
|
||||||
release = '0.5.6'
|
release = '0.5.6'
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
overrides: "pyexcel.yaml"
|
overrides: "pyexcel.yaml"
|
||||||
name: "pyexcel-ods"
|
name: "pyexcel-ods"
|
||||||
nick_name: ods
|
nick_name: ods
|
||||||
version: 0.5.6
|
version: 0.6.0
|
||||||
current_version: 0.5.6
|
current_version: 0.6.0
|
||||||
release: 0.5.6
|
release: 0.5.6
|
||||||
copyright_year: 2015-2020
|
copyright_year: 2015-2020
|
||||||
file_type: ods
|
file_type: ods
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
pyexcel_ods
|
pyexcel_ods
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
The lower level ods file format handler using odfpy
|
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
|
: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
|
# this line has to be place above all else
|
||||||
# because of dynamic import
|
# because of dynamic import
|
||||||
from pyexcel_io.plugins import IOPluginInfoChain
|
from pyexcel_io.plugins import IOPluginInfoChain, IOPluginInfoChainV2
|
||||||
|
|
||||||
__FILE_TYPE__ = "ods"
|
__FILE_TYPE__ = "ods"
|
||||||
IOPluginInfoChain(__name__).add_a_reader(
|
IOPluginInfoChain(__name__)
|
||||||
|
IOPluginInfoChainV2(__name__).add_a_reader(
|
||||||
relative_plugin_class_path="odsr.ODSBook",
|
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__],
|
file_types=[__FILE_TYPE__],
|
||||||
stream_type="binary",
|
stream_type="binary",
|
||||||
).add_a_writer(
|
).add_a_writer(
|
||||||
relative_plugin_class_path="odsw.ODSWriter",
|
relative_plugin_class_path="odsw.ODSWriter",
|
||||||
|
locations=["file", "memory"],
|
||||||
file_types=[__FILE_TYPE__],
|
file_types=[__FILE_TYPE__],
|
||||||
stream_type="binary",
|
stream_type="binary",
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
ods reader
|
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
|
:license: New BSD License, see LICENSE for more details
|
||||||
"""
|
"""
|
||||||
# Copyright 2011 Marco Conti
|
# Copyright 2011 Marco Conti
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
import pyexcel_io.service as service
|
import pyexcel_io.service as service
|
||||||
from odf.text import P
|
from odf.text import P
|
||||||
|
@ -28,17 +29,17 @@ from odf.table import Table, TableRow, TableCell
|
||||||
# Thanks to grt for the fixes
|
# Thanks to grt for the fixes
|
||||||
from odf.teletype import extractText
|
from odf.teletype import extractText
|
||||||
from odf.namespaces import OFFICENS
|
from odf.namespaces import OFFICENS
|
||||||
from pyexcel_io.book import BookReader
|
|
||||||
from odf.opendocument import load
|
from odf.opendocument import load
|
||||||
from pyexcel_io.sheet import SheetReader
|
from pyexcel_io.plugin_api.abstract_sheet import ISheet
|
||||||
from pyexcel_io._compact import OrderedDict
|
from pyexcel_io.plugin_api.abstract_reader import IReader
|
||||||
|
|
||||||
|
|
||||||
class ODSSheet(SheetReader):
|
class ODSSheet(ISheet):
|
||||||
"""native ods sheet"""
|
"""native ods sheet"""
|
||||||
|
|
||||||
def __init__(self, sheet, auto_detect_int=True, **keywords):
|
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
|
self.__auto_detect_int = auto_detect_int
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -99,62 +100,38 @@ class ODSSheet(SheetReader):
|
||||||
return "\n".join(text_content)
|
return "\n".join(text_content)
|
||||||
|
|
||||||
|
|
||||||
class ODSBook(BookReader):
|
class ODSBook(IReader):
|
||||||
"""read ods book"""
|
"""read ods book"""
|
||||||
|
|
||||||
def open(self, file_name, **keywords):
|
def __init__(self, file_alike_object, _, **keywords):
|
||||||
"""open ods file"""
|
self._native_book = load(file_alike_object)
|
||||||
BookReader.open(self, file_name, **keywords)
|
self._keywords = keywords
|
||||||
self._load_from_file()
|
self.content_array = [
|
||||||
|
NameObject(table.getAttribute("name"), table)
|
||||||
def open_stream(self, file_stream, **keywords):
|
for table in self._native_book.spreadsheet.getElementsByType(Table)
|
||||||
"""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
|
|
||||||
]
|
]
|
||||||
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"""
|
"""read a sheet at a specified index"""
|
||||||
tables = self._native_book.spreadsheet.getElementsByType(Table)
|
table = self.content_array[sheet_index].sheet
|
||||||
length = len(tables)
|
sheet = ODSSheet(table, **self._keywords)
|
||||||
if sheet_index < length:
|
return sheet
|
||||||
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()}
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self._native_book = None
|
self._native_book = None
|
||||||
|
|
||||||
def _load_from_memory(self):
|
|
||||||
self._native_book = load(self._file_stream)
|
|
||||||
|
|
||||||
def _load_from_file(self):
|
class ODSBookInContent(ODSBook):
|
||||||
self._native_book = load(self._file_name)
|
"""
|
||||||
|
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
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
ods writer
|
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
|
:license: New BSD License, see LICENSE for more details
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
@ -13,27 +13,23 @@ import pyexcel_io.service as converter
|
||||||
from odf.text import P
|
from odf.text import P
|
||||||
from odf.table import Table, TableRow, TableCell
|
from odf.table import Table, TableRow, TableCell
|
||||||
from odf.namespaces import OFFICENS
|
from odf.namespaces import OFFICENS
|
||||||
from pyexcel_io.book import BookWriter
|
|
||||||
from odf.opendocument import OpenDocumentSpreadsheet
|
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
|
PY2 = sys.version_info[0] == 2
|
||||||
|
|
||||||
PY27_BELOW = PY2 and sys.version_info[1] < 7
|
PY27_BELOW = PY2 and sys.version_info[1] < 7
|
||||||
|
|
||||||
|
|
||||||
class ODSSheetWriter(SheetWriter):
|
class ODSSheetWriter(ISheetWriter):
|
||||||
"""
|
"""
|
||||||
ODS sheet writer
|
ODS sheet writer
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def set_sheet_name(self, name):
|
def __init__(self, ods_book, ods_sheet, sheet_name, **keywords):
|
||||||
"""initialize the native table"""
|
self._native_book = ods_book
|
||||||
self._native_sheet = Table(name=name)
|
self._native_sheet = Table(name=sheet_name)
|
||||||
|
|
||||||
def set_size(self, size):
|
|
||||||
"""not used in this class but used in ods3"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def write_cell(self, row, cell):
|
def write_cell(self, row, cell):
|
||||||
"""write a native cell"""
|
"""write a native cell"""
|
||||||
|
@ -77,14 +73,14 @@ class ODSSheetWriter(SheetWriter):
|
||||||
self._native_book.spreadsheet.addElement(self._native_sheet)
|
self._native_book.spreadsheet.addElement(self._native_sheet)
|
||||||
|
|
||||||
|
|
||||||
class ODSWriter(BookWriter):
|
class ODSWriter(IWriter):
|
||||||
"""
|
"""
|
||||||
open document spreadsheet writer
|
open document spreadsheet writer
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, file_alike_object, file_type, **keywords):
|
||||||
BookWriter.__init__(self)
|
self._file_alike_object = file_alike_object
|
||||||
self._native_book = OpenDocumentSpreadsheet()
|
self._native_book = OpenDocumentSpreadsheet()
|
||||||
|
|
||||||
def create_sheet(self, name):
|
def create_sheet(self, name):
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -29,7 +29,7 @@ except (ValueError, UnicodeError, locale.Error):
|
||||||
|
|
||||||
NAME = "pyexcel-ods"
|
NAME = "pyexcel-ods"
|
||||||
AUTHOR = "chfw"
|
AUTHOR = "chfw"
|
||||||
VERSION = "0.5.6"
|
VERSION = "0.6.0"
|
||||||
EMAIL = "info@pyexcel.org"
|
EMAIL = "info@pyexcel.org"
|
||||||
LICENSE = "New BSD"
|
LICENSE = "New BSD"
|
||||||
DESCRIPTION = (
|
DESCRIPTION = (
|
||||||
|
|
|
@ -7,8 +7,9 @@ from pyexcel_ods.odsw import ODSWriter
|
||||||
|
|
||||||
class TestODSReader(ODSCellTypes):
|
class TestODSReader(ODSCellTypes):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
r = ODSBook()
|
r = ODSBook(
|
||||||
r.open(os.path.join("tests", "fixtures", "ods_formats.ods"))
|
os.path.join("tests", "fixtures", "ods_formats.ods"), "ods"
|
||||||
|
)
|
||||||
self.data = r.read_all()
|
self.data = r.read_all()
|
||||||
for key in self.data.keys():
|
for key in self.data.keys():
|
||||||
self.data[key] = list(self.data[key])
|
self.data[key] = list(self.data[key])
|
||||||
|
@ -17,16 +18,15 @@ class TestODSReader(ODSCellTypes):
|
||||||
|
|
||||||
class TestODSWriter(ODSCellTypes):
|
class TestODSWriter(ODSCellTypes):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
r = ODSBook()
|
r = ODSBook(
|
||||||
r.open(os.path.join("tests", "fixtures", "ods_formats.ods"))
|
os.path.join("tests", "fixtures", "ods_formats.ods"), "ods"
|
||||||
|
)
|
||||||
self.data1 = r.read_all()
|
self.data1 = r.read_all()
|
||||||
self.testfile = "odswriter.ods"
|
self.testfile = "odswriter.ods"
|
||||||
w = ODSWriter()
|
w = ODSWriter(self.testfile, "ods")
|
||||||
w.open(self.testfile)
|
|
||||||
w.write(self.data1)
|
w.write(self.data1)
|
||||||
w.close()
|
w.close()
|
||||||
r2 = ODSBook()
|
r2 = ODSBook(self.testfile, "ods")
|
||||||
r2.open(self.testfile)
|
|
||||||
self.data = r2.read_all()
|
self.data = r2.read_all()
|
||||||
for key in self.data.keys():
|
for key in self.data.keys():
|
||||||
self.data[key] = list(self.data[key])
|
self.data[key] = list(self.data[key])
|
||||||
|
|
|
@ -13,12 +13,10 @@ class TestNativeODSWriter:
|
||||||
"Sheet3": [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]],
|
"Sheet3": [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]],
|
||||||
}
|
}
|
||||||
self.testfile = "writer.ods"
|
self.testfile = "writer.ods"
|
||||||
writer = Writer()
|
writer = Writer(self.testfile, "ods")
|
||||||
writer.open(self.testfile)
|
|
||||||
writer.write(self.content)
|
writer.write(self.content)
|
||||||
writer.close()
|
writer.close()
|
||||||
reader = Reader()
|
reader = Reader(self.testfile, "ods")
|
||||||
reader.open(self.testfile)
|
|
||||||
content = reader.read_all()
|
content = reader.read_all()
|
||||||
for key in content.keys():
|
for key in content.keys():
|
||||||
content[key] = list(content[key])
|
content[key] = list(content[key])
|
||||||
|
|
Loading…
Reference in New Issue