From 432376a5f1b33c8586c05fdd2ca64b8c61150c06 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 18 Oct 2016 00:41:01 +0100 Subject: [PATCH 001/111] fix #14: fix numbercolumnsrepeated where cached row runs out of index --- pyexcel_ods/ods.py | 7 +++++-- tests/fixtures/issue_61.ods | Bin 0 -> 9539 bytes tests/test_bug_fixes.py | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 tests/fixtures/issue_61.ods diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index 1f6ed67..c469188 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -61,8 +61,11 @@ class ODSSheet(SheetReader): cell_value = None if str(row) in self.cached_rows: row_cache = self.cached_rows[str(row)] - cell_value = row_cache[column] - return cell_value + try: + cell_value = row_cache[column] + return cell_value + except IndexError: + return None try: cell = cells[column] diff --git a/tests/fixtures/issue_61.ods b/tests/fixtures/issue_61.ods new file mode 100644 index 0000000000000000000000000000000000000000..34c917a47d728ded67e45bde55ae532b594d2cb8 GIT binary patch literal 9539 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 U1@-PR{M$dr+g062efR1A0n~@o#Q*>R literal 0 HcmV?d00001 diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 67b515f..6e6c008 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -76,3 +76,9 @@ def test_issue_13(): written_data = get_data(test_file, skip_empty_rows=False) eq_(data, written_data[test_file]) os.unlink(test_file) + + +def test_issue_61(): + test_file = "issue_61.ods" + data=get_data(os.path.join("tests", "fixtures", test_file)) + print(data) \ No newline at end of file From 9b7b4417aa3d7d54412ab5756e3d3071c6e1dde1 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 18 Oct 2016 00:47:03 +0100 Subject: [PATCH 002/111] update release candidate version and update common files --- CHANGELOG.rst | 13 ++++++++++ README.rst | 2 +- docs/source/conf.py | 4 +-- pyexcel_ods.yaml | 4 +-- setup.py | 57 +++++++++++++++++++++++++++++------------ test.bat | 3 ++- test.sh | 3 ++- tests/test_bug_fixes.py | 7 ++--- 8 files changed, 66 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index eaedf8c..b419ac5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,19 @@ Change log ================================================================================ +0.2.2 - unreleased +-------------------------------------------------------------------------------- +#. issue `#14 `_, index error + when reading a ods file that has non-uniform columns repeated property. + + +Updated +******************************************************************************** + +#. support pagination. two pairs: start_row, row_limit and start_column, + column_limit help you deal with large files. + + 0.2.1 - 31.08.2016 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index 112dd94..8502aa9 100644 --- a/README.rst +++ b/README.rst @@ -284,7 +284,7 @@ Development steps for code changes Upgrade your setup tools and pip. They are needed for development and testing only: -#. pip install --upgrade setuptools "pip==7.1" +#. pip install --upgrade setuptools "pip==7.1" Then install relevant development requirements: diff --git a/docs/source/conf.py b/docs/source/conf.py index 1f3f712..2e133e2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,8 +16,8 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2016 Onni Software Ltd.' -version = '0.2.0' -release = '0.2.1' +version = '0.2.1' +release = '0.2.2' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index 667d2b3..e60ddbc 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.2.1 -release: 0.2.0 +version: 0.2.2 +release: 0.2.1 file_type: ods dependencies: - pyexcel-io>=0.2.0 diff --git a/setup.py b/setup.py index fb9b466..6fe0be3 100644 --- a/setup.py +++ b/setup.py @@ -7,10 +7,9 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.2.1' +VERSION = '0.2.2' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' -PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' + '' @@ -21,15 +20,6 @@ KEYWORDS = [ 'pyexcel', ] -INSTALL_REQUIRES = [ - 'pyexcel-io>=0.2.0', - 'odfpy>=1.3.3', -] - - -EXTRAS_REQUIRE = { -} - CLASSIFIERS = [ 'Topic :: Office/Business', 'Topic :: Utilities', @@ -41,19 +31,52 @@ CLASSIFIERS = [ 'Programming Language :: Python :: 2.7' ] +INSTALL_REQUIRES = [ + 'pyexcel-io>=0.2.0', + 'odfpy>=1.3.3', +] + + +PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) +EXTRAS_REQUIRE = { +} + def read_files(*files): """Read files into setup""" text = "" for single_file in files: - text = text + read(single_file) + "\n" + content = read(single_file) + text = text + content + "\n" return text def read(afile): """Read a file into setup""" with open(afile, 'r') as opened_file: - return opened_file.read() + content = filter_out_test_code(opened_file) + content = "".join(list(content)) + return content + + +def filter_out_test_code(file_handle): + found_test_code = False + for line in file_handle.readlines(): + if line.startswith('.. testcode:'): + found_test_code = True + continue + if found_test_code is True: + if line.startswith(' '): + continue + else: + empty_line = line.strip() + if len(empty_line) == 0: + continue + else: + found_test_code = False + yield line + else: + yield line if __name__ == '__main__': @@ -63,14 +86,14 @@ if __name__ == '__main__': version=VERSION, author_email=EMAIL, description=DESCRIPTION, - install_requires=INSTALL_REQUIRES, + long_description=read_files('README.rst', 'CHANGELOG.rst'), + license=LICENSE, keywords=KEYWORDS, extras_require=EXTRAS_REQUIRE, + tests_require=['nose'], + install_requires=INSTALL_REQUIRES, packages=PACKAGES, include_package_data=True, - long_description=read_files('README.rst', 'CHANGELOG.rst'), zip_safe=False, - tests_require=['nose'], - license=LICENSE, classifiers=CLASSIFIERS ) diff --git a/test.bat b/test.bat index dbacc63..86e1379 100644 --- a/test.bat +++ b/test.bat @@ -1,3 +1,4 @@ + pip freeze -nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index dbacc63..86e1379 100644 --- a/test.sh +++ b/test.sh @@ -1,3 +1,4 @@ + pip freeze -nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 6e6c008..6287a82 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -78,7 +78,8 @@ def test_issue_13(): os.unlink(test_file) -def test_issue_61(): +def test_issue_14(): + # pyexcel issue 61 test_file = "issue_61.ods" - data=get_data(os.path.join("tests", "fixtures", test_file)) - print(data) \ No newline at end of file + data = get_data(os.path.join("tests", "fixtures", test_file)) + eq_(data['S-LMC'], [[u'aaa'], [0]]) From 982414f3461b5403be262963278c1f712c5abd5c Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 18 Oct 2016 21:26:53 +0100 Subject: [PATCH 003/111] use released version for verfication --- rnd_requirements.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index cabc29e..e18f04d 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,3 +1 @@ -https://github.com/pyexcel/pyexcel-io/archive/master.zip https://github.com/pyexcel/pyexcel-xls/archive/master.zip -https://github.com/pyexcel/pyexcel/archive/master.zip From e3270d1094df00c4a7bbeb32db1b8b4bde3c195a Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 18 Oct 2016 21:37:51 +0100 Subject: [PATCH 004/111] fix broken test --- tests/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/base.py b/tests/base.py index 974de35..d55c16c 100644 --- a/tests/base.py +++ b/tests/base.py @@ -94,7 +94,7 @@ class PyexcelMultipleSheetBase: for s in b: data = pyexcel.utils.to_array(s) assert self.content[s.name] == data - si = pyexcel.sheets.iterators.SheetIterator(b) + si = pyexcel.iterators.SheetIterator(b) for s in si: data = pyexcel.utils.to_array(s) assert self.content[s.name] == data From 210a33b73d8257ac4046ecafb146459da88d5c19 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 24 Oct 2016 21:18:43 +0100 Subject: [PATCH 005/111] prepare for the release --- CHANGELOG.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b419ac5..e45bbc6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,15 +3,12 @@ Change log 0.2.2 - unreleased -------------------------------------------------------------------------------- -#. issue `#14 `_, index error - when reading a ods file that has non-uniform columns repeated property. - Updated ******************************************************************************** -#. support pagination. two pairs: start_row, row_limit and start_column, - column_limit help you deal with large files. +#. issue `#14 `_, index error + when reading a ods file that has non-uniform columns repeated property. 0.2.1 - 31.08.2016 From 8a0b42bcfceba11826415daaf035abb458853332 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 24 Oct 2016 21:35:03 +0100 Subject: [PATCH 006/111] test against pyexcel v0.3.0 --- docs/source/conf.py | 4 +-- pyexcel_ods.yaml | 4 +-- rnd_requirements.txt | 1 + setup.py | 2 +- tests/base.py | 32 ++++--------------- ...iple_sheets.py => test_multiple_sheets.py} | 12 +++---- tests/test_stringio.py | 4 +-- 7 files changed, 20 insertions(+), 39 deletions(-) rename tests/{test_mutliple_sheets.py => test_multiple_sheets.py} (96%) diff --git a/docs/source/conf.py b/docs/source/conf.py index 2e133e2..6c04665 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,8 +16,8 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2016 Onni Software Ltd.' -version = '0.2.1' -release = '0.2.2' +version = '0.2.2' +release = '0.2.3' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index e60ddbc..06c6a5e 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.2.2 -release: 0.2.1 +version: 0.2.3 +release: 0.2.2 file_type: ods dependencies: - pyexcel-io>=0.2.0 diff --git a/rnd_requirements.txt b/rnd_requirements.txt index e18f04d..640de20 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1 +1,2 @@ +https://github.com/pyexcel/pyexcel/archive/master.zip https://github.com/pyexcel/pyexcel-xls/archive/master.zip diff --git a/setup.py b/setup.py index 6fe0be3..f31d964 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.2.2' +VERSION = '0.2.3' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( diff --git a/tests/base.py b/tests/base.py index d55c16c..db8a901 100644 --- a/tests/base.py +++ b/tests/base.py @@ -26,8 +26,7 @@ class PyexcelHatWriterBase: def test_series_table(self): pyexcel.save_as(adict=self.content, dest_file_name=self.testfile) r = pyexcel.get_sheet(file_name=self.testfile, name_columns_by_row=0) - actual = pyexcel.utils.to_dict(r) - assert actual == self.content + assert r.dict == self.content class PyexcelWriterBase: @@ -50,7 +49,7 @@ class PyexcelWriterBase: def test_write_array(self): self._create_a_file(self.testfile) r = pyexcel.get_sheet(file_name=self.testfile) - actual = pyexcel.utils.to_array(r.rows()) + actual = list(r.rows()) assert actual == self.content @@ -74,40 +73,21 @@ class PyexcelMultipleSheetBase: def test_reading_through_sheets(self): b = pyexcel.BookReader(self.testfile) - data = pyexcel.utils.to_array(b["Sheet1"].rows()) + data = list(b["Sheet1"].rows()) expected = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]] assert data == expected - data = pyexcel.utils.to_array(b["Sheet2"].rows()) + data = list(b["Sheet2"].rows()) expected = [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]] assert data == expected - data = pyexcel.utils.to_array(b["Sheet3"].rows()) + data = list(b["Sheet3"].rows()) expected = [[u'X', u'Y', u'Z'], [1, 4, 7], [2, 5, 8], [3, 6, 9]] assert data == expected sheet3 = b["Sheet3"] sheet3.name_columns_by_row(0) - data = pyexcel.utils.to_array(b["Sheet3"].rows()) + data = list(b["Sheet3"].rows()) expected = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] assert data == expected - def test_iterate_through_sheets(self): - b = pyexcel.BookReader(self.testfile) - for s in b: - data = pyexcel.utils.to_array(s) - assert self.content[s.name] == data - si = pyexcel.iterators.SheetIterator(b) - for s in si: - data = pyexcel.utils.to_array(s) - assert self.content[s.name] == data - - def test_random_access_operator(self): - r = pyexcel.BookReader(self.testfile) - value = r["Sheet1"][0, 1] - assert value == 1 - value = r["Sheet3"][0, 1] - assert value == 'Y' - r["Sheet3"].name_columns_by_row(0) - assert r["Sheet3"][0, 1] == 4 - class ODSCellTypes: diff --git a/tests/test_mutliple_sheets.py b/tests/test_multiple_sheets.py similarity index 96% rename from tests/test_mutliple_sheets.py rename to tests/test_multiple_sheets.py index bebbf19..eaabcc9 100644 --- a/tests/test_mutliple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -104,7 +104,7 @@ class TestAddBooks: b1 = pyexcel.get_book(file_name=self.testfile) b2 = pyexcel.get_book(file_name=self.testfile2) b3 = b1 + b2 - content = pyexcel.utils.to_dict(b3) + content = b3.dict sheet_names = content.keys() assert len(sheet_names) == 6 for name in sheet_names: @@ -122,7 +122,7 @@ class TestAddBooks: b1 = pyexcel.BookReader(self.testfile) b2 = pyexcel.BookReader(self.testfile2) b1 += b2 - content = pyexcel.utils.to_dict(b1) + content = b1.dict sheet_names = content.keys() assert len(sheet_names) == 6 for name in sheet_names: @@ -140,7 +140,7 @@ class TestAddBooks: b1 = pyexcel.BookReader(self.testfile) b2 = pyexcel.BookReader(self.testfile2) b3 = b1 + b2["Sheet3"] - content = pyexcel.utils.to_dict(b3) + content = b3.dict sheet_names = content.keys() assert len(sheet_names) == 4 for name in sheet_names: @@ -158,7 +158,7 @@ class TestAddBooks: b1 = pyexcel.BookReader(self.testfile) b2 = pyexcel.BookReader(self.testfile2) b1 += b2["Sheet3"] - content = pyexcel.utils.to_dict(b1) + content = b1.dict sheet_names = content.keys() assert len(sheet_names) == 4 for name in sheet_names: @@ -176,7 +176,7 @@ class TestAddBooks: b1 = pyexcel.BookReader(self.testfile) b2 = pyexcel.BookReader(self.testfile2) b3 = b1["Sheet1"] + b2["Sheet3"] - content = pyexcel.utils.to_dict(b3) + content = b3.dict sheet_names = content.keys() assert len(sheet_names) == 2 assert content["Sheet3"] == self.content["Sheet3"] @@ -189,7 +189,7 @@ class TestAddBooks: b1 = pyexcel.BookReader(self.testfile) b2 = pyexcel.BookReader(self.testfile2) b3 = b1["Sheet1"] + b2 - content = pyexcel.utils.to_dict(b3) + content = b3.dict sheet_names = content.keys() assert len(sheet_names) == 4 for name in sheet_names: diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 203d5d5..98cab41 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -13,7 +13,7 @@ class TestStringIO(TestCase): content = f.read() r = pyexcel.get_sheet(file_type="ods", file_content=content) result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] - actual = pyexcel.utils.to_array(r.enumerate()) + actual = list(r.enumerate()) self.assertEqual(result, actual) if os.path.exists(odsfile): os.unlink(odsfile) @@ -26,5 +26,5 @@ class TestStringIO(TestCase): io = pyexcel.save_as(dest_file_type='ods', array=data) r = pyexcel.get_sheet(file_type="ods", file_content=io.getvalue()) result = [1, 2, 3, 4, 5, 6] - actual = pyexcel.utils.to_array(r.enumerate()) + actual = list(r.enumerate()) self.assertEqual(result, actual) From ee288f6972c95a92236b27a53934575e944b7e37 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 24 Oct 2016 22:26:43 +0100 Subject: [PATCH 007/111] update test cases --- tests/base.py | 4 ++-- tests/test_multiple_sheets.py | 13 +++++++------ tests/test_stringio.py | 8 ++++---- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/base.py b/tests/base.py index db8a901..1b72d4b 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,7 +1,7 @@ import os import pyexcel -from nose.tools import raises import datetime +from nose.tools import raises, eq_ def create_sample_file1(file): @@ -26,7 +26,7 @@ class PyexcelHatWriterBase: def test_series_table(self): pyexcel.save_as(adict=self.content, dest_file_name=self.testfile) r = pyexcel.get_sheet(file_name=self.testfile, name_columns_by_row=0) - assert r.dict == self.content + eq_(r.dict, self.content) class PyexcelWriterBase: diff --git a/tests/test_multiple_sheets.py b/tests/test_multiple_sheets.py index eaabcc9..6d60dbb 100644 --- a/tests/test_multiple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -1,8 +1,8 @@ -from base import PyexcelMultipleSheetBase -import pyexcel import os -from nose.tools import raises import sys +import pyexcel +from nose.tools import raises +from base import PyexcelMultipleSheetBase if sys.version_info[0] == 2 and sys.version_info[1] < 7: from ordereddict import OrderedDict @@ -42,7 +42,8 @@ class TestAddBooks: 3,3,3,3 """ self.rows = 3 - pyexcel.save_book_as(bookdict=self.content, dest_file_name=file) + pyexcel.save_book_as(bookdict=self.content, + dest_file_name=file) def setUp(self): self.testfile = "multiple1.ods" @@ -63,11 +64,11 @@ class TestAddBooks: @raises(IndexError) def test_load_a_single_sheet3(self): - pyexcel.load_book(self.testfile, sheet_index=10000) + pyexcel.get_book(file_name=self.testfile, sheet_index=10000) @raises(ValueError) def test_load_a_single_sheet4(self): - pyexcel.load_book(self.testfile, sheet_name="Not exist") + pyexcel.get_book(file_name=self.testfile, sheet_name="Not exist") def test_delete_sheets(self): b1 = pyexcel.load_book(self.testfile) diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 98cab41..2e84d86 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -1,10 +1,10 @@ import os -from unittest import TestCase +from nose.tools import eq_ import pyexcel from base import create_sample_file1 -class TestStringIO(TestCase): +class TestStringIO: def test_ods_stringio(self): odsfile = "cute.ods" @@ -14,7 +14,7 @@ class TestStringIO(TestCase): r = pyexcel.get_sheet(file_type="ods", file_content=content) result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] actual = list(r.enumerate()) - self.assertEqual(result, actual) + eq_(result, actual) if os.path.exists(odsfile): os.unlink(odsfile) @@ -27,4 +27,4 @@ class TestStringIO(TestCase): r = pyexcel.get_sheet(file_type="ods", file_content=io.getvalue()) result = [1, 2, 3, 4, 5, 6] actual = list(r.enumerate()) - self.assertEqual(result, actual) + eq_(result, actual) From ebcaa87494a210fdbfcfe504a9620ca853862540 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 25 Oct 2016 09:01:16 +0100 Subject: [PATCH 008/111] update release date --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e45bbc6..5dc9e77 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.2.2 - unreleased +0.2.2 - 24.10.2016 -------------------------------------------------------------------------------- Updated From ae5148595075379dc49756d65c095e42e034f5df Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 9 Nov 2016 21:49:21 +0000 Subject: [PATCH 009/111] code refactoring: pythonic private starts with __ --- pyexcel_ods/ods.py | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index c469188..1b6e710 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -41,15 +41,15 @@ class ODSSheet(SheetReader): SheetReader.__init__(self, sheet, **keywords) self.auto_detect_int = auto_detect_int self.rows = self.native_sheet.getElementsByType(TableRow) - self.cached_rows = {} - self._number_of_rows = len(self.rows) - self._number_of_columns = self._find_columns() + self.__cached_rows = {} + self.__number_of_rows = len(self.rows) + self.__number_of_columns = self.__find_columns() def number_of_rows(self): - return self._number_of_rows + return self.__number_of_rows def number_of_columns(self): - return self._number_of_columns + return self.__number_of_columns @property def name(self): @@ -59,8 +59,8 @@ class ODSSheet(SheetReader): current_row = self.rows[row] cells = current_row.getElementsByType(TableCell) cell_value = None - if str(row) in self.cached_rows: - row_cache = self.cached_rows[str(row)] + if str(row) in self.__cached_rows: + row_cache = self.__cached_rows[str(row)] try: cell_value = row_cache[column] return cell_value @@ -69,17 +69,17 @@ class ODSSheet(SheetReader): try: cell = cells[column] - cell_value = self._read_cell(cell) + cell_value = self.__read_cell(cell) except IndexError: cell_value = None return cell_value - def _read_row(self, cells): + def __read_row(self, cells): tmp_row = [] for cell in cells: # repeated value? repeat = cell.getAttribute("numbercolumnsrepeated") - cell_value = self._read_cell(cell) + cell_value = self.__read_cell(cell) if repeat: number_of_repeat = int(repeat) tmp_row += [cell_value] * number_of_repeat @@ -87,7 +87,7 @@ class ODSSheet(SheetReader): tmp_row.append(cell_value) return tmp_row - def _read_text_cell(self, cell): + def __read_text_cell(self, cell): text_content = [] paragraphs = cell.getElementsByType(P) # for each text node @@ -100,12 +100,12 @@ class ODSSheet(SheetReader): text_content.append(node.data) return '\n'.join(text_content) - def _read_cell(self, cell): + def __read_cell(self, cell): cell_type = cell.getAttrNS(OFFICENS, "value-type") value_token = converter.VALUE_TOKEN.get(cell_type, "value") ret = None if cell_type == "string": - text_content = self._read_text_cell(cell) + text_content = self.__read_text_cell(cell) ret = text_content else: if cell_type in converter.VALUE_CONVERTERS: @@ -116,17 +116,17 @@ class ODSSheet(SheetReader): n_value = int(n_value) ret = n_value else: - text_content = self._read_text_cell(cell) + text_content = self.__read_text_cell(cell) ret = text_content return ret - def _find_columns(self): + def __find_columns(self): max = -1 for row_index, row in enumerate(self.rows): cells = row.getElementsByType(TableCell) - if self._check_for_column_repeat(cells): - row_cache = self._read_row(cells) - self.cached_rows.update({str(row_index): row_cache}) + if self.__check_for_column_repeat(cells): + row_cache = self.__read_row(cells) + self.__cached_rows.update({str(row_index): row_cache}) length = len(row_cache) else: length = len(cells) @@ -134,7 +134,7 @@ class ODSSheet(SheetReader): max = length return max - def _check_for_column_repeat(self, cells): + def __check_for_column_repeat(self, cells): found_repeated_columns = False for cell in cells: repeat = cell.getAttribute("numbercolumnsrepeated") @@ -196,7 +196,6 @@ class ODSBook(BookReader): def _load_from_file(self): self.native_book = load(self.file_name) - pass class ODSSheetWriter(SheetWriter): From 77e8818da27aec044186aa81516ef342d099558a Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 1 Dec 2016 23:14:14 +0000 Subject: [PATCH 010/111] adapt pyexcel-io v0.3.0 --- CHANGELOG.rst | 9 +++++++++ docs/source/conf.py | 2 +- pyexcel_ods.yaml | 4 ++-- pyexcel_ods/ods.py | 40 ++++++++++++++++++++-------------------- requirements.txt | 2 +- rnd_requirements.txt | 3 ++- setup.py | 4 ++-- 7 files changed, 37 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5dc9e77..472866e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.3.0 - unreleased +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. Code refactoring with pyexcel-io v 0.3.0 + + 0.2.2 - 24.10.2016 -------------------------------------------------------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index 6c04665..f1d4e1a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -17,7 +17,7 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2016 Onni Software Ltd.' version = '0.2.2' -release = '0.2.3' +release = '0.3.0' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index 06c6a5e..a0677eb 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,10 +1,10 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.2.3 +version: 0.3.0 release: 0.2.2 file_type: ods dependencies: - - pyexcel-io>=0.2.0 + - pyexcel-io>=0.3.0 - odfpy>=1.3.3 description: A wrapper library to read, manipulate and write data in ods format diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index 1b6e710..35ba32e 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -39,10 +39,10 @@ class ODSSheet(SheetReader): """native ods sheet""" def __init__(self, sheet, auto_detect_int=True, **keywords): SheetReader.__init__(self, sheet, **keywords) - self.auto_detect_int = auto_detect_int - self.rows = self.native_sheet.getElementsByType(TableRow) + self.__auto_detect_int = auto_detect_int + self.__rows = self._native_sheet.getElementsByType(TableRow) self.__cached_rows = {} - self.__number_of_rows = len(self.rows) + self.__number_of_rows = len(self.__rows) self.__number_of_columns = self.__find_columns() def number_of_rows(self): @@ -53,10 +53,10 @@ class ODSSheet(SheetReader): @property def name(self): - return self.native_sheet.getAttribute("name") + return self._native_sheet.getAttribute("name") def _cell_value(self, row, column): - current_row = self.rows[row] + current_row = self.__rows[row] cells = current_row.getElementsByType(TableCell) cell_value = None if str(row) in self.__cached_rows: @@ -111,7 +111,7 @@ class ODSSheet(SheetReader): if cell_type in converter.VALUE_CONVERTERS: value = cell.getAttrNS(OFFICENS, value_token) n_value = converter.VALUE_CONVERTERS[cell_type](value) - if cell_type == 'float' and self.auto_detect_int: + if cell_type == 'float' and self.__auto_detect_int: if is_integer_ok_for_xl_float(n_value): n_value = int(n_value) ret = n_value @@ -122,7 +122,7 @@ class ODSSheet(SheetReader): def __find_columns(self): max = -1 - for row_index, row in enumerate(self.rows): + for row_index, row in enumerate(self.__rows): cells = row.getElementsByType(TableCell) if self.__check_for_column_repeat(cells): row_cache = self.__read_row(cells) @@ -159,7 +159,7 @@ class ODSBook(BookReader): def read_sheet_by_name(self, sheet_name): """read a named sheet""" - tables = self.native_book.spreadsheet.getElementsByType(Table) + tables = self._native_book.spreadsheet.getElementsByType(Table) rets = [table for table in tables if table.getAttribute('name') == sheet_name] if len(rets) == 0: @@ -169,7 +169,7 @@ class ODSBook(BookReader): def read_sheet_by_index(self, sheet_index): """read a sheet at a specified index""" - tables = self.native_book.spreadsheet.getElementsByType(Table) + tables = self._native_book.spreadsheet.getElementsByType(Table) length = len(tables) if sheet_index < length: return self.read_sheet(tables[sheet_index]) @@ -180,22 +180,22 @@ class ODSBook(BookReader): def read_all(self): """read all sheets""" result = OrderedDict() - for sheet in self.native_book.spreadsheet.getElementsByType(Table): - ods_sheet = ODSSheet(sheet, **self.keywords) + 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) + sheet = ODSSheet(native_sheet, **self._keywords) return {sheet.name: sheet.to_array()} def _load_from_memory(self): - self.native_book = load(self.file_stream) + self._native_book = load(self._file_stream) def _load_from_file(self): - self.native_book = load(self.file_name) + self._native_book = load(self._file_name) class ODSSheetWriter(SheetWriter): @@ -204,7 +204,7 @@ class ODSSheetWriter(SheetWriter): """ def set_sheet_name(self, name): """initialize the native table""" - self.native_sheet = Table(name=name) + self._native_sheet = Table(name=name) def set_size(self, size): """not used in this class but used in ods3""" @@ -237,7 +237,7 @@ class ODSSheetWriter(SheetWriter): write a row into the file """ row = TableRow() - self.native_sheet.addElement(row) + self._native_sheet.addElement(row) for cell in array: self.write_cell(row, cell) @@ -246,7 +246,7 @@ class ODSSheetWriter(SheetWriter): This call writes file """ - self.native_book.spreadsheet.addElement(self.native_sheet) + self._native_book.spreadsheet.addElement(self._native_sheet) class ODSWriter(BookWriter): @@ -256,20 +256,20 @@ class ODSWriter(BookWriter): """ def __init__(self): BookWriter.__init__(self) - self.native_book = OpenDocumentSpreadsheet() + self._native_book = OpenDocumentSpreadsheet() def create_sheet(self, name): """ write a row into the file """ - return ODSSheetWriter(self.native_book, None, name) + return ODSSheetWriter(self._native_book, None, name) def close(self): """ This call writes file """ - self.native_book.write(self.file_alike_object) + self._native_book.write(self._file_alike_object) def is_integer_ok_for_xl_float(value): diff --git a/requirements.txt b/requirements.txt index 59763ff..606b659 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.2.0 +pyexcel-io>=0.3.0 odfpy>=1.3.3 diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 640de20..960e547 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,2 +1,3 @@ -https://github.com/pyexcel/pyexcel/archive/master.zip +https://github.com/pyexcel/pyexcel/archive/io3.zip +https://github.com/pyexcel/pyexcel-io/archive/master.zip https://github.com/pyexcel/pyexcel-xls/archive/master.zip diff --git a/setup.py b/setup.py index f31d964..14911bc 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.2.3' +VERSION = '0.3.0' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -32,7 +32,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.2.0', + 'pyexcel-io>=0.3.0', 'odfpy>=1.3.3', ] From d43e523387fdd8d1ceb7e09125d074bcbfb56b7f Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 2 Dec 2016 23:31:13 +0000 Subject: [PATCH 011/111] fix #16: reverting back to v0.2.0 but use pyexcel-io v0.3.0's protocol to produce the two dimensional array --- pyexcel_ods/ods.py | 61 +++++++++------------------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index 35ba32e..3756bcb 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -40,39 +40,25 @@ class ODSSheet(SheetReader): def __init__(self, sheet, auto_detect_int=True, **keywords): SheetReader.__init__(self, sheet, **keywords) self.__auto_detect_int = auto_detect_int - self.__rows = self._native_sheet.getElementsByType(TableRow) - self.__cached_rows = {} - self.__number_of_rows = len(self.__rows) - self.__number_of_columns = self.__find_columns() - - def number_of_rows(self): - return self.__number_of_rows - - def number_of_columns(self): - return self.__number_of_columns @property def name(self): return self._native_sheet.getAttribute("name") - def _cell_value(self, row, column): - current_row = self.__rows[row] - cells = current_row.getElementsByType(TableCell) - cell_value = None - if str(row) in self.__cached_rows: - row_cache = self.__cached_rows[str(row)] - try: - cell_value = row_cache[column] - return cell_value - except IndexError: - return None + def _iterate_rows(self): + return self._native_sheet.getElementsByType(TableRow) - try: - cell = cells[column] + def _iterate_columns(self, row): + cells = row.getElementsByType(TableCell) + for cell in cells: + repeat = cell.getAttribute("numbercolumnsrepeated") cell_value = self.__read_cell(cell) - except IndexError: - cell_value = None - return cell_value + if repeat: + number_of_repeat = int(repeat) + for i in range(number_of_repeat): + yield cell_value + else: + yield cell_value def __read_row(self, cells): tmp_row = [] @@ -120,29 +106,6 @@ class ODSSheet(SheetReader): ret = text_content return ret - def __find_columns(self): - max = -1 - for row_index, row in enumerate(self.__rows): - cells = row.getElementsByType(TableCell) - if self.__check_for_column_repeat(cells): - row_cache = self.__read_row(cells) - self.__cached_rows.update({str(row_index): row_cache}) - length = len(row_cache) - else: - length = len(cells) - if length > max: - max = length - return max - - def __check_for_column_repeat(self, cells): - found_repeated_columns = False - for cell in cells: - repeat = cell.getAttribute("numbercolumnsrepeated") - if repeat: - found_repeated_columns = True - break - return found_repeated_columns - class ODSBook(BookReader): """read ods book""" From e31df32b73ab4e409a106a81f16525bf50a767fe Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 6 Dec 2016 09:27:52 +0000 Subject: [PATCH 012/111] describe the library using meta for lazy loading --- pyexcel_ods/__init__.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index 5bc061e..790de9d 100644 --- a/pyexcel_ods/__init__.py +++ b/pyexcel_ods/__init__.py @@ -8,8 +8,12 @@ # flake8: noqa # this line has to be place above all else # because of dynamic import -_FILE_TYPE = 'ods' -__pyexcel_io_plugins__ = [_FILE_TYPE] +__FILE_TYPE__ = 'ods' +__META__ = { + 'file_type': __FILE_TYPE__, + 'stream_type': 'binary' +} +__pyexcel_io_plugins__ = [__META__] from pyexcel_io.io import get_data as read_data, isstream, store_data as write_data @@ -18,12 +22,12 @@ from pyexcel_io.io import get_data as read_data, isstream, store_data as write_d def save_data(afile, data, file_type=None, **keywords): """standalone module function for writing module supported file type""" if isstream(afile) and file_type is None: - file_type = _FILE_TYPE + file_type = __FILE_TYPE__ write_data(afile, data, file_type=file_type, **keywords) def get_data(afile, file_type=None, **keywords): """standalone module function for reading module supported file type""" if isstream(afile) and file_type is None: - file_type = _FILE_TYPE + file_type = __FILE_TYPE__ return read_data(afile, file_type=file_type, **keywords) From 855504bd50548858b8ee09f8219dd256f255fea2 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 6 Dec 2016 14:10:07 +0000 Subject: [PATCH 013/111] use master branch for testing --- rnd_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 960e547..3188ce5 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,3 +1,3 @@ -https://github.com/pyexcel/pyexcel/archive/io3.zip +https://github.com/pyexcel/pyexcel/archive/master.zip https://github.com/pyexcel/pyexcel-io/archive/master.zip https://github.com/pyexcel/pyexcel-xls/archive/master.zip From 9647854c4ab9294be8cdbb622ad2c1c22f8d8de2 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 14 Dec 2016 22:13:58 +0000 Subject: [PATCH 014/111] adjust lazy loading behavior --- pyexcel_ods/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index 790de9d..439ddc0 100644 --- a/pyexcel_ods/__init__.py +++ b/pyexcel_ods/__init__.py @@ -10,7 +10,8 @@ # because of dynamic import __FILE_TYPE__ = 'ods' __META__ = { - 'file_type': __FILE_TYPE__, + 'submodule': __FILE_TYPE__, + 'file_types': [__FILE_TYPE__], 'stream_type': 'binary' } __pyexcel_io_plugins__ = [__META__] From 0f3ae05a0682e81b067a8cec6b2227ac02a77897 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 22 Dec 2016 00:04:51 +0000 Subject: [PATCH 015/111] update function names --- pyexcel_ods/ods.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index 3756bcb..e6ba02a 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -45,10 +45,10 @@ class ODSSheet(SheetReader): def name(self): return self._native_sheet.getAttribute("name") - def _iterate_rows(self): + def row_iterator(self): return self._native_sheet.getElementsByType(TableRow) - def _iterate_columns(self, row): + def column_iterator(self, row): cells = row.getElementsByType(TableCell) for cell in cells: repeat = cell.getAttribute("numbercolumnsrepeated") From 676d60b65c9ee0b188f1fe86f411ef0449d509a0 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 22 Dec 2016 10:31:33 +0000 Subject: [PATCH 016/111] update changelog --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 472866e..53989bf 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.3.0 - unreleased +0.3.0 - 22.12.2016 -------------------------------------------------------------------------------- Updated From aeb8d9494122c49586b42526a0898d4f5967ff2d Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 16 Jan 2017 18:27:32 +0000 Subject: [PATCH 017/111] kick start 0.3.1 --- LICENSE | 2 +- README.rst | 2 +- docs/source/conf.py | 6 +++--- pyexcel_ods.yaml | 4 ++-- pyexcel_ods/__init__.py | 2 +- setup.py | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/LICENSE b/LICENSE index 6e42f18..fea8f2d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2016 by Onni Software Ltd. and its contributors +Copyright (c) 2015-2017 by Onni Software Ltd. and its contributors All rights reserved. Redistribution and use in source and binary forms of the software as well diff --git a/README.rst b/README.rst index 8502aa9..d5415a5 100644 --- a/README.rst +++ b/README.rst @@ -297,7 +297,7 @@ In order to update test environment, and documentation, additional setps are required: #. pip install moban -#. git clone https://github.com/pyexcel/pyexcel-commons.git +#. git clone https://github.com/pyexcel/pyexcel-commons.git commons #. make your changes in `.moban.d` directory, then issue command `moban` What is rnd_requirements.txt diff --git a/docs/source/conf.py b/docs/source/conf.py index f1d4e1a..62b0d6c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -15,9 +15,9 @@ source_suffix = '.rst' master_doc = 'index' project = u'pyexcel-ods' -copyright = u'2015-2016 Onni Software Ltd.' -version = '0.2.2' -release = '0.3.0' +copyright = u'2015-2017 Onni Software Ltd.' +version = '0.3.0' +release = '0.3.1' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index a0677eb..a2152a5 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.3.0 -release: 0.2.2 +version: 0.3.1 +release: 0.3.0 file_type: ods dependencies: - pyexcel-io>=0.3.0 diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index 439ddc0..3d0a58f 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-2016 by Onni Software Ltd & its contributors + :copyright: (c) 2015-2017 by Onni Software Ltd & its contributors :license: New BSD License """ # flake8: noqa diff --git a/setup.py b/setup.py index 14911bc..2e09d95 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.3.0' +VERSION = '0.3.1' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( From 7774a01d18a173ade4c836d962a88d556fb58a14 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 24 Jan 2017 22:44:34 +0000 Subject: [PATCH 018/111] update test case due to https://github.com/pyexcel/pyexcel-io/issues/29 --- .moban.d/travis.yml | 9 +++++---- .travis.yml | 9 +++++---- tests/test_bug_fixes.py | 3 ++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.moban.d/travis.yml b/.moban.d/travis.yml index 0f9b438..006a222 100644 --- a/.moban.d/travis.yml +++ b/.moban.d/travis.yml @@ -2,10 +2,11 @@ {%block custom_python_versions%} python: - - 2.6 - - 2.7 - - 3.3 - - 3.4 + - 3.6 - 3.5 + - 3.4 + - 3.3 + - 2.7 + - 2.6 {%endblock%} diff --git a/.travis.yml b/.travis.yml index 4f15504..23877d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,12 @@ language: python notifications: email: false python: - - 2.6 - - 2.7 - - 3.3 - - 3.4 + - 3.6 - 3.5 + - 3.4 + - 3.3 + - 2.7 + - 2.6 before_install: - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install flake8==2.6.2; fi - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 6287a82..375c407 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -81,5 +81,6 @@ def test_issue_13(): def test_issue_14(): # pyexcel issue 61 test_file = "issue_61.ods" - data = get_data(os.path.join("tests", "fixtures", test_file)) + data = get_data(os.path.join("tests", "fixtures", test_file), + skip_empty_rows=True) eq_(data['S-LMC'], [[u'aaa'], [0]]) From 392e76e129f5d1ca2cb447336fab51a2749f07a3 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 30 Jan 2017 17:38:21 +0000 Subject: [PATCH 019/111] serve a special notice on the performance of the pagination feature --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index d5415a5..9234e12 100644 --- a/README.rst +++ b/README.rst @@ -123,6 +123,11 @@ Continue from previous example: Pagination feature ******************************************************************************** +Special notice 30/01/2017: due to the constraints of the underlying 3rd party +library, it will read the whole file before returning the paginated data. So +at the end of day, the only benefit is less data returned from the reading +function. No major performance improvement will be seen. + Let's assume the following file is a huge ods file: .. code-block:: python From e9d2f09f3afb8f0dd7863e623a1b769c26184da4 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Feb 2017 21:07:42 +0000 Subject: [PATCH 020/111] update readme and classifiers --- .moban.d/README.rst | 10 ++++++++++ .moban.d/setup.py | 5 ----- README.rst | 25 +++++++++++-------------- setup.py | 5 ++++- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/.moban.d/README.rst b/.moban.d/README.rst index e3d0faf..4980f88 100644 --- a/.moban.d/README.rst +++ b/.moban.d/README.rst @@ -8,6 +8,16 @@ ods format using python 2.6 and python 2.7. You are likely to use it with does the same thing but supports Python 3.3 and 3.4 and depends on lxml. {%endblock%} +{% block pagination_note%} +Special notice 30/01/2017: due to the constraints of the underlying 3rd party +library, it will read the whole file before returning the paginated data. So +at the end of day, the only benefit is less data returned from the reading +function. No major performance improvement will be seen. + +With that said, please install `pyexcel-odsr `_ +and it gives better performance in reading partial ods files. +{%endblock%} + {%block extras %} Credits ================================================================================ diff --git a/.moban.d/setup.py b/.moban.d/setup.py index aa56454..2a8e138 100644 --- a/.moban.d/setup.py +++ b/.moban.d/setup.py @@ -6,8 +6,3 @@ {%block compat_block%} {%endblock%} -{%block additional_classifiers%} - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7' -{%endblock%}} - diff --git a/README.rst b/README.rst index 9234e12..37a1438 100644 --- a/README.rst +++ b/README.rst @@ -43,9 +43,6 @@ Usage As a standalone library -------------------------------------------------------------------------------- -Write to an ods file -******************************************************************************** - .. testcode:: :hide: @@ -62,6 +59,11 @@ Write to an ods file ... from collections import OrderedDict +Write to an ods file +******************************************************************************** + + + Here's the sample code to write a dictionary to an ods file: .. code-block:: python @@ -72,6 +74,7 @@ Here's the sample code to write a dictionary to an ods file: >>> data.update({"Sheet 2": [["row 1", "row 2", "row 3"]]}) >>> save_data("your_file.ods", data) + Read from an ods file ******************************************************************************** @@ -105,6 +108,7 @@ Here's the sample code to write a dictionary to an ods file: + Read from an ods from memory ******************************************************************************** @@ -128,6 +132,9 @@ library, it will read the whole file before returning the paginated data. So at the end of day, the only benefit is less data returned from the reading function. No major performance improvement will be seen. +With that said, please install `pyexcel-odsr `_ +and it gives better performance in reading partial ods files. + Let's assume the following file is a huge ods file: .. code-block:: python @@ -184,16 +191,6 @@ No longer, explicit import is needed since pyexcel version 0.2.2. Instead, this library is auto-loaded. So if you want to read data in ods format, installing it is enough. -Any version under pyexcel 0.2.2, you have to keep doing the following: - -Import it in your file to enable this plugin: - -.. code-block:: python - - from pyexcel.ext import ods - -Please note only pyexcel version 0.0.4+ support this. - Reading from an ods file ******************************************************************************** @@ -203,7 +200,6 @@ Here is the sample code: .. code-block:: python >>> import pyexcel as pe - >>> # from pyexcel.ext import ods >>> sheet = pe.get_book(file_name="your_file.ods") >>> sheet Sheet 1: @@ -274,6 +270,7 @@ You need to pass a StringIO instance to Writer: >>> # In reality, you might give it to your http response >>> # object for downloading + License ================================================================================ diff --git a/setup.py b/setup.py index 2e09d95..b77ebf3 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,10 @@ CLASSIFIERS = [ 'License :: OSI Approved :: BSD License', 'Intended Audience :: Developers', 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7' + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ] INSTALL_REQUIRES = [ From 2c5551bd47ab88708ebb2cb178b1dc9003512c57 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Feb 2017 21:14:45 +0000 Subject: [PATCH 021/111] update documentation --- .moban.d/README.rst | 5 +++-- README.rst | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.moban.d/README.rst b/.moban.d/README.rst index 4980f88..d17295c 100644 --- a/.moban.d/README.rst +++ b/.moban.d/README.rst @@ -5,7 +5,8 @@ ods format using python 2.6 and python 2.7. You are likely to use it with `pyexcel `_. `pyexcel-ods3 `_ is a sister library that -does the same thing but supports Python 3.3 and 3.4 and depends on lxml. +depends on ezodf and lxml. `pyexcel-odsr `_ +is the other sister library that has no external dependency but do ods reading only {%endblock%} {% block pagination_note%} @@ -15,7 +16,7 @@ at the end of day, the only benefit is less data returned from the reading function. No major performance improvement will be seen. With that said, please install `pyexcel-odsr `_ -and it gives better performance in reading partial ods files. +and it gives better performance in pagination. {%endblock%} {%block extras %} diff --git a/README.rst b/README.rst index 37a1438..0d83457 100644 --- a/README.rst +++ b/README.rst @@ -12,7 +12,8 @@ pyexcel-ods - Let you focus on data, instead of ods format ods format using python 2.6 and python 2.7. You are likely to use it with `pyexcel `_. `pyexcel-ods3 `_ is a sister library that -does the same thing but supports Python 3.3 and 3.4 and depends on lxml. +depends on ezodf and lxml. `pyexcel-odsr `_ +is the other sister library that has no external dependency but do ods reading only Known constraints ================== @@ -133,7 +134,7 @@ at the end of day, the only benefit is less data returned from the reading function. No major performance improvement will be seen. With that said, please install `pyexcel-odsr `_ -and it gives better performance in reading partial ods files. +and it gives better performance in pagination. Let's assume the following file is a huge ods file: From 689aecc573f093239f5d2abee400ca5477ee63ce Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Feb 2017 21:46:14 +0000 Subject: [PATCH 022/111] recognize currency as text --- pyexcel_ods/ods.py | 4 ++++ tests/base.py | 58 +++++++++++++++++++++++----------------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index e6ba02a..8d9f651 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -93,6 +93,10 @@ class ODSSheet(SheetReader): if cell_type == "string": text_content = self.__read_text_cell(cell) ret = text_content + elif cell_type == "currency": + value = cell.getAttrNS(OFFICENS, value_token) + currency = cell.getAttrNS(OFFICENS, cell_type) + ret = value + ' ' + currency else: if cell_type in converter.VALUE_CONVERTERS: value = cell.getAttrNS(OFFICENS, value_token) diff --git a/tests/base.py b/tests/base.py index 1b72d4b..f92845b 100644 --- a/tests/base.py +++ b/tests/base.py @@ -94,45 +94,45 @@ class ODSCellTypes: def test_formats(self): # date formats date_format = "%d/%m/%Y" - assert self.data["Sheet1"][0][0] == "Date" - assert self.data["Sheet1"][1][0].strftime(date_format) == "11/11/2014" - assert self.data["Sheet1"][2][0].strftime(date_format) == "01/01/2001" - assert self.data["Sheet1"][3][0] == "" + eq_(self.data["Sheet1"][0][0], "Date") + eq_(self.data["Sheet1"][1][0].strftime(date_format), "11/11/2014") + eq_(self.data["Sheet1"][2][0].strftime(date_format), "01/01/2001") + eq_(self.data["Sheet1"][3][0], "") # time formats time_format = "%S:%M:%H" - assert self.data["Sheet1"][0][1] == "Time" - assert self.data["Sheet1"][1][1].strftime(time_format) == "12:12:11" - assert self.data["Sheet1"][2][1].strftime(time_format) == "12:00:00" - assert self.data["Sheet1"][3][1] == 0 - assert self.data["Sheet1"][4][1] == datetime.timedelta(hours=27, - minutes=17, - seconds=54) - assert self.data["Sheet1"][5][1] == "Other" + eq_(self.data["Sheet1"][0][1], "Time") + eq_(self.data["Sheet1"][1][1].strftime(time_format), "12:12:11") + eq_(self.data["Sheet1"][2][1].strftime(time_format), "12:00:00") + eq_(self.data["Sheet1"][3][1], 0) + eq_(self.data["Sheet1"][4][1], datetime.timedelta(hours=27, + minutes=17, + seconds=54)) + eq_(self.data["Sheet1"][5][1], "Other") # boolean - assert self.data["Sheet1"][0][2] == "Boolean" - assert self.data["Sheet1"][1][2] is True - assert self.data["Sheet1"][2][2] is False + eq_(self.data["Sheet1"][0][2], "Boolean") + eq_(self.data["Sheet1"][1][2], True) + eq_(self.data["Sheet1"][2][2], False) # Float - assert self.data["Sheet1"][0][3] == "Float" - assert self.data["Sheet1"][1][3] == 11.11 + eq_(self.data["Sheet1"][0][3], "Float") + eq_(self.data["Sheet1"][1][3], 11.11) # Currency - assert self.data["Sheet1"][0][4] == "Currency" - assert self.data["Sheet1"][1][4] == 1 - assert self.data["Sheet1"][2][4] == -10000 + eq_(self.data["Sheet1"][0][4], "Currency") + eq_(self.data["Sheet1"][1][4], '1 GBP') + eq_(self.data["Sheet1"][2][4], '-10000 GBP') # Percentage - assert self.data["Sheet1"][0][5] == "Percentage" - assert self.data["Sheet1"][1][5] == 2 + eq_(self.data["Sheet1"][0][5], "Percentage") + eq_(self.data["Sheet1"][1][5], 2) # int - assert self.data["Sheet1"][0][6] == "Int" - assert self.data["Sheet1"][1][6] == 3 - assert self.data["Sheet1"][4][6] == 11 + eq_(self.data["Sheet1"][0][6], "Int") + eq_(self.data["Sheet1"][1][6], 3) + eq_(self.data["Sheet1"][4][6], 11) # Scientifed not supported - assert self.data["Sheet1"][1][7] == 100000 + eq_(self.data["Sheet1"][1][7], 100000) # Fraction - assert self.data["Sheet1"][1][8] == 1.25 + eq_(self.data["Sheet1"][1][8], 1.25) # Text - assert self.data["Sheet1"][1][9] == "abc" + eq_(self.data["Sheet1"][1][9], "abc") @raises(IndexError) def test_no_excessive_trailing_columns(self): - assert self.data["Sheet1"][2][6] == "" + eq_(self.data["Sheet1"][2][6], "") From 81c21f9a9f4b1025d69d0a6f8db2b62fe0903f37 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Feb 2017 21:59:32 +0000 Subject: [PATCH 023/111] releasing 0.3.1 --- CHANGELOG.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 53989bf..c453422 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Change log ================================================================================ +0.3.1 - 02.02.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. Recognize currency type + 0.3.0 - 22.12.2016 -------------------------------------------------------------------------------- From d56d325b428c4eb8bf63639d4c1a10c3ea3ccd09 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Feb 2017 22:00:54 +0000 Subject: [PATCH 024/111] mention python version 3.3 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index b77ebf3..fb71b11 100644 --- a/setup.py +++ b/setup.py @@ -29,6 +29,7 @@ CLASSIFIERS = [ 'Intended Audience :: Developers', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', From 45c6f347c0e3638e77993ff4a1582afe6d77a145 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Feb 2017 23:22:00 +0000 Subject: [PATCH 025/111] common tests are mobanized --- .moban.d/tests/test_formatters.py | 4 ++++ .moban.yml | 5 +++++ tests/test_stringio.py | 17 +++++++++-------- tests/test_writer.py | 17 +++++++++-------- 4 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 .moban.d/tests/test_formatters.py diff --git a/.moban.d/tests/test_formatters.py b/.moban.d/tests/test_formatters.py new file mode 100644 index 0000000..0cdd0f4 --- /dev/null +++ b/.moban.d/tests/test_formatters.py @@ -0,0 +1,4 @@ +{% extends 'tests/test_formatters.py.jj2' %} + +{% block test_date_format %} +{% endblock %} \ No newline at end of file diff --git a/.moban.yml b/.moban.yml index 8294aab..68457b2 100644 --- a/.moban.yml +++ b/.moban.yml @@ -15,3 +15,8 @@ targets: - "tests/requirements.txt": "tests/requirements.txt" - test.sh: test.sh.jj2 - test.bat: test.sh.jj2 + - "tests/test_filter.py": "tests/test_filter.py.jj2" + - "tests/test_formatters.py": "tests/test_formatters.py" + - "tests/test_stringio.py": "tests/test_stringio.py.jj2" + - "tests/test_writer.py": "tests/test_writer.py.jj2" + - "tests/base.py": "tests/base.py.jj2" diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 2e84d86..4075bb7 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -1,29 +1,30 @@ import os -from nose.tools import eq_ import pyexcel +from nose.tools import eq_ from base import create_sample_file1 class TestStringIO: def test_ods_stringio(self): - odsfile = "cute.ods" - create_sample_file1(odsfile) - with open(odsfile, "rb") as f: + testfile = "cute.ods" + create_sample_file1(testfile) + with open(testfile, "rb") as f: content = f.read() r = pyexcel.get_sheet(file_type="ods", file_content=content) result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] actual = list(r.enumerate()) eq_(result, actual) - if os.path.exists(odsfile): - os.unlink(odsfile) + if os.path.exists(testfile): + os.unlink(testfile) - def test_xls_output_stringio(self): + def test_ods_output_stringio(self): data = [ [1, 2, 3], [4, 5, 6] ] - io = pyexcel.save_as(dest_file_type='ods', array=data) + io = pyexcel.save_as(dest_file_type="ods", + array=data) r = pyexcel.get_sheet(file_type="ods", file_content=io.getvalue()) result = [1, 2, 3, 4, 5, 6] actual = list(r.enumerate()) diff --git a/tests/test_writer.py b/tests/test_writer.py index 4ee967e..4eedec4 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,5 +1,5 @@ import os -from pyexcel_ods import ods +from pyexcel_ods.ods import ODSWriter as Writer, ODSBook as Reader from base import PyexcelWriterBase, PyexcelHatWriterBase @@ -10,14 +10,15 @@ class TestNativeODSWriter: "Sheet2": [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]], "Sheet3": [[u'X', u'Y', u'Z'], [1, 4, 7], [2, 5, 8], [3, 6, 9]] } - self.testfile = "odswriter.ods" - writer = ods.ODSWriter() + self.testfile = "writer.ods" + writer = Writer() writer.open(self.testfile) writer.write(self.content) writer.close() - reader = ods.ODSBook() + reader = Reader() reader.open(self.testfile) content = reader.read_all() + reader.close() for key in content.keys(): content[key] = list(content[key]) assert content == self.content @@ -27,9 +28,9 @@ class TestNativeODSWriter: os.unlink(self.testfile) -class TestODSnCSVWriter(PyexcelWriterBase): +class TestodsnCSVWriter(PyexcelWriterBase): def setUp(self): - self.testfile = "testods.ods" + self.testfile = "test.ods" self.testfile2 = "test.csv" def tearDown(self): @@ -39,9 +40,9 @@ class TestODSnCSVWriter(PyexcelWriterBase): os.unlink(self.testfile2) -class TestODSHatWriter(PyexcelHatWriterBase): +class TestodsHatWriter(PyexcelHatWriterBase): def setUp(self): - self.testfile = "testhat.ods" + self.testfile = "test.ods" def tearDown(self): if os.path.exists(self.testfile): From 78626bb2dc0d7c05da75e3a6e5b6ca7856ff22b4 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 6 Apr 2017 23:04:06 +0100 Subject: [PATCH 026/111] update plugin protocol --- CHANGELOG.rst | 2 +- pyexcel_ods/__init__.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c453422..fd789d9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,7 +4,7 @@ Change log 0.3.1 - 02.02.2017 -------------------------------------------------------------------------------- -Updated +Added ******************************************************************************** #. Recognize currency type diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index 3d0a58f..3359b15 100644 --- a/pyexcel_ods/__init__.py +++ b/pyexcel_ods/__init__.py @@ -10,6 +10,7 @@ # because of dynamic import __FILE_TYPE__ = 'ods' __META__ = { + 'plugin_type': 'pyexcel io plugin', 'submodule': __FILE_TYPE__, 'file_types': [__FILE_TYPE__], 'stream_type': 'binary' From 1b1100db54699e33dbdf4cadd98dc2d3a67032c2 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 6 Apr 2017 23:27:51 +0100 Subject: [PATCH 027/111] add lml for testing and use v0.4.x branches --- rnd_requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 3188ce5..ce2c7f6 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,3 +1,4 @@ +https://github.com/chfw/lml/archive/master.zip https://github.com/pyexcel/pyexcel/archive/master.zip -https://github.com/pyexcel/pyexcel-io/archive/master.zip -https://github.com/pyexcel/pyexcel-xls/archive/master.zip +https://github.com/pyexcel/pyexcel-io/archive/v0.4.x.zip +https://github.com/pyexcel/pyexcel-xls/archive/v0.4.x.zip From a632925dc2cb53b9f47ea5e184f49060bf7ba965 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 7 Apr 2017 08:20:32 +0100 Subject: [PATCH 028/111] fix #17: respect empty line --- pyexcel_ods/ods.py | 6 ++++-- tests/fixtures/multilineods.ods | Bin 8030 -> 8218 bytes tests/test_multiline_feature.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index 8d9f651..94ea348 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -78,12 +78,14 @@ class ODSSheet(SheetReader): paragraphs = cell.getElementsByType(P) # for each text node for paragraph in paragraphs: + data = '' for node in paragraph.childNodes: if (node.nodeType == 3): if PY2: - text_content.append(unicode(node.data)) + data = unicode(node.data) else: - text_content.append(node.data) + data = node.data + text_content.append(data) return '\n'.join(text_content) def __read_cell(self, cell): diff --git a/tests/fixtures/multilineods.ods b/tests/fixtures/multilineods.ods index c03f6456a3144882c3462a9ebbb1ba0700abcc85..3cf556bd232b4449934a5776ad2a00775c93ef07 100644 GIT binary patch delta 4993 zcmZu#1yoeu_8w9?2ZUjU7?1`jX^`#~ltvn*TO!C?imU}S&?E)mTI>5FhCds}=E=;C4k0mCo|@En&N zfzPd}qG)_CXMIxGh)ENqFk+aNh)Yo?86g!BC;pY)luhdc)I-fK8cUQQ{>C3S1UG}$ z@A3qD#Ckc+)`ZH}Pr(maS7$SdUXD#wj<4>4hJtE0akkF3sCw^uhy6U-cWOknd%YD$ z@;d`@EN1y*YwUYAh_X~ebHmAxH&APv(x|D8CGNh7 z1v_l>{^T6BJ-7W8maq_O9YO#cz@(fxU52`ezL$csKPQ)6Q)lGjNjJQQ`0NB*+`XGq zSVsS7QOJa($!*+FPfy&2*JftMY9m+{S{y6Yi~U}mGmst`OWEYcEO&5yuQ>=2*tGe> zE5A+~Tkkpq&0E-es>02o#CFISU+_S7Q9gC-+tIv`B<~0Njd~?(%3GU*6$f$*6sQ2c zg&xYC!?)~?*wIS4wOv;j!cjJ)jE4EgYI%>LV&3e(c_uczEco@V_K3=56R+=xnm_XG zaqf}m?W~9#82>Q3etn)I>Uh+4ACOUPUd&N{WA5=9AmQ|?IaFA3Vhojc_!I%@0SUn z>;Z3rZvYj+D#wBh&*dHbvKpMmi$$)fs;5$+bo;^Y1o>zE1A&B`2;O0)0n>ePrm_9! z3WmE$IaQ=J>RFJ9_eReZjBcK6%6!h?vDm(wJq1EPq8)0M*l`kr@|q#;X)dl2eI-hB zf6#Rz_*Ajmgum)1CwBLT{7$WJC?ur|_c(;a!h~ z47-hlk{6SE*<8(%6A=lembG19fE=C5ck<|tN4Z)7Uzju2i<~Ro$;*tFUEJl+0oHWlzlcre*QHWcYD2F~#_I>KBe?gMEvZ%W_t-va-XyXyWfM!K*c82Es2{ z+pmcF3EK?QXFqVfu_sk_m51*W4D+$vHr+~Y%ra7uD1DXC*PIpcY&5%aK5W|$cEIlb z{ZbLvkQu>7Vy{S^Ja6BZrJ{ajwY<&Xqo~1^`Q;z7x1@8k`fP*CznL!pePtu^HaugR z{!vG-Z~1gKHPMx~1!J~3n?H9v*q=S&%n|+Al<>;0_)eUKfeMvmWAY|NvTGD0TU1Rz z;BDH(nA79sADJwy2uJ7FSdpi3{if-;G6hr04CTA9u_QkCrf!bWjH~kHuSWx3mq2Y` zgJ`7#>4Zy2Zf8yJC$nsv>Ntx-EmQY{nVDS(RtRr}yXkAjy7xw8Kx@3xgq8^-3JJ4g zI+5ES>`~QUgj#|H$m-Uw+@vf==CZZ-J?40f_b@`c+6vWIj1V1K+0^Ud#9EQY=(fv^ z;2N>%J2&b3GgrluMbA%W88M71FLe0GPN>INq6qKH?Af=g_B##ni&pDrzO#T3MxAu{ zIEFF38&5#f=yxj}L7wRIqbc`a`i7v^9=JLh+c}@TZc}(1u!MWSnS1zwqSrl|PcwJE zc4GO9tVF;~Q-qEK0hdXR$MCD6yqgvDR#j?_{suqprmAKU2#iXkKoj9EeDC^c=+?zv z4>??VD=D0>J*DP0`yy_tmVU6)W;4iq`C#F(>nJaDyvQVojZC1m^y}i|OH{{rf?t{r zSEguy8G1_wR^EEJV+z*o6)6@n)#q6hEZk-@-IlpACV}|e67nj*LR_|^T)69&-Y|!A zFzdB>N)1!CbyZz!xxHfqzmDKU$;haR?(6k)_!+h>Q-{Kpi8*7hx%?gui8LN!%2?cVmdGa%fH2x&+~SJbdL4P z4`KICm+J^l`Ra&pkCUrD_RSkbPE{Z~eJS`8)t2B(0f@3ibXS&mTW$JQZ&h z%)O4N2QN)tA0^Vs#*;bSavW~GexlXhx=4ygbIO26Ls65_TD7})*61f)!{_3eJ)De~ zayuh1(7r^pw2~=?!2^MgsX?GW$^hQ^t^@>=FeBQH&_Yx#2Ye!}m$;C_-`H%Gqy=ig zPbG)bv+X=-$g9TLKMK#S@}a%C-iqV**xkqQ&}!drnzoW_NlVmc#vM0*kOU5zS=sO} zqxYf=?Oh68b=q$DIU>#2EYm&l`2H*wql)7-mY$!Q2e-H{m7ym-Sr2cAainO)0-(YI zS;Qsf*+UU$-#P%&mnSRKyLmjWR5JW#T{7X|+fO;LZ&R?JpTo<7Lu1Or$Ak6P(gvo* zqT>)`S4c&ijqF?WmRfRu)|Nhpn069z%IQ7q6(a);~grK}ouqvqH3ELSbQ7FHKh zojuGlsoPl2vfy1#Z8rdA-ga4xyi2#D*o#QJhJm6Hkfm`0r zyQ29!swGRuxsj3Xb7&l5bn5XIC~O4$eo;ybg;}9_@t_)7m?V zUo*QDg$Zw7z>Hqmz*X?CFK#pB;D~okHD2C6Gt26`|1c!}-P*2=HtFO! z@US@J;kz{)rq(926UmkIhKG8r2eB4==D%eLYsTLY6w)Khxm)Xv5MY(6AjRHLA&jz! zWVEGO$!@@lC^@U@4W}8Qz-AQdC?cq9iaj9;dIstr48Zw}oHE5|nMo9U`*lP!B(9e+ z`Rg9{to`GmaBO3ckR8V&wXPW9@X(@3p(D7g`g8MS}3c>2!8+K^u~1M#94Ss5UpH* z;$f(o*ci(E+Hp~+dsG8WoncFNk}lF}n`_mkTVb5BZ!?p>R$A#BIdhTU z%V-_j`t$srVfrh-FVg!i1r&kym=vc9-MmF4LdBursOj2NCoz5PzG4=xCRO1_WtKbf zpJnrJZf8SI_pgSs?;DM^o*pbR;W$jEWUX<=8*r%_|A6eoV7@X!jA3To~2=u+%bU&ZAytDmT|BIr_)mp1+F|%y!Mo@yb)hE0P?KFnBp9Mn3s%9!uY0xQlUGou%hgslv9|WriB@EuoThrG zKfI~LC%s=kt-8=Xo4qzOZqo!y!#R+cag`$I%65b69XEAeeiy0W>}!qgLsEgpwTf12 zF&pss!Oo+G=xJE=CccSE%`BE1${v&ZO_qh0+{>FNF5Jz(*P;e7oSnBDLQP`igM=pg zo!VYn;kPXDFdi(@HW@N^;Y@J=llToPaa(X_-PZoNQRtfvL!C*BvCg;-&W<;ZDk79SH;R3m|Nzc<_{PKBvx z(#7b^z+aDvbfQC@}RQGS)flYB+4mV~H+Iw;{>Mx(`?I~Jw^*mr-fbVO1Ac@K`W&}sPck$ zQJ##>l(ysW)MB!mD1LSzLcNr#;LDNdY^g?Ecs+}qaEfS_jzWOgh^}}k_?d!OgFF2- z#BoAr!mu0OPj(0E?Kj`}Z(rBAK6OHgzW0ydtQ{e)15esR< z61G~K<-V8_;!k!;b9AgW@lV}MP#AL36qcNd5VDx9FrlEzMt&pj3*wqs_vOIB!w)PTyLisV4A+dL(!P4U*hQzv)^nqwehCk9)T~$ z@xo^GHl89yXm_tO+#oRasoU+q*hlrE={^*5s{}gFy0STmMwS;<$({g=>hMS&H6ytZ z7?`|S=6+AwC(npv#A<8D9WC;VN(EZ;F6sm;`8ie+(dYHp>#F)glitagp|t0tm=%(x zJgJcu;6n(b%EOeS0`2hkx5mll4vr|U(geppo7F(bgqjm!s6<3G(%P-tA}o(8dH21X zVgat3qRH&bmLHU5oCs@Q+LPaCqF1A6%sM^l4l%YAZ(EE>GKaLZwzRYmA4d*oOwb}P z2gB5Z9d8g@VZywY$G*NDvsrBsqs$7J;;pc6vUYV-Xm4DJ3rkg!9R9&}XGVS0gd9ae_bn{TS7jkj!^XU1pDhhiC}* zy_+rh(=RV2?3y0=9fsECY6;mJ0+R zP(S4VR{H8_unZ3Qh0xGc(a?}~z8j=f572So(n<&ji3tcv7z+zai-<^H6B85_0q_~r z@r89oL;zg|K^zevgaHctU@!*&26;viIIFv(pRKf~-Caj}KLLABe-A%7xDfm*pvfro zOX;W%Wpu{*t$AP|g8!9S-Z4P{Nha{Q)IxRsm-$;}0hpN}IPw41SJ+uDhWCf?0%G~o z0L@+Ck|(GsaB#t(|7tnF1u-iW41__!|BnIs7lSdt2Ic!bv}q^=cn#(KZCo&5&l&h} zNdRjY$$t>k`XZUl2Ci^RpgA~wbhL~Qk|2elLe}U*IK_FkhAU8+f|3zMN;PQz82Ly^d zpYy-Th3SBHX2{J8^8YM~bI`d)_DA!g2Z1hT{C`nvYVa3vo>QxyYgTlB#DGA25I~rP Mi!k;4!~p{R3xJd9%>V!Z delta 4755 zcmaJ_2T)U8(@y9up(8cYdq6rtnuzocij)up0qG#2h`^OzLyHK8CPkVGA}S(PK#EcY zq<0XME&)N>2RiSo-#7pKJ9Fpmo_luB-Z{Hx_dGb&DP^dUE+G*E2t)<~@xD~lN`dN; zozibU!<6XP*aqU)8!HOt_=9#6M{fz4>Jgx0At1G6Yv0piQ4Ly%mT93 z#wBhK7%`|CJ48KZ7QRMv%~n|W!9CsLyn;gAaNR1Rz)gx~3Q6fL8zM<^>DM*cU0n#w znE6D?@kwe9W?sIjQ8Du_=$P6tZ&j|s12y5EUIlGgRET(Cg$%B14B5Z2e&daGw9$ic z?;5LTUveTT9WiR$45=zWo@n(rVrizirXZOtQeBWY+Gsb^yw|gVx~0~$fJZJ7r#1>4 zZSCHuvs#tSJbG^3r9_v0i^8FDsvJQ2wZy;Dkze=5oUT$2Yry1O%(@UMdG-7L@XpSV zZA!DZso=*oc?I`*(Q$jayky1TBuTgldx6)dS@y;K1Lu?%({6xYi-{1skG!UZC{!-( zz>s>SW@%PU>6vj+cCW{)F$heV-6sIA*zm3981E(bL(#fqT6538zzOO!3d8<#7*N}K z!nvdv^R!D*lSUzhCD zyqc$xNho3>M9XeQl{aw^7~4mj!uy@RA;xJo?p0;$Suki{F;Fj8vkm(lC;x;LmX?$s zuzVzktIR^nm91R~&0pq1IGh`SIlJ)E>&6mjTWmFM7@>;XI-hWl6OYBy_tv%Fk;1VE zj|K&GFU*mRk)?Tt4}BNAuG(`|^gEg@=onABPZKn8^wLpnZw!*_A@-pAc-o>P&- z^;$RIMNy`qVgVPi{UNPX!KZ=OE{KSk)#;=FlO&|B@iCvu${q{_mZEjclai8N?(T-& zNfOb4yP9}u&n6_AO1Ti?=%b}#9Jhej6iev`w>lz zS_ZkA7Mnk{?AAg*Dks-w4=f4zk;Hq3$97;G_G=`^lp;Fy&X+`~Igg*?f7lqb^^6V?u8A3)i(GWvLYxcG zZHYFd)t>D1+MpmTPvjm;hIq_YAn9gt3Ga*_I%9Y`_ zt!8yhHUeDH3PZimveTFd0gHFq!3NXIJ4>n}=1-KbKY0N&t7CO|xOk}@k11?2CUPgv zxRRe=PqLe~3O*+QTUPTIc)h99x^79CJ}bU)=i17T1wGdR)3KLjVi9@o&4=D(ZGpIz zu2-L%Qc<+s91qhaRA;<)Q;#m!-Ix4C-G6TqJq_PD|5-(=+F^cYJpo{8s14;O)(w?T znC80i_~kk6JLEFrpDHgz-YmXmco$c@xh3=P=9}lQLkC;eD;|I9jPl^P%b44907Fq) zxIsaF)y`_exz7?bw&Q*5^D)nq69e|;zNpP(svvay5Tfv^F&5^$;etW_iNQ#(4 za$9r&zj9RyA@T&(+O`e+6iMo&i&0{Xk!IQ{g03Ea6Y_fkaR*jJXVV;l9compmK_Eu z=_z2A4aOUrjm8^Zg;RJ;X~oHK=|E+FLHKMT{fWuQ5yVKBlnjs(==ykiC}U|rp#RSF zzX}3~>QwM?K%<>KoP5Lr0C%@F3uB)#d76-o3fn^iD&BP29M$MP=gXO{QW=Hy4di#h z`Zu3xrg|?|sEoF8%#Fb%OuoR@W8bAVAUDdDgGEpc!3o!$2-Qp$E*Arzd=#1psf19F z?ArZaMATUdvQ;9KvnNU3a z&OufE#PzL(6yxIy=+8Rub5@F+15*u{ zE_?9XRuo~$F?dH#J3`$%K2;cbJWchW({urF85n`?vl1Txq1Lot+7rqeB_dq*h6NJ^ zy=dY{UiXPirGq7FF8w&FzNZ3Zm{d(v<_Q|2$+>iK^AoD2@M?1pPH<7nx@rNLZd*>Oha2`1VKJnD^nhvJmvoM3^IWBaDM{An@{ z#51V`Q`kdKSkmCj)M3|lFyI9$-!Q5x#JC%;!+(Zvo5Hz!AqzulX63Pi81>sxF(H8mm9deu-t$!<=z%g+VKNY*U+rvdrazsCRD4I zZ9mE1wx}E$JPJrAOXb@`q!Ze=NhdjL=PA$GsRe+#+F(aSVM%;^hqAMwI$HX*wsr!T z`3!epgEz)sopyUe!hpemjFL{njE9!ppJq(aWPQ%);K=3{lEm0;iNj`L1oy$ewiW^C zt8Ygs;jr*ZoIcVnO=9gE@kiEyBE=pShE}Je;s%t@38BuHEBFz}A~kWpG|KhW>HvRW z6;`#~G0a$0)p5wZu4Tf(q@BOirdl*6VjHLu`4Bq-OYLLhoz?TUX+y9sL z6lZCVzT@U_n)L2&lNOU6YD{sZXsWFE=v+WyMmtlxuIe*0VuDaHTc+7c}MuR3r7ro_8 zwv)9?RM=yn>gWruSm^!DY%lA@LZeVKO^rg*wn*z?EL$VpdmNAU;#*Zj3g8+!T*n(J zV_DtrT4knWm(?vJH}m=xx4%nyWt*Q{|Jq?18#5oe*ve9_v1+|h^}O3o7~!P1uQeX9~- zd`nCP<8CTkcK9G>^b=^%NOYmI-dmI~EWxW6^GFI1tf><`DRX+;vlojj{Fs@D)piDj}S@soW>_5OnA zAs%_uPP3$!7-`}1%9QOfH;UzZ+tmrJ*$KEg?`D5zg5!$>lvJR^fKZK5qL#wRb3$LH zax;Hnr-8?1PH<^@ZAl7Z1#_txhjTDfMA2_KuzU$(L&y*HSp`<}^ z7s%+Hz&kgK1rP1`Q z!`dIj6=+s)*ItNMa_Xa7wlR*4+v9;I?!%oP=*!(=8mE}ptx(~p%1MfasI7luuY7bf zx$}8VBoKo2qGJW(r7<(Q6+?T2BknWTWRp-;5w8dk!pPKf-M;)%keHpG-2K- z^rvP=-NNPf7D4wFkT>+jM-0nNanSS-jpUGbCr$+O2^t=1a4sT#5rR&UJkRF)Qx;2o zru2pHBbr528yF-;%gX!Nn0QqXlY7imvq!eyZG0`%rdO=?v`Y_5yY^q&%Eq;w=PQM@ zvuhJqOnVXv0$20_Mu>J)JxTGM!A{6VDg)_cPw}9f++|IhQjZ_kzf`Iau%>>haDE=j z8LezTFGX82ZmQ?^ymsLIIEyYKdUJ=MsCN!YAF=%Xpj|@Rz>z(cs)$*8N8R5@dUJgl zZm!cvtWkbIQ7j~5-2l?R#i%Low;vHM*cCH1cfz2g1o(WslCNSOCswdXx0HkEuaEBt zVo{Gx{aK)UuT|GIYV%@n^to82_u^iKjoHd@A~YEbOW_CG3e+XBBXh=Dm8zCb`X>)N zQqW=xr5sY>V*@o&rASI1Qlvg`*IijyEOYv{rWR&uYGT4V`skfw;c9GOe0^d;{fp8F zF}(a6JmBI!@vQ=HgCo_i^7L{`YiKC(sns;lU7u`dVYzO2Yhdfy{h%Pi>Xd7_81 z$MuoMttmbAjuZYIHP|~1jaYs<$Ra5-XvKjOk{mU^RQ*LY^ecWA&K;LaWXvx5;MlK{ zsz82_2SN#%2wAddZVIWqjzT^wc+8{pKp7c=LWmaEJ%>n(qsE8IAWz$sP1hsmhhT{( zQZ5H_XBFWdi4)sAF$mPf`o9&SN`>(v7;<)t-+b$8k3DM^tD>2B3Fu|v7bM`4@@A5f z3Q|%E7v#jG5ZDH0O#&GSEIEr9SOP20!j7$CL7Z}HEUZ{V78I70RqPiyP=#Q10{?~y z3faW|1uU?f?5tQk8w1vWo#*`7ihnnu=l>Q!PkwdDn1BKF2mip1v9W@ee|;ol zr(ygD7WrG39ox&!b&78=|90R^;W~DbUEsGk!@-Jm;}HHMyyRdwMLL-NolI~H#u^bY zVY@hJ{!CJX2}A!I=)eZTM%lS8`rrF@RImy6i`Q!Ab<*tPQlBqOJh0|NaA%FjwE diff --git a/tests/test_multiline_feature.py b/tests/test_multiline_feature.py index 7a3afc1..8d049a4 100644 --- a/tests/test_multiline_feature.py +++ b/tests/test_multiline_feature.py @@ -6,10 +6,11 @@ def test_reading_multiline_ods(): testfile = os.path.join("tests", "fixtures", "multilineods.ods") sheet = pyexcel.get_sheet(file_name=testfile) assert sheet[0, 0] == '1\n2\n3\n4' + assert sheet[1, 0] == 'Line 1\n\nLine 2' def test_writing_multiline_ods(): - content = "2\n3\n4\n993939\na" + content = "2\n3\n4\n993939\n\na" testfile = "writemultiline.ods" array = [[content, "test"]] pyexcel.save_as(array=array, dest_file_name=testfile) From 684f7101b9d31fdb5dd87f51eafcf6ec388b96b6 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 7 Apr 2017 08:21:32 +0100 Subject: [PATCH 029/111] fix #6: PT288H00M00S is a valid duration --- pyexcel_ods/converter.py | 8 +++++--- tests/test_bug_fixes.py | 7 +++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/pyexcel_ods/converter.py b/pyexcel_ods/converter.py index fc65958..fad8b9b 100644 --- a/pyexcel_ods/converter.py +++ b/pyexcel_ods/converter.py @@ -41,9 +41,11 @@ def ods_date_value(value): def time_value(value): """convert to time value accroding the specification""" - hour = int(value[2:4]) - minute = int(value[5:7]) - second = int(value[8:10]) + import re + results = re.match('PT(\d+)H(\d+)M(\d+)S', value) + hour = int(results.group(1)) + minute = int(results.group(2)) + second = int(results.group(3)) if hour < 24: ret = datetime.time(hour, minute, second) else: diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 375c407..8834310 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -84,3 +84,10 @@ def test_issue_14(): data = get_data(os.path.join("tests", "fixtures", test_file), skip_empty_rows=True) eq_(data['S-LMC'], [[u'aaa'], [0]]) + + +def test_issue_6(): + test_file = "12_day_as_time.ods" + data = get_data(os.path.join("tests", "fixtures", test_file), + skip_empty_rows=True) + eq_(data['Sheet1'][0][0].days, 12) From 8e69905c3f953cdc49cc7517328fbd5ad580a191 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 7 Apr 2017 08:21:31 +0100 Subject: [PATCH 030/111] add missing test fixture --- tests/fixtures/12_day_as_time.ods | Bin 0 -> 8026 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/fixtures/12_day_as_time.ods diff --git a/tests/fixtures/12_day_as_time.ods b/tests/fixtures/12_day_as_time.ods new file mode 100644 index 0000000000000000000000000000000000000000..b7f7197b86a32fcd9ddec3f04f1b0cb805fe51d9 GIT binary patch literal 8026 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 rIV6))rERHg*X#}? Date: Fri, 7 Apr 2017 23:21:22 +0100 Subject: [PATCH 031/111] use released version for travis --- rnd_requirements.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 3188ce5..e69de29 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,3 +0,0 @@ -https://github.com/pyexcel/pyexcel/archive/master.zip -https://github.com/pyexcel/pyexcel-io/archive/master.zip -https://github.com/pyexcel/pyexcel-xls/archive/master.zip From b9b140d6e5c243ef6120661bf1c47acad9199cf7 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 11 Apr 2017 17:37:01 +0100 Subject: [PATCH 032/111] pump up versions --- README.rst | 6 +++--- docs/source/conf.py | 20 ++++++++++++++------ pyexcel_ods.yaml | 4 ++-- setup.py | 2 +- test.bat | 4 +--- test.sh | 4 +--- tests/base.py | 6 +++--- 7 files changed, 25 insertions(+), 21 deletions(-) diff --git a/README.rst b/README.rst index 0d83457..38fb3ac 100644 --- a/README.rst +++ b/README.rst @@ -287,7 +287,7 @@ Development steps for code changes Upgrade your setup tools and pip. They are needed for development and testing only: -#. pip install --upgrade setuptools "pip==7.1" +#. pip install --upgrade setuptools pip Then install relevant development requirements: @@ -296,7 +296,7 @@ Then install relevant development requirements: #. pip install -r tests/requirements.txt -In order to update test environment, and documentation, additional setps are +In order to update test environment, and documentation, additional steps are required: #. pip install moban @@ -325,7 +325,7 @@ Although `nose` and `doctest` are both used in code testing, it is adviable that On Linux/Unix systems, please launch your tests like this:: - $ make test + $ make On Windows systems, please issue this command:: diff --git a/docs/source/conf.py b/docs/source/conf.py index 62b0d6c..ae31813 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,4 +1,8 @@ # -*- coding: utf-8 -*- +DESCRIPTION = ( + 'A wrapper library to read, manipulate and write data in ods format' + + '' +) extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', @@ -16,8 +20,8 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.3.0' -release = '0.3.1' +version = '0.3.1' +release = '0.4.0' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' @@ -25,15 +29,19 @@ html_static_path = ['_static'] htmlhelp_basename = 'pyexcel-odsdoc' latex_elements = {} latex_documents = [ - ('index', 'pyexcel-ods.tex', u'pyexcel-ods Documentation', + ('index', 'pyexcel-ods.tex', + 'pyexcel-ods Documentation', 'Onni Software Ltd.', 'manual'), ] man_pages = [ - ('index', 'pyexcel-ods', u'pyexcel-ods Documentation', + ('index', 'pyexcel-ods', + 'pyexcel-ods Documentation', [u'Onni Software Ltd.'], 1) ] texinfo_documents = [ - ('index', 'pyexcel-ods', u'pyexcel-ods Documentation', - 'Onni Software Ltd.', 'pyexcel-ods', 'One line description of project.', + ('index', 'pyexcel-ods', + 'pyexcel-ods Documentation', + 'Onni Software Ltd.', 'pyexcel-ods', + DESCRIPTION, 'Miscellaneous'), ] diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index a2152a5..31a2d10 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.3.1 -release: 0.3.0 +version: 0.4.0 +release: 0.3.1 file_type: ods dependencies: - pyexcel-io>=0.3.0 diff --git a/setup.py b/setup.py index fb71b11..a7fba70 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.3.1' +VERSION = '0.4.0' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( diff --git a/test.bat b/test.bat index 86e1379..7e4a6fa 100644 --- a/test.bat +++ b/test.bat @@ -1,4 +1,2 @@ - - pip freeze -nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index 86e1379..7e4a6fa 100644 --- a/test.sh +++ b/test.sh @@ -1,4 +1,2 @@ - - pip freeze -nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/tests/base.py b/tests/base.py index f92845b..e469574 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,7 +1,7 @@ -import os +import os # noqa import pyexcel -import datetime -from nose.tools import raises, eq_ +import datetime # noqa +from nose.tools import raises, eq_ # noqa def create_sample_file1(file): From b1861b30349c980ec9331b1e15682ef2026e9076 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 11 Apr 2017 17:41:39 +0100 Subject: [PATCH 033/111] simplify plugin interace. aligned it with pyexcel. both uses meta_class --- pyexcel_ods/ods.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index 8d9f651..f1e6328 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -113,6 +113,9 @@ class ODSSheet(SheetReader): class ODSBook(BookReader): """read ods book""" + file_types = ['ods'] + stream_type = 'binary' + library = 'pyexcel-ods' def open(self, file_name, **keywords): """open ods file""" @@ -221,6 +224,10 @@ class ODSWriter(BookWriter): open document spreadsheet writer """ + file_types = ['ods'] + stream_type = 'binary' + library = 'pyexcel-ods' + def __init__(self): BookWriter.__init__(self) self._native_book = OpenDocumentSpreadsheet() @@ -242,15 +249,3 @@ class ODSWriter(BookWriter): def is_integer_ok_for_xl_float(value): """check if a float had zero value in digits""" return value == math.floor(value) - - -_ods_registry = { - "file_type": "ods", - "reader": ODSBook, - "writer": ODSWriter, - "stream_type": "binary", - "mime_type": "application/vnd.oasis.opendocument.spreadsheet", - "library": "pyexcel-ods" -} - -exports = (_ods_registry,) From a742c5847049adf0956379b35fefd89ec1199493 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 13 Apr 2017 08:08:56 +0100 Subject: [PATCH 034/111] release v0.3.2 --- CHANGELOG.rst | 11 +++++++++++ docs/source/conf.py | 20 ++++++++++++++------ pyexcel_ods.yaml | 4 ++-- setup.py | 2 +- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c453422..7cdc380 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,17 @@ Change log ================================================================================ +0.3.2 - 13.04.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. issue `#17 `_, empty + new line is ignored +#. issue `#6 `_, PT288H00M00S + is valid duration + 0.3.1 - 02.02.2017 -------------------------------------------------------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index 62b0d6c..f744620 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,4 +1,8 @@ # -*- coding: utf-8 -*- +DESCRIPTION = ( + 'A wrapper library to read, manipulate and write data in ods format' + + '' +) extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', @@ -16,8 +20,8 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.3.0' -release = '0.3.1' +version = '0.3.2' +release = '0.3.2' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' @@ -25,15 +29,19 @@ html_static_path = ['_static'] htmlhelp_basename = 'pyexcel-odsdoc' latex_elements = {} latex_documents = [ - ('index', 'pyexcel-ods.tex', u'pyexcel-ods Documentation', + ('index', 'pyexcel-ods.tex', + 'pyexcel-ods Documentation', 'Onni Software Ltd.', 'manual'), ] man_pages = [ - ('index', 'pyexcel-ods', u'pyexcel-ods Documentation', + ('index', 'pyexcel-ods', + 'pyexcel-ods Documentation', [u'Onni Software Ltd.'], 1) ] texinfo_documents = [ - ('index', 'pyexcel-ods', u'pyexcel-ods Documentation', - 'Onni Software Ltd.', 'pyexcel-ods', 'One line description of project.', + ('index', 'pyexcel-ods', + 'pyexcel-ods Documentation', + 'Onni Software Ltd.', 'pyexcel-ods', + DESCRIPTION, 'Miscellaneous'), ] diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index a2152a5..04dd447 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.3.1 -release: 0.3.0 +version: 0.3.2 +release: 0.3.2 file_type: ods dependencies: - pyexcel-io>=0.3.0 diff --git a/setup.py b/setup.py index fb71b11..e10c5d8 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.3.1' +VERSION = '0.3.2' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( From 39a3660ba820a6621e3af7b35c5c97a2c24bd96e Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 13 Apr 2017 22:07:57 +0100 Subject: [PATCH 035/111] launch patreon support channel --- README.rst | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 0d83457..35a1d43 100644 --- a/README.rst +++ b/README.rst @@ -2,11 +2,17 @@ pyexcel-ods - Let you focus on data, instead of ods format ================================================================================ -.. image:: https://api.travis-ci.org/pyexcel/pyexcel-ods.png - :target: http://travis-ci.org/pyexcel/pyexcel-ods +.. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png + :target: https://www.patreon.com/pyexcel + +.. image:: https://api.travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master + :target: http://travis-ci.org/pyexcel/pyexcel-ods .. image:: https://codecov.io/github/pyexcel/pyexcel-ods/coverage.png - :target: https://codecov.io/github/pyexcel/pyexcel-ods + :target: https://codecov.io/github/pyexcel/pyexcel-ods + +.. image:: https://readthedocs.org/projects/pyexcel-ods/badge/?version=latest + :target: http://pyexcel-ods.readthedocs.org/en/latest/ **pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in ods format using python 2.6 and python 2.7. You are likely to use it with @@ -287,7 +293,7 @@ Development steps for code changes Upgrade your setup tools and pip. They are needed for development and testing only: -#. pip install --upgrade setuptools "pip==7.1" +#. pip install --upgrade setuptools pip Then install relevant development requirements: @@ -296,7 +302,7 @@ Then install relevant development requirements: #. pip install -r tests/requirements.txt -In order to update test environment, and documentation, additional setps are +In order to update test environment, and documentation, additional steps are required: #. pip install moban @@ -325,7 +331,7 @@ Although `nose` and `doctest` are both used in code testing, it is adviable that On Linux/Unix systems, please launch your tests like this:: - $ make test + $ make On Windows systems, please issue this command:: @@ -342,3 +348,9 @@ ODSReader is originally written by `Marco Conti >> import os >>> os.unlink("your_file.ods") >>> os.unlink("another_file.ods") + +Support the project +================================================================================ + +If your company has embedded pyexcel and its components into a revenue generating +product, please `support me on patreon `_. From dad76a368f0d4fdd900d3ba21b068a93e3a689ab Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 3 May 2017 12:45:21 +0100 Subject: [PATCH 036/111] fix #19 bug fix on multi-node text --- pyexcel_ods/ods.py | 4 ++-- tests/fixtures/pyexcel_81_ods_19.ods | Bin 0 -> 11013 bytes tests/test_bug_fixes.py | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100755 tests/fixtures/pyexcel_81_ods_19.ods diff --git a/pyexcel_ods/ods.py b/pyexcel_ods/ods.py index 94ea348..10f3525 100644 --- a/pyexcel_ods/ods.py +++ b/pyexcel_ods/ods.py @@ -82,9 +82,9 @@ class ODSSheet(SheetReader): for node in paragraph.childNodes: if (node.nodeType == 3): if PY2: - data = unicode(node.data) + data += unicode(node.data) else: - data = node.data + data += node.data text_content.append(data) return '\n'.join(text_content) diff --git a/tests/fixtures/pyexcel_81_ods_19.ods b/tests/fixtures/pyexcel_81_ods_19.ods new file mode 100755 index 0000000000000000000000000000000000000000..a1954e08405d8401ec4c3b41a3e3ef90ebc39e75 GIT binary patch literal 11013 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

cm=x7voEqC=%G) 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 literal 0 HcmV?d00001 diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 8834310..d5a4cd1 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -91,3 +91,10 @@ def test_issue_6(): data = get_data(os.path.join("tests", "fixtures", test_file), skip_empty_rows=True) eq_(data['Sheet1'][0][0].days, 12) + +def test_issue_19(): + test_file = "pyexcel_81_ods_19.ods" + data = get_data(os.path.join("tests", "fixtures", test_file), + skip_empty_rows=True) + print(data) + eq_(data['product.template'][1][1], 'PRODUCT NAME PMP') From b7316ce961bcc585a61d1af214be8ed5392ec2aa Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 3 May 2017 22:26:07 +0100 Subject: [PATCH 037/111] fix flake8 warning --- tests/test_bug_fixes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index d5a4cd1..8bb936d 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -92,9 +92,9 @@ def test_issue_6(): skip_empty_rows=True) eq_(data['Sheet1'][0][0].days, 12) + def test_issue_19(): test_file = "pyexcel_81_ods_19.ods" data = get_data(os.path.join("tests", "fixtures", test_file), skip_empty_rows=True) - print(data) - eq_(data['product.template'][1][1], 'PRODUCT NAME PMP') + eq_(data['product.template'][1][1], 'PRODUCT NAME PMP') From 1eb25ae9ce3860930f0f4a813709a373c3ea3dc6 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 7 May 2017 13:18:04 +0100 Subject: [PATCH 038/111] release 0.3.3 --- CHANGELOG.rst | 9 +++++++++ README.rst | 5 +++-- docs/source/conf.py | 4 ++-- pyexcel_ods.yaml | 4 ++-- setup.py | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7cdc380..85cf8eb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.3.3 - 07.05.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. issue `#19 `_, not all texts + in a multi-node cell were extracted. + 0.3.2 - 13.04.2017 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index 35a1d43..4c6ab60 100644 --- a/README.rst +++ b/README.rst @@ -40,7 +40,7 @@ or clone it and install it: .. code-block:: bash - $ git clone http://github.com/pyexcel/pyexcel-ods.git + $ git clone https://github.com/pyexcel/pyexcel-ods.git $ cd pyexcel-ods $ python setup.py install @@ -353,4 +353,5 @@ Support the project ================================================================================ If your company has embedded pyexcel and its components into a revenue generating -product, please `support me on patreon `_. +product, please `support me on patreon `_ to +maintain the project and develop it further. diff --git a/docs/source/conf.py b/docs/source/conf.py index f744620..6c5de13 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,8 +20,8 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.3.2' -release = '0.3.2' +version = '0.3.3' +release = '0.3.3' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index 04dd447..c6123b8 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.3.2 -release: 0.3.2 +version: 0.3.3 +release: 0.3.3 file_type: ods dependencies: - pyexcel-io>=0.3.0 diff --git a/setup.py b/setup.py index e10c5d8..2c36ee1 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.3.2' +VERSION = '0.3.3' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( From 3ab2e15927dec0a285abe3757d0e757ac7970530 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 7 May 2017 13:20:14 +0100 Subject: [PATCH 039/111] remove doc link --- README.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.rst b/README.rst index 4c6ab60..2e9179a 100644 --- a/README.rst +++ b/README.rst @@ -11,9 +11,6 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://codecov.io/github/pyexcel/pyexcel-ods/coverage.png :target: https://codecov.io/github/pyexcel/pyexcel-ods -.. image:: https://readthedocs.org/projects/pyexcel-ods/badge/?version=latest - :target: http://pyexcel-ods.readthedocs.org/en/latest/ - **pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in ods format using python 2.6 and python 2.7. You are likely to use it with `pyexcel `_. From 16133985e360a87a754ada49623b887ae8687099 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 7 May 2017 17:51:44 +0100 Subject: [PATCH 040/111] fix the merge error --- rnd_requirements.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index b1f9be1..79fea6b 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,7 +1,5 @@ -<<<<<<< HEAD https://github.com/chfw/lml/archive/master.zip https://github.com/pyexcel/pyexcel/archive/master.zip https://github.com/pyexcel/pyexcel-io/archive/v0.4.x.zip https://github.com/pyexcel/pyexcel-xls/archive/v0.4.x.zip -======= ->>>>>>> master + From 548f2b17e6e4590cb4c2ea3d553aefafea5179a7 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 7 May 2017 17:55:49 +0100 Subject: [PATCH 041/111] update test cases --- tests/test_ods_reader.py | 11 ++++++----- tests/test_writer.py | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/test_ods_reader.py b/tests/test_ods_reader.py index 551bda3..cf7c1f3 100644 --- a/tests/test_ods_reader.py +++ b/tests/test_ods_reader.py @@ -1,11 +1,12 @@ import os -from pyexcel_ods import ods +from pyexcel_ods.odsr import ODSBook +from pyexcel_ods.odsw import ODSWriter from base import ODSCellTypes class TestODSReader(ODSCellTypes): def setUp(self): - r = ods.ODSBook() + r = ODSBook() r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) @@ -17,17 +18,17 @@ class TestODSReader(ODSCellTypes): class TestODSWriter(ODSCellTypes): def setUp(self): - r = ods.ODSBook() + r = ODSBook() r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) self.data1 = r.read_all() self.testfile = "odswriter.ods" - w = ods.ODSWriter() + w = ODSWriter() w.open(self.testfile) w.write(self.data1) w.close() - r2 = ods.ODSBook() + r2 = ODSBook() r2.open(self.testfile) self.data = r2.read_all() for key in self.data.keys(): diff --git a/tests/test_writer.py b/tests/test_writer.py index 4eedec4..1e5a799 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,5 +1,6 @@ import os -from pyexcel_ods.ods import ODSWriter as Writer, ODSBook as Reader +from pyexcel_ods.odsw import ODSWriter as Writer +from pyexcel_ods.odsr import ODSBook as Reader from base import PyexcelWriterBase, PyexcelHatWriterBase From 1e78632474ec7d124e50184414b0a45137078046 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 7 May 2017 18:00:50 +0100 Subject: [PATCH 042/111] update readme --- .moban.d/README.rst | 3 +++ README.rst | 1 + 2 files changed, 4 insertions(+) diff --git a/.moban.d/README.rst b/.moban.d/README.rst index d17295c..83502eb 100644 --- a/.moban.d/README.rst +++ b/.moban.d/README.rst @@ -1,5 +1,8 @@ {%extends 'README.rst.jj2' %} +{%block documentation_link%} +{%endblock%} + {%block description%} **pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in ods format using python 2.6 and python 2.7. You are likely to use it with diff --git a/README.rst b/README.rst index 2e9179a..2decc89 100644 --- a/README.rst +++ b/README.rst @@ -11,6 +11,7 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://codecov.io/github/pyexcel/pyexcel-ods/coverage.png :target: https://codecov.io/github/pyexcel/pyexcel-ods + **pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in ods format using python 2.6 and python 2.7. You are likely to use it with `pyexcel `_. From f83f41f1a648a1cf7b5590c043fa44656bef3557 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 18 May 2017 20:11:47 +0100 Subject: [PATCH 043/111] test against pyexcel-io 0.3.4 --- rnd_requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index e69de29..30a50e9 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -0,0 +1 @@ +https://github.com/pyexcel/pyexcel-io/archive/master.zip From 8635232a179978cf6eb4e9f053729c1ca150a2b6 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 22 May 2017 08:43:08 +0100 Subject: [PATCH 044/111] propagate the lml interface changes --- README.rst | 2 +- pyexcel_ods/__init__.py | 8 ++++---- pyexcel_ods/odsr.py | 4 ---- pyexcel_ods/odsw.py | 4 ---- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/README.rst b/README.rst index 2decc89..64b0e70 100644 --- a/README.rst +++ b/README.rst @@ -351,5 +351,5 @@ Support the project ================================================================================ If your company has embedded pyexcel and its components into a revenue generating -product, please `support me on patreon `_ to +product, please `support me on patreon `_ to maintain the project and develop it further. diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index f24fee0..70c50de 100644 --- a/pyexcel_ods/__init__.py +++ b/pyexcel_ods/__init__.py @@ -8,16 +8,16 @@ # flake8: noqa # this line has to be place above all else # because of dynamic import -from pyexcel_io.plugins import IORegistry +from pyexcel_io.plugins import IOPluginInfoChain from pyexcel_io.io import get_data as read_data, isstream, store_data as write_data __FILE_TYPE__ = 'ods' -IORegistry(__name__).add_a_reader( - submodule='odsr.ODSBook', +IOPluginInfoChain(__name__).add_a_reader( + relative_plugin_class_path='odsr.ODSBook', file_types=[__FILE_TYPE__], stream_type='binary' ).add_a_writer( - submodule='odsw.ODSWriter', + relative_plugin_class_path='odsw.ODSWriter', file_types=[__FILE_TYPE__], stream_type='binary' ) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index f7b965b..ce1ed70 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -124,10 +124,6 @@ class ODSSheet(SheetReader): class ODSBook(BookReader): """read ods book""" - file_types = ['ods'] - stream_type = 'binary' - library = 'pyexcel-ods' - def open(self, file_name, **keywords): """open ods file""" BookReader.open(self, file_name, **keywords) diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index c6b9651..c1a6af4 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -80,10 +80,6 @@ class ODSWriter(BookWriter): open document spreadsheet writer """ - file_types = ['ods'] - stream_type = 'binary' - library = 'pyexcel-ods' - def __init__(self): BookWriter.__init__(self) self._native_book = OpenDocumentSpreadsheet() From 4c35d8f90a57d381f0bf5cd0d25ce67f1eca49e0 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 31 May 2017 23:39:12 +0100 Subject: [PATCH 045/111] verify odfpy does close file handle, https://github.com/pyexcel/pyexcel-xlsx/issues/14 --- tests/test_bug_fixes.py | 43 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 8bb936d..d39c14b 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -1,12 +1,14 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- import os +import psutil +import pyexcel as pe from pyexcel_ods import get_data, save_data from nose.tools import raises, eq_ def test_bug_fix_for_issue_1(): - data = get_data(os.path.join("tests", "fixtures", "repeated.ods")) + data = get_data(get_fixtures("repeated.ods")) eq_(data["Sheet1"], [['repeated', 'repeated', 'repeated', 'repeated']]) @@ -81,20 +83,53 @@ def test_issue_13(): def test_issue_14(): # pyexcel issue 61 test_file = "issue_61.ods" - data = get_data(os.path.join("tests", "fixtures", test_file), + data = get_data(get_fixtures(test_file), skip_empty_rows=True) eq_(data['S-LMC'], [[u'aaa'], [0]]) def test_issue_6(): test_file = "12_day_as_time.ods" - data = get_data(os.path.join("tests", "fixtures", test_file), + data = get_data(get_fixtures(test_file), skip_empty_rows=True) eq_(data['Sheet1'][0][0].days, 12) def test_issue_19(): test_file = "pyexcel_81_ods_19.ods" - data = get_data(os.path.join("tests", "fixtures", test_file), + data = get_data(get_fixtures(test_file), skip_empty_rows=True) eq_(data['product.template'][1][1], 'PRODUCT NAME PMP') + + +def test_issue_83_ods_file_handle(): + # this proves that odfpy + # does not leave a file handle open at all + proc = psutil.Process() + test_file = get_fixtures("issue_61.ods") + open_files_l1 = proc.open_files() + + # start with a csv file + data = pe.iget_array(file_name=test_file) + open_files_l2 = proc.open_files() + delta = len(open_files_l2) - len(open_files_l1) + # cannot catch open file handle + assert delta == 0 + + # now the file handle get opened when we run through + # the generator + list(data) + open_files_l3 = proc.open_files() + delta = len(open_files_l3) - len(open_files_l1) + # cannot catch open file handle + assert delta == 0 + + # free the fish + pe.free_resource() + open_files_l4 = proc.open_files() + # this confirms that no more open file handle + eq_(open_files_l1, open_files_l4) + + +def get_fixtures(filename): + return os.path.join("tests", "fixtures", filename) From f5930fcf896f8f8c3ec799118ef553023f8ec9ea Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 31 May 2017 23:40:17 +0100 Subject: [PATCH 046/111] make sure pyexcel-ods is used for reading --- tests/test_bug_fixes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index d39c14b..7d0478c 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -110,7 +110,7 @@ def test_issue_83_ods_file_handle(): open_files_l1 = proc.open_files() # start with a csv file - data = pe.iget_array(file_name=test_file) + data = pe.iget_array(file_name=test_file, library='pyexcel-ods') open_files_l2 = proc.open_files() delta = len(open_files_l2) - len(open_files_l1) # cannot catch open file handle From b896b3979ad88998f71bac07d2e4e797e392600f Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 1 Jun 2017 22:35:00 +0100 Subject: [PATCH 047/111] avoid updating setuptools 36.0 because it has a bug needing six --- .travis.yml | 1 - docs/source/conf.py | 2 +- tests/requirements.txt | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 23877d2..8f123a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,6 @@ before_install: - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then mv min_requirements.txt requirements.txt ; fi - - pip install --upgrade setuptools "pip==7.1" - test ! -f rnd_requirements.txt || pip install --no-deps -r rnd_requirements.txt - test ! -f rnd_requirements.txt || pip install -r rnd_requirements.txt ; - pip install -r tests/requirements.txt diff --git a/docs/source/conf.py b/docs/source/conf.py index 6f3829f..8f5fdc0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,7 +11,7 @@ extensions = [ ] intersphinx_mapping = { - 'pyexcel': ('http://pyexcel.readthedocs.org/en/latest/', None) + 'pyexcel': ('http://pyexcel.readthedocs.org/en/latest/', None), } spelling_word_list_filename = 'spelling_wordlist.txt' templates_path = ['_templates'] diff --git a/tests/requirements.txt b/tests/requirements.txt index f13a9b5..973f2b9 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,5 @@ nose +mock;python_version<"3" codecov coverage flake8 From cafad5cbfaa2b7fe906ba8b5cfee7e5aa2be2d35 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 1 Jun 2017 22:44:40 +0100 Subject: [PATCH 048/111] add test dependency --- .moban.d/tests/requirements.txt | 1 + tests/requirements.txt | 1 + tests/test_writer.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.moban.d/tests/requirements.txt b/.moban.d/tests/requirements.txt index 3f0c5aa..962ea54 100644 --- a/.moban.d/tests/requirements.txt +++ b/.moban.d/tests/requirements.txt @@ -1,5 +1,6 @@ {% extends 'tests/requirements.txt.jj2' %} {%block extras %} +psutil pyexcel pyexcel-xls {%endblock%} diff --git a/tests/requirements.txt b/tests/requirements.txt index 973f2b9..4b23de1 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,5 +3,6 @@ mock;python_version<"3" codecov coverage flake8 +psutil pyexcel pyexcel-xls diff --git a/tests/test_writer.py b/tests/test_writer.py index 1e5a799..5dec2db 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -19,10 +19,10 @@ class TestNativeODSWriter: reader = Reader() reader.open(self.testfile) content = reader.read_all() - reader.close() for key in content.keys(): content[key] = list(content[key]) assert content == self.content + reader.close() def tearDown(self): if os.path.exists(self.testfile): From 5a8e72b24b9ea75c995416fd59821d5565379b17 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 13 Jun 2017 18:58:46 +0100 Subject: [PATCH 049/111] update dependencies --- .travis.yml | 3 +++ README.rst | 22 +++++++++++++++------- docs/source/conf.py | 2 +- pyexcel_ods.yaml | 4 ++-- pyexcel_ods/odsr.py | 13 ++++--------- requirements.txt | 2 +- setup.py | 2 +- 7 files changed, 27 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8f123a4..3f300e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,9 @@ python: - 2.7 - 2.6 before_install: + - cd $HOME + - "if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then deactivate && wget https://bitbucket.org/squeaky/portable-pypy/downloads/pypy-5.7.1-linux_x86_64-portable.tar.bz2 -O - | tar -jxf - && echo 'Setting up aliases...' && ln -s pypy-5.7.1-linux_x86_64-portable pypy2-latest && export PATH=$HOME/pypy2-latest/bin/:$PATH && virtualenv --no-site-packages --python ~/pypy2-latest/bin/pypy pypy2-env && echo 'Creating custom env...' && source pypy2-env/bin/activate && python -V; fi" + - cd - - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install flake8==2.6.2; fi - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then mv min_requirements.txt requirements.txt ; diff --git a/README.rst b/README.rst index 64b0e70..16ef068 100644 --- a/README.rst +++ b/README.rst @@ -42,6 +42,21 @@ or clone it and install it: $ cd pyexcel-ods $ python setup.py install +Support the project +================================================================================ + +If your company has embedded pyexcel and its components into a revenue generating +product, please `support me on patreon `_ to +maintain the project and develop it further. + +If you are an individual, you are welcome to support me too on patreon and for however long +you feel like to. As a patreon, you will receive +`early access to pyexcel related contents `_. + +With your financial support, I will be able to invest +a little bit more time in coding, documentation and writing interesting posts. + + Usage ================================================================================ @@ -346,10 +361,3 @@ ODSReader is originally written by `Marco Conti >> import os >>> os.unlink("your_file.ods") >>> os.unlink("another_file.ods") - -Support the project -================================================================================ - -If your company has embedded pyexcel and its components into a revenue generating -product, please `support me on patreon `_ to -maintain the project and develop it further. diff --git a/docs/source/conf.py b/docs/source/conf.py index 8f5fdc0..01ee293 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,7 +20,7 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.3.3' +version = '0.4.0' release = '0.4.0' exclude_patterns = [] pygments_style = 'sphinx' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index 9d79aca..b780f92 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -2,9 +2,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods version: 0.4.0 -release: 0.3.3 +release: 0.4.0 file_type: ods dependencies: - - pyexcel-io>=0.3.0 + - pyexcel-io>=0.4.0 - odfpy>=1.3.3 description: A wrapper library to read, manipulate and write data in ods format diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index ce1ed70..b37d109 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -22,7 +22,6 @@ # limitations under the License. # Thanks to grt for the fixes -import sys import math from odf.table import TableRow, TableCell, Table @@ -32,17 +31,10 @@ from odf.opendocument import load from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader +from pyexcel_io._compact import OrderedDict, PY2 import pyexcel_ods.converter as converter -PY2 = sys.version_info[0] == 2 - -PY27_BELOW = PY2 and sys.version_info[1] < 7 -if PY27_BELOW: - from ordereddict import OrderedDict -else: - from collections import OrderedDict - class ODSSheet(SheetReader): """native ods sheet""" @@ -168,6 +160,9 @@ class ODSBook(BookReader): sheet = ODSSheet(native_sheet, **self._keywords) return {sheet.name: sheet.to_array()} + def close(self): + self._native_book = None + def _load_from_memory(self): self._native_book = load(self._file_stream) diff --git a/requirements.txt b/requirements.txt index 606b659..bbd7824 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.3.0 +pyexcel-io>=0.4.0 odfpy>=1.3.3 diff --git a/setup.py b/setup.py index a7fba70..78ac3fa 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.3.0', + 'pyexcel-io>=0.4.0', 'odfpy>=1.3.3', ] From ec2c312ce16a6376adc1a4d86ad028c96712d810 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 14 Jun 2017 23:20:23 +0100 Subject: [PATCH 050/111] make _native book as none for writer --- pyexcel_ods/odsw.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index c1a6af4..87856c5 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -96,3 +96,4 @@ class ODSWriter(BookWriter): """ self._native_book.write(self._file_alike_object) + self._native_book = None From ab98fe8849736284595ea1e06d26713c41aaf64f Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 14 Jun 2017 23:27:31 +0100 Subject: [PATCH 051/111] fix broken tests --- tests/test_bug_fixes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 7d0478c..58443b9 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -125,7 +125,7 @@ def test_issue_83_ods_file_handle(): assert delta == 0 # free the fish - pe.free_resource() + pe.free_resources() open_files_l4 = proc.open_files() # this confirms that no more open file handle eq_(open_files_l1, open_files_l4) From 745f56adf87c4364e062709382c5595ee470b590 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 19 Jun 2017 11:46:12 +0100 Subject: [PATCH 052/111] release v0.4.0 --- CHANGELOG.rst | 12 ++++++++++++ setup.py | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8ee7eb0..499ded4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,18 @@ Change log ================================================================================ +0.4.0 - 19.06.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#14 `_, close file + handle +#. pyexcel-io plugin interface now updated to use + `lml `_. + + 0.3.3 - 07.05.2017 -------------------------------------------------------------------------------- diff --git a/setup.py b/setup.py index 78ac3fa..1e22fe7 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' VERSION = '0.4.0' -EMAIL = 'wangc_2011 (at) hotmail.com' +EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' + From d1e146748e8c5b0d7fe582515bdb342b315fc795 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 22 Jun 2017 10:09:38 +0100 Subject: [PATCH 053/111] code refactoring: remove useless code --- README.rst | 55 +++++++++++++++++++++++++++++---------------- docs/source/conf.py | 2 +- pyexcel_ods.yaml | 3 ++- pyexcel_ods/odsr.py | 47 ++++++++++++++------------------------ setup.py | 2 +- 5 files changed, 57 insertions(+), 52 deletions(-) diff --git a/README.rst b/README.rst index 16ef068..8fc5134 100644 --- a/README.rst +++ b/README.rst @@ -314,28 +314,16 @@ Then install relevant development requirements: #. pip install -r requirements.txt #. pip install -r tests/requirements.txt +Once you have finished your changes, please provide test case(s), relevant documentation +and update CHANGELOG.rst. -In order to update test environment, and documentation, additional steps are -required: +.. note:: -#. pip install moban -#. git clone https://github.com/pyexcel/pyexcel-commons.git commons -#. make your changes in `.moban.d` directory, then issue command `moban` + As to rnd_requirements.txt, usually, it is created when a dependent + library is not released. Once the dependecy is installed + (will be released), the future + version of the dependency in the requirements.txt will be valid. -What is rnd_requirements.txt -------------------------------- - -Usually, it is created when a dependent library is not released. Once the dependecy is installed(will be released), the future version of the dependency in the requirements.txt will be valid. - -What is pyexcel-commons ---------------------------------- - -Many information that are shared across pyexcel projects, such as: this developer guide, license info, etc. are stored in `pyexcel-commons` project. - -What is .moban.d ---------------------------------- - -`.moban.d` stores the specific meta data for the library. How to test your contribution ------------------------------ @@ -350,6 +338,35 @@ On Windows systems, please issue this command:: > test.bat +How to update test environment and update documentation +--------------------------------------------------------- + +Additional steps are required: + +#. pip install moban +#. git clone https://github.com/pyexcel/pyexcel-commons.git commons +#. make your changes in `.moban.d` directory, then issue command `moban` + +What is pyexcel-commons +--------------------------------- + +Many information that are shared across pyexcel projects, such as: this developer guide, license info, etc. are stored in `pyexcel-commons` project. + +What is .moban.d +--------------------------------- + +`.moban.d` stores the specific meta data for the library. + +Acceptance criteria +------------------- + +#. Has Test cases written +#. Has all code lines tested +#. Passes all Travis CI builds +#. Has fair amount of documentation if your change is complex +#. Agree on NEW BSD License for your contribution + + Credits ================================================================================ diff --git a/docs/source/conf.py b/docs/source/conf.py index 01ee293..328a588 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,7 +21,7 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' version = '0.4.0' -release = '0.4.0' +release = '0.4.1' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index b780f92..5e3fa9a 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,7 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.4.0 +version: 0.4.1 +current_version: 0.4.1 release: 0.4.0 file_type: ods dependencies: diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index b37d109..ffb4ad9 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -61,34 +61,6 @@ class ODSSheet(SheetReader): else: yield cell_value - def __read_row(self, cells): - tmp_row = [] - for cell in cells: - # repeated value? - repeat = cell.getAttribute("numbercolumnsrepeated") - cell_value = self.__read_cell(cell) - if repeat: - number_of_repeat = int(repeat) - tmp_row += [cell_value] * number_of_repeat - else: - tmp_row.append(cell_value) - return tmp_row - - def __read_text_cell(self, cell): - text_content = [] - paragraphs = cell.getElementsByType(P) - # for each text node - for paragraph in paragraphs: - data = '' - for node in paragraph.childNodes: - if (node.nodeType == 3): - if PY2: - data += unicode(node.data) - else: - data += node.data - text_content.append(data) - return '\n'.join(text_content) - def __read_cell(self, cell): cell_type = cell.getAttrNS(OFFICENS, "value-type") value_token = converter.VALUE_TOKEN.get(cell_type, "value") @@ -105,7 +77,7 @@ class ODSSheet(SheetReader): value = cell.getAttrNS(OFFICENS, value_token) n_value = converter.VALUE_CONVERTERS[cell_type](value) if cell_type == 'float' and self.__auto_detect_int: - if is_integer_ok_for_xl_float(n_value): + if _is_integer_ok_for_xl_float(n_value): n_value = int(n_value) ret = n_value else: @@ -113,6 +85,21 @@ class ODSSheet(SheetReader): ret = text_content return ret + def __read_text_cell(self, cell): + text_content = [] + paragraphs = cell.getElementsByType(P) + # for each text node + for paragraph in paragraphs: + data = '' + for node in paragraph.childNodes: + if (node.nodeType == 3): + if PY2: + data += unicode(node.data) + else: + data += node.data + text_content.append(data) + return '\n'.join(text_content) + class ODSBook(BookReader): """read ods book""" @@ -170,6 +157,6 @@ class ODSBook(BookReader): self._native_book = load(self._file_name) -def is_integer_ok_for_xl_float(value): +def _is_integer_ok_for_xl_float(value): """check if a float had zero value in digits""" return value == math.floor(value) diff --git a/setup.py b/setup.py index 1e22fe7..83aa3cc 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.4.0' +VERSION = '0.4.1' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( From a9a1154bcdbd67ebb9787775da1eb00e3084face Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 20 Aug 2017 01:12:28 +0100 Subject: [PATCH 054/111] :books: update documentations --- .gitignore | 103 +++++++++++++++++++++++++++++++++++++++++--- .moban.yml | 8 ++-- .travis.yml | 3 -- README.rst | 17 +++++--- docs/source/conf.py | 2 +- setup.cfg | 4 ++ setup.py | 18 +++++--- 7 files changed, 131 insertions(+), 24 deletions(-) create mode 100644 setup.cfg diff --git a/.gitignore b/.gitignore index d98e374..f32c742 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,99 @@ -*.pyc -*~ +# April 2016 +# reference: https://github.com/github/gitignore/blob/master/Python.gitignore +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ .coverage -pyexcel*-info -build -dist \ No newline at end of file +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +# emacs +*~ + +# moban hashes +.moban.hashes +.DS_store + diff --git a/.moban.yml b/.moban.yml index 68457b2..eed4989 100644 --- a/.moban.yml +++ b/.moban.yml @@ -2,6 +2,7 @@ configuration: configuration_dir: "commons/config" template_dir: - "commons/templates" + - "setupmobans/templates" - ".moban.d" configuration: pyexcel_ods.yaml targets: @@ -9,12 +10,13 @@ targets: - setup.py: setup.py - "docs/source/conf.py": "docs/source/conf.py.jj2" - .travis.yml: travis.yml + - .gitignore: gitignore.jj2 - requirements.txt: requirements.txt - - LICENSE: LICENSE.jj2 + - LICENSE: NEW_BSD_LICENSE.jj2 - MANIFEST.in: MANIFEST.in.jj2 - "tests/requirements.txt": "tests/requirements.txt" - - test.sh: test.sh.jj2 - - test.bat: test.sh.jj2 + - test.sh: test.script.jj2 + - test.bat: test.script.jj2 - "tests/test_filter.py": "tests/test_filter.py.jj2" - "tests/test_formatters.py": "tests/test_formatters.py" - "tests/test_stringio.py": "tests/test_stringio.py.jj2" diff --git a/.travis.yml b/.travis.yml index 3f300e8..8f123a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,6 @@ python: - 2.7 - 2.6 before_install: - - cd $HOME - - "if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then deactivate && wget https://bitbucket.org/squeaky/portable-pypy/downloads/pypy-5.7.1-linux_x86_64-portable.tar.bz2 -O - | tar -jxf - && echo 'Setting up aliases...' && ln -s pypy-5.7.1-linux_x86_64-portable pypy2-latest && export PATH=$HOME/pypy2-latest/bin/:$PATH && virtualenv --no-site-packages --python ~/pypy2-latest/bin/pypy pypy2-env && echo 'Creating custom env...' && source pypy2-env/bin/activate && python -V; fi" - - cd - - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install flake8==2.6.2; fi - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then mv min_requirements.txt requirements.txt ; diff --git a/README.rst b/README.rst index 8fc5134..9beea66 100644 --- a/README.rst +++ b/README.rst @@ -8,8 +8,11 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://api.travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-ods -.. image:: https://codecov.io/github/pyexcel/pyexcel-ods/coverage.png - :target: https://codecov.io/github/pyexcel/pyexcel-ods +.. image:: https://codecov.io/gh/pyexcel/pyexcel-ods/branch/master/graph/badge.svg + :target: https://codecov.io/gh/pyexcel/pyexcel-ods + +.. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg + :target: https://gitter.im/pyexcel/Lobby **pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in @@ -320,9 +323,9 @@ and update CHANGELOG.rst. .. note:: As to rnd_requirements.txt, usually, it is created when a dependent - library is not released. Once the dependecy is installed - (will be released), the future - version of the dependency in the requirements.txt will be valid. + library is not released. Once the dependecy is installed + (will be released), the future + version of the dependency in the requirements.txt will be valid. How to test your contribution @@ -344,6 +347,7 @@ How to update test environment and update documentation Additional steps are required: #. pip install moban +#. git clone https://github.com/moremoban/setupmobans.git # generic setup #. git clone https://github.com/pyexcel/pyexcel-commons.git commons #. make your changes in `.moban.d` directory, then issue command `moban` @@ -364,9 +368,10 @@ Acceptance criteria #. Has all code lines tested #. Passes all Travis CI builds #. Has fair amount of documentation if your change is complex +#. Please update CHANGELOG.rst +#. Please add yourself to CONTRIBUTORS.rst #. Agree on NEW BSD License for your contribution - Credits ================================================================================ diff --git a/docs/source/conf.py b/docs/source/conf.py index 328a588..d775af3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,7 +11,7 @@ extensions = [ ] intersphinx_mapping = { - 'pyexcel': ('http://pyexcel.readthedocs.org/en/latest/', None), + 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), } spelling_word_list_filename = 'spelling_wordlist.txt' templates_path = ['_templates'] diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..8c8abfd --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[metadata] +description-file = README.rst +[bdist_wheel] +universal = 1 diff --git a/setup.py b/setup.py index 83aa3cc..e25b836 100644 --- a/setup.py +++ b/setup.py @@ -14,10 +14,11 @@ DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' + '' ) +URL = 'https://github.com/pyexcel/pyexcel-ods' +DOWNLOAD_URL = '%s/archive/0.4.0.tar.gz' % URL +FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ - 'excel', - 'python', - 'pyexcel', + 'python' ] CLASSIFIERS = [ @@ -25,7 +26,6 @@ CLASSIFIERS = [ 'Topic :: Utilities', 'Topic :: Software Development :: Libraries', 'Programming Language :: Python', - 'License :: OSI Approved :: BSD License', 'Intended Audience :: Developers', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', @@ -80,7 +80,11 @@ def filter_out_test_code(file_handle): found_test_code = False yield line else: - yield line + for keyword in ['|version|', '|today|']: + if keyword in line: + break + else: + yield line if __name__ == '__main__': @@ -90,7 +94,9 @@ if __name__ == '__main__': version=VERSION, author_email=EMAIL, description=DESCRIPTION, - long_description=read_files('README.rst', 'CHANGELOG.rst'), + url=URL, + download_url=DOWNLOAD_URL, + long_description=read_files(*FILES), license=LICENSE, keywords=KEYWORDS, extras_require=EXTRAS_REQUIRE, From 28e801697f5fd8590a15af9b6f802024c58c7ade Mon Sep 17 00:00:00 2001 From: "Azamat H. Hackimov" Date: Mon, 21 Aug 2017 23:08:25 +0500 Subject: [PATCH 055/111] Added whitespace handling in cell This fixes bug where pyexcel-ods cannot parse multiple whitespaces ( and such). --- pyexcel_ods/odsr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index ffb4ad9..728f107 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -24,6 +24,7 @@ # Thanks to grt for the fixes import math +from odf import teletype from odf.table import TableRow, TableCell, Table from odf.text import P from odf.namespaces import OFFICENS @@ -87,7 +88,7 @@ class ODSSheet(SheetReader): def __read_text_cell(self, cell): text_content = [] - paragraphs = cell.getElementsByType(P) + paragraphs = teletype.extractText(cell.getElementsByType(P)) # for each text node for paragraph in paragraphs: data = '' From a180d610e542f7218fa9bd34b661580f8b545370 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 Aug 2017 18:16:37 +0100 Subject: [PATCH 056/111] :green_heart: :microscope: :art: fix the broken test, code refactor the whitespace handler --- pyexcel_ods/odsr.py | 12 +++--------- tests/fixtures/white_space.ods | Bin 0 -> 9868 bytes tests/test_bug_fixes.py | 7 +++++++ 3 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 tests/fixtures/white_space.ods diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 728f107..a5b4b1f 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -24,7 +24,7 @@ # Thanks to grt for the fixes import math -from odf import teletype +from odf.teletype import extractText from odf.table import TableRow, TableCell, Table from odf.text import P from odf.namespaces import OFFICENS @@ -88,16 +88,10 @@ class ODSSheet(SheetReader): def __read_text_cell(self, cell): text_content = [] - paragraphs = teletype.extractText(cell.getElementsByType(P)) + paragraphs = cell.getElementsByType(P) # for each text node for paragraph in paragraphs: - data = '' - for node in paragraph.childNodes: - if (node.nodeType == 3): - if PY2: - data += unicode(node.data) - else: - data += node.data + data = extractText(paragraph) text_content.append(data) return '\n'.join(text_content) diff --git a/tests/fixtures/white_space.ods b/tests/fixtures/white_space.ods new file mode 100644 index 0000000000000000000000000000000000000000..8e891c24e76f68fa9631d40380efb5c0aa549649 GIT binary patch literal 9868 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 literal 0 HcmV?d00001 diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 58443b9..703f2a0 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -131,5 +131,12 @@ def test_issue_83_ods_file_handle(): eq_(open_files_l1, open_files_l4) +def test_pr_22(): + test_file = get_fixtures("white_space.ods") + data = get_data(test_file) + # OrderedDict([(u'Sheet1', [[u'paragraph with tab, space, new line']])]) + eq_(data['Sheet1'][0][0], 'paragraph with tab(\t), space, \nnew line') + + def get_fixtures(filename): return os.path.join("tests", "fixtures", filename) From dbcfb77f1c4d4f618ec6d02c424e0e7490d8aa85 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 Aug 2017 23:24:05 +0100 Subject: [PATCH 057/111] :bug: test #23 --- tests/test_bug_fixes.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 58443b9..f16f7b8 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -5,6 +5,9 @@ import psutil import pyexcel as pe from pyexcel_ods import get_data, save_data from nose.tools import raises, eq_ +from nose import SkipTest + +IN_TRAVIS = 'TRAVIS' in os.environ def test_bug_fix_for_issue_1(): @@ -131,5 +134,11 @@ def test_issue_83_ods_file_handle(): eq_(open_files_l1, open_files_l4) +def test_issue_20(): + if not IN_TRAVIS: + raise SkipTest() + pe.get_book(url="https://github.com/pyexcel/pyexcel-ods/raw/master/tests/fixtures/white_space.ods"); # flake8: noqa + + def get_fixtures(filename): return os.path.join("tests", "fixtures", filename) From c6bbd2b58cc4aff10bb708e6bbfbb01de6b768aa Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 Aug 2017 23:33:13 +0100 Subject: [PATCH 058/111] :bug: fix #23 --- pyexcel_ods/odsr.py | 6 +++++- tests/test_bug_fixes.py | 6 ++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index a5b4b1f..43965f7 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -32,7 +32,7 @@ from odf.opendocument import load from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader -from pyexcel_io._compact import OrderedDict, PY2 +from pyexcel_io._compact import OrderedDict, BytesIO import pyexcel_ods.converter as converter @@ -105,6 +105,10 @@ class ODSBook(BookReader): def open_stream(self, file_stream, **keywords): """open ods file stream""" + if not hasattr(file_stream, 'seek'): + # Hei zipfile in odfpy would do a seek + # but stream from urlib cannot do seek + file_stream = BytesIO(file_stream.read()) BookReader.open_stream(self, file_stream, **keywords) self._load_from_memory() diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 9a5d5d8..c09e112 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -102,7 +102,7 @@ def test_issue_19(): test_file = "pyexcel_81_ods_19.ods" data = get_data(get_fixtures(test_file), skip_empty_rows=True) - eq_(data['product.template'][1][1], 'PRODUCT NAME PMP') + eq_(data['product.template'][1][1], 'PRODUCT NAME PMP') def test_issue_83_ods_file_handle(): @@ -141,9 +141,7 @@ def test_pr_22(): eq_(data['Sheet1'][0][0], 'paragraph with tab(\t), space, \nnew line') -def test_issue_20(): - if not IN_TRAVIS: - raise SkipTest() +def test_issue_23(): pe.get_book(url="https://github.com/pyexcel/pyexcel-ods/raw/master/tests/fixtures/white_space.ods"); # flake8: noqa From 504bd942242277450b50230140dc357c569bad78 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 24 Aug 2017 18:32:13 +0100 Subject: [PATCH 059/111] :green_heart: fix broken test --- pyexcel_ods/odsr.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 43965f7..21a3a35 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -23,6 +23,7 @@ # Thanks to grt for the fixes import math +from io import UnsupportedOperation from odf.teletype import extractText from odf.table import TableRow, TableCell, Table @@ -106,8 +107,15 @@ class ODSBook(BookReader): def open_stream(self, file_stream, **keywords): """open ods file stream""" if not hasattr(file_stream, 'seek'): + # python 2 # Hei zipfile in odfpy would do a seek # but stream from urlib cannot do seek + import pdb; pdb.set_trace() + file_stream = BytesIO(file_stream.read()) + try: + file_stream.seek(0) + except UnsupportedOperation: + # python 3 file_stream = BytesIO(file_stream.read()) BookReader.open_stream(self, file_stream, **keywords) self._load_from_memory() From 5e54845d60b73785f37488e90b9f70770623a494 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 24 Aug 2017 18:48:49 +0100 Subject: [PATCH 060/111] :ambulance: remove the f**k pdb in the test. --- pyexcel_ods/odsr.py | 1 - tests/test_bug_fixes.py | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 21a3a35..4b191cf 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -110,7 +110,6 @@ class ODSBook(BookReader): # python 2 # Hei zipfile in odfpy would do a seek # but stream from urlib cannot do seek - import pdb; pdb.set_trace() file_stream = BytesIO(file_stream.read()) try: file_stream.seek(0) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index c09e112..4bf4460 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -142,6 +142,8 @@ def test_pr_22(): def test_issue_23(): + if not IN_TRAVIS: + raise SkipTest() pe.get_book(url="https://github.com/pyexcel/pyexcel-ods/raw/master/tests/fixtures/white_space.ods"); # flake8: noqa From b64838dbcffde99f1693c7767fe6577702480b76 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Aug 2017 06:57:19 +0100 Subject: [PATCH 061/111] :egg: :ferris_wheel: release 0.4.1 --- CHANGELOG.rst | 9 +++++++++ docs/source/conf.py | 2 +- pyexcel_ods.yaml | 2 +- setup.py | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 499ded4..de0ab41 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.4.1 - 25.08.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#23 `_, handle unseekable + stream given by http response + 0.4.0 - 19.06.2017 -------------------------------------------------------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index d775af3..4423ccb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,7 +20,7 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.4.0' +version = '0.4.1' release = '0.4.1' exclude_patterns = [] pygments_style = 'sphinx' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index 5e3fa9a..bdefd5b 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -3,7 +3,7 @@ name: "pyexcel-ods" nick_name: ods version: 0.4.1 current_version: 0.4.1 -release: 0.4.0 +release: 0.4.1 file_type: ods dependencies: - pyexcel-io>=0.4.0 diff --git a/setup.py b/setup.py index e25b836..e97928e 100644 --- a/setup.py +++ b/setup.py @@ -15,8 +15,8 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.4.0.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +DOWNLOAD_URL = '%s/archive/0.4.1.tar.gz' % URL +FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python' ] From f5bbf7e5fd8f135b24e070e4e8e78d263cc99730 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Aug 2017 07:44:23 +0100 Subject: [PATCH 062/111] :newspaper: append a missing log in changelog --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index de0ab41..17cd6c3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,8 @@ Updated #. `#23 `_, handle unseekable stream given by http response +#. PR `#22 `_, hanle white + spaces in a cell. 0.4.0 - 19.06.2017 -------------------------------------------------------------------------------- From bb8b97f7fd80f6c599742ff7c3ab76db123a28b2 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Aug 2017 08:21:26 +0100 Subject: [PATCH 063/111] :fire: remove useless code as it is now handled in pyexcel-io --- pyexcel_ods/converter.py | 135 --------------------------------------- pyexcel_ods/odsr.py | 17 ++--- rnd_requirements.txt | 4 +- 3 files changed, 7 insertions(+), 149 deletions(-) delete mode 100644 pyexcel_ods/converter.py diff --git a/pyexcel_ods/converter.py b/pyexcel_ods/converter.py deleted file mode 100644 index fad8b9b..0000000 --- a/pyexcel_ods/converter.py +++ /dev/null @@ -1,135 +0,0 @@ -import sys -import datetime - -PY2 = sys.version_info[0] == 2 - - -def float_value(value): - """convert a value to float""" - ret = float(value) - return ret - - -def date_value(value): - """convert to data value accroding ods specification""" - ret = "invalid" - try: - # catch strptime exceptions only - if len(value) == 10: - ret = datetime.datetime.strptime( - value, - "%Y-%m-%d") - ret = ret.date() - elif len(value) == 19: - ret = datetime.datetime.strptime( - value, - "%Y-%m-%dT%H:%M:%S") - elif len(value) > 19: - ret = datetime.datetime.strptime( - value[0:26], - "%Y-%m-%dT%H:%M:%S.%f") - except ValueError: - pass - if ret == "invalid": - raise Exception("Bad date value %s" % value) - return ret - - -def ods_date_value(value): - return value.strftime("%Y-%m-%d") - - -def time_value(value): - """convert to time value accroding the specification""" - import re - results = re.match('PT(\d+)H(\d+)M(\d+)S', value) - hour = int(results.group(1)) - minute = int(results.group(2)) - second = int(results.group(3)) - if hour < 24: - ret = datetime.time(hour, minute, second) - else: - ret = datetime.timedelta(hours=hour, minutes=minute, seconds=second) - return ret - - -def ods_time_value(value): - return value.strftime("PT%HH%MM%SS") - - -def boolean_value(value): - """get bolean value""" - if value == "true": - ret = True - else: - ret = False - return ret - - -def ods_bool_value(value): - """convert a boolean value to text""" - if value is True: - return "true" - else: - return "false" - - -def ods_timedelta_value(cell): - """convert a cell value to time delta""" - hours = cell.days * 24 + cell.seconds // 3600 - minutes = (cell.seconds // 60) % 60 - seconds = cell.seconds % 60 - return "PT%02dH%02dM%02dS" % (hours, minutes, seconds) - - -ODS_FORMAT_CONVERSION = { - "float": float, - "date": datetime.date, - "time": datetime.time, - 'timedelta': datetime.timedelta, - "boolean": bool, - "percentage": float, - "currency": float -} - - -ODS_WRITE_FORMAT_COVERSION = { - float: "float", - int: "float", - str: "string", - datetime.date: "date", - datetime.time: "time", - datetime.timedelta: "timedelta", - bool: "boolean" -} - -if PY2: - ODS_WRITE_FORMAT_COVERSION[unicode] = "string" - -VALUE_CONVERTERS = { - "float": float_value, - "date": date_value, - "time": time_value, - "timedelta": time_value, - "boolean": boolean_value, - "percentage": float_value, - "currency": float_value -} - -ODS_VALUE_CONVERTERS = { - "date": ods_date_value, - "time": ods_time_value, - "boolean": ods_bool_value, - "timedelta": ods_timedelta_value -} - - -VALUE_TOKEN = { - "float": "value", - "date": "date-value", - "time": "time-value", - "boolean": "boolean-value", - "percentage": "value", - "currency": "value", - "timedelta": "time-value" -} diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 4b191cf..1e13a62 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -22,7 +22,6 @@ # limitations under the License. # Thanks to grt for the fixes -import math from io import UnsupportedOperation from odf.teletype import extractText @@ -34,8 +33,7 @@ from odf.opendocument import load from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader from pyexcel_io._compact import OrderedDict, BytesIO - -import pyexcel_ods.converter as converter +import pyexcel_io.service as service class ODSSheet(SheetReader): @@ -65,7 +63,7 @@ class ODSSheet(SheetReader): def __read_cell(self, cell): cell_type = cell.getAttrNS(OFFICENS, "value-type") - value_token = converter.VALUE_TOKEN.get(cell_type, "value") + value_token = service.VALUE_TOKEN.get(cell_type, "value") ret = None if cell_type == "string": text_content = self.__read_text_cell(cell) @@ -75,11 +73,11 @@ class ODSSheet(SheetReader): currency = cell.getAttrNS(OFFICENS, cell_type) ret = value + ' ' + currency else: - if cell_type in converter.VALUE_CONVERTERS: + if cell_type in service.VALUE_CONVERTERS: value = cell.getAttrNS(OFFICENS, value_token) - n_value = converter.VALUE_CONVERTERS[cell_type](value) + n_value = service.VALUE_CONVERTERS[cell_type](value) if cell_type == 'float' and self.__auto_detect_int: - if _is_integer_ok_for_xl_float(n_value): + if service.has_no_digits_in_float(n_value): n_value = int(n_value) ret = n_value else: @@ -161,8 +159,3 @@ class ODSBook(BookReader): def _load_from_file(self): self._native_book = load(self._file_name) - - -def _is_integer_ok_for_xl_float(value): - """check if a float had zero value in digits""" - return value == math.floor(value) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 0e70294..3d8132d 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,4 +1,4 @@ https://github.com/chfw/lml/archive/master.zip -https://github.com/pyexcel/pyexcel-io/archive/master.zip +https://github.com/pyexcel/pyexcel-io/archive/dev.zip https://github.com/pyexcel/pyexcel/archive/master.zip -https://github.com/pyexcel/pyexcel-xls/archive/master.zip +https://github.com/pyexcel/pyexcel-xls/archive/dev.zip From 32c7728949709937ce72f565164e1d57680f3400 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 27 Aug 2017 00:10:22 +0100 Subject: [PATCH 064/111] :green_heart: fix broken tests --- pyexcel_ods/odsr.py | 14 +------------- pyexcel_ods/odsw.py | 2 +- tests/test_bug_fixes.py | 19 ------------------- 3 files changed, 2 insertions(+), 33 deletions(-) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 1e13a62..f4b6c9e 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -22,8 +22,6 @@ # limitations under the License. # Thanks to grt for the fixes -from io import UnsupportedOperation - from odf.teletype import extractText from odf.table import TableRow, TableCell, Table from odf.text import P @@ -32,7 +30,7 @@ from odf.opendocument import load from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader -from pyexcel_io._compact import OrderedDict, BytesIO +from pyexcel_io._compact import OrderedDict import pyexcel_io.service as service @@ -104,16 +102,6 @@ class ODSBook(BookReader): def open_stream(self, file_stream, **keywords): """open ods file stream""" - if not hasattr(file_stream, 'seek'): - # python 2 - # Hei zipfile in odfpy would do a seek - # but stream from urlib cannot do seek - file_stream = BytesIO(file_stream.read()) - try: - file_stream.seek(0) - except UnsupportedOperation: - # python 3 - file_stream = BytesIO(file_stream.read()) BookReader.open_stream(self, file_stream, **keywords) self._load_from_memory() diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index 87856c5..3be88c2 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -17,7 +17,7 @@ from odf.opendocument import OpenDocumentSpreadsheet from pyexcel_io.book import BookWriter from pyexcel_io.sheet import SheetWriter -import pyexcel_ods.converter as converter +import pyexcel_io.service as converter PY2 = sys.version_info[0] == 2 diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 4bf4460..c5c3d89 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -24,25 +24,6 @@ def test_bug_fix_for_issue_2(): assert new_data["Sheet 2"] == [[u'row 1', u'H\xe9ll\xf4!', u'Hol\xc1!']] -def test_date_util_parse(): - from pyexcel_ods.converter import date_value - value = "2015-08-17T19:20:00" - d = date_value(value) - assert d.strftime("%Y-%m-%dT%H:%M:%S") == "2015-08-17T19:20:00" - value = "2015-08-17" - d = date_value(value) - assert d.strftime("%Y-%m-%d") == "2015-08-17" - value = "2015-08-17T19:20:59.999999" - d = date_value(value) - assert d.strftime("%Y-%m-%dT%H:%M:%S") == "2015-08-17T19:20:59" - value = "2015-08-17T19:20:59.99999" - d = date_value(value) - assert d.strftime("%Y-%m-%dT%H:%M:%S") == "2015-08-17T19:20:59" - value = "2015-08-17T19:20:59.999999999999999" - d = date_value(value) - assert d.strftime("%Y-%m-%dT%H:%M:%S") == "2015-08-17T19:20:59" - - @raises(Exception) def test_invalid_date(): from pyexcel_ods.ods import date_value From b85ab9e3325e6ece2c69a44e7039ae2677658db6 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 30 Aug 2017 23:37:59 +0100 Subject: [PATCH 065/111] release 0.5.0 :egg: :ferris_wheel: --- CHANGELOG.rst | 16 ++++++++++++++++ docs/source/conf.py | 4 ++-- pyexcel_ods.yaml | 8 ++++---- requirements.txt | 2 +- rnd_requirements.txt | 4 +--- setup.py | 6 +++--- 6 files changed, 27 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 17cd6c3..83bc45b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,22 @@ Change log ================================================================================ + +0.5.0 - 30.08.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. put dependency on pyexcel-io 0.5.0, which uses cStringIO instead of StringIO. + Hence, there will be performance boost in handling files in memory. + +Relocated +-------------------------------------------------------------------------------- + +#. All ods type conversion code lives in pyexcel_io.service module + + 0.4.1 - 25.08.2017 -------------------------------------------------------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index 4423ccb..3836c77 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,8 +20,8 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.4.1' -release = '0.4.1' +version = '0.5.0' +release = '0.5.0' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index bdefd5b..c72ed07 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,11 +1,11 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.4.1 -current_version: 0.4.1 -release: 0.4.1 +version: 0.5.0 +current_version: 0.5.0 +release: 0.5.0 file_type: ods dependencies: - - pyexcel-io>=0.4.0 + - pyexcel-io>=0.5.0 - odfpy>=1.3.3 description: A wrapper library to read, manipulate and write data in ods format diff --git a/requirements.txt b/requirements.txt index bbd7824..9ffd1b6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.4.0 +pyexcel-io>=0.5.0 odfpy>=1.3.3 diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 3d8132d..2ce1c92 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,4 +1,2 @@ -https://github.com/chfw/lml/archive/master.zip -https://github.com/pyexcel/pyexcel-io/archive/dev.zip https://github.com/pyexcel/pyexcel/archive/master.zip -https://github.com/pyexcel/pyexcel-xls/archive/dev.zip + diff --git a/setup.py b/setup.py index e97928e..513c5c7 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ except ImportError: NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.4.1' +VERSION = '0.5.0' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -15,7 +15,7 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.4.1.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.0.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python' @@ -36,7 +36,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.4.0', + 'pyexcel-io>=0.5.0', 'odfpy>=1.3.3', ] From 3f15550c9e79b83e9291765e3fd41a5e8fca1819 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 20 Oct 2017 07:43:30 +0100 Subject: [PATCH 066/111] :handshake: take latest code from setupmobans and release 0.5.1 :egg: :ferris_wheel:, which carries LICENSE file, https://github.com/pyexcel/pyexcel/pull/103 --- CHANGELOG.rst | 8 ++++++ MANIFEST.in | 1 + docs/source/conf.py | 4 +-- pyexcel_ods.yaml | 6 ++--- setup.py | 61 +++++++++++++++++++++++++++++++++++++-------- test.bat | 2 +- test.sh | 2 +- 7 files changed, 66 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 83bc45b..47196b4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Change log ================================================================================ +0.5.1 - 20.10.2017 +-------------------------------------------------------------------------------- + +added +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#. `#103 `_, include LICENSE file + in MANIFEST.in, meaning LICENSE file will appear in the released tar ball. 0.5.0 - 30.08.2017 -------------------------------------------------------------------------------- diff --git a/MANIFEST.in b/MANIFEST.in index 5f13ef0..c2e4b1b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,3 @@ include README.rst +include LICENSE include CHANGELOG.rst diff --git a/docs/source/conf.py b/docs/source/conf.py index 3836c77..fed1d80 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,8 +20,8 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.5.0' -release = '0.5.0' +version = '0.5.1' +release = '0.5.1' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index c72ed07..33358f0 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.5.0 -current_version: 0.5.0 -release: 0.5.0 +version: 0.5.1 +current_version: 0.5.1 +release: 0.5.1 file_type: ods dependencies: - pyexcel-io>=0.5.0 diff --git a/setup.py b/setup.py index 513c5c7..ffd20ba 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,12 @@ -try: - from setuptools import setup, find_packages -except ImportError: - from ez_setup import use_setuptools - use_setuptools() - from setuptools import setup, find_packages +# Template by setupmobans +import os +import codecs +from shutil import rmtree +from setuptools import setup, find_packages, Command NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.5.0' +VERSION = '0.5.1' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -15,8 +14,8 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.5.0.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +DOWNLOAD_URL = '%s/archive/0.5.1.tar.gz' % URL +FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python' ] @@ -44,6 +43,42 @@ INSTALL_REQUIRES = [ PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) EXTRAS_REQUIRE = { } +PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( + sys.executable) +GS_COMMAND = ('gs pyexcel-ods v0.5.1 ' + + "Find 0.5.1 in changelog for more details") +here = os.path.abspath(os.path.dirname(__file__)) + + +class PublishCommand(Command): + """Support setup.py upload.""" + + description = 'Build and publish the package on github and pypi' + user_options = [] + + @staticmethod + def status(s): + """Prints things in bold.""" + print('\033[1m{0}\033[0m'.format(s)) + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + try: + self.status('Removing previous builds…') + rmtree(os.path.join(here, 'dist')) + except OSError: + pass + + self.status('Building Source and Wheel (universal) distribution…') + if os.system(GS_COMMAND) == 0: + os.system(PUBLISH_COMMAND) + + sys.exit() def read_files(*files): @@ -57,7 +92,7 @@ def read_files(*files): def read(afile): """Read a file into setup""" - with open(afile, 'r') as opened_file: + with codecs.open(afile, 'r', 'utf-8') as opened_file: content = filter_out_test_code(opened_file) content = "".join(list(content)) return content @@ -105,5 +140,9 @@ if __name__ == '__main__': packages=PACKAGES, include_package_data=True, zip_safe=False, - classifiers=CLASSIFIERS + classifiers=CLASSIFIERS, + setup_requires=['gease'], + cmdclass={ + 'publish': PublishCommand, + } ) diff --git a/test.bat b/test.bat index 7e4a6fa..ae229d9 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index 7e4a6fa..ae229d9 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long From 54f8b41f9b56101877a0efdbd4f263e794f15c86 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 20 Oct 2017 07:47:46 +0100 Subject: [PATCH 067/111] :bug: fix setup.py where sys is missing --- .moban.d/setup.py | 1 - setup.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.moban.d/setup.py b/.moban.d/setup.py index 2a8e138..b276d5a 100644 --- a/.moban.d/setup.py +++ b/.moban.d/setup.py @@ -5,4 +5,3 @@ {%block compat_block%} {%endblock%} - diff --git a/setup.py b/setup.py index ffd20ba..694a50f 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ # Template by setupmobans import os +import sys import codecs from shutil import rmtree from setuptools import setup, find_packages, Command From 71f4ca1540819df270ddc5d2d5721b57e4716aff Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 23 Oct 2017 18:35:16 +0100 Subject: [PATCH 068/111] :egg: :ferris_wheel: release 0.5.2. related to https://github.com/pyexcel/pyexcel/issues/105 --- CHANGELOG.rst | 9 +++++++++ README.rst | 5 +++-- docs/source/conf.py | 4 ++-- pyexcel_ods.yaml | 8 ++++---- requirements.txt | 2 +- setup.py | 46 +++++++++++++++++++++++++++++++++------------ 6 files changed, 53 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 47196b4..114af9b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.5.2 - 23.10.2017 +-------------------------------------------------------------------------------- + +updated +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +#. pyexcel `#105 `_, remove gease + from setup_requires, introduced by 0.5.1. +#. remove python2.6 test support + 0.5.1 - 20.10.2017 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index 9beea66..c319864 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,8 @@ Fonts, colors and charts are not supported. Installation ================================================================================ -You can install it via pip: + +You can install pyexcel-ods via pip: .. code-block:: bash @@ -53,7 +54,7 @@ product, please `support me on patreon `_. With your financial support, I will be able to invest diff --git a/docs/source/conf.py b/docs/source/conf.py index fed1d80..ffdfa2b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,8 +20,8 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.5.1' -release = '0.5.1' +version = '0.5.2' +release = '0.5.2' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index 33358f0..5136e84 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,11 +1,11 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.5.1 -current_version: 0.5.1 -release: 0.5.1 +version: 0.5.2 +current_version: 0.5.2 +release: 0.5.2 file_type: ods dependencies: - - pyexcel-io>=0.5.0 + - pyexcel-io>=0.5.3 - odfpy>=1.3.3 description: A wrapper library to read, manipulate and write data in ods format diff --git a/requirements.txt b/requirements.txt index 9ffd1b6..61e8b85 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.5.0 +pyexcel-io>=0.5.3 odfpy>=1.3.3 diff --git a/setup.py b/setup.py index 694a50f..ff55dd0 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ from setuptools import setup, find_packages, Command NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.5.1' +VERSION = '0.5.2' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -15,7 +15,7 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.5.1.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.2.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python' @@ -36,7 +36,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.5.0', + 'pyexcel-io>=0.5.3', 'odfpy>=1.3.3', ] @@ -44,11 +44,15 @@ INSTALL_REQUIRES = [ PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) EXTRAS_REQUIRE = { } +# You do not need to read beyond this line PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( sys.executable) -GS_COMMAND = ('gs pyexcel-ods v0.5.1 ' + - "Find 0.5.1 in changelog for more details") -here = os.path.abspath(os.path.dirname(__file__)) +GS_COMMAND = ('gs pyexcel-ods v0.5.2 ' + + "Find 0.5.2 in changelog for more details") +NO_GS_MESSAGE = ('Automatic github release is disabled. ' + + 'Please install gease to enable it.') +UPLOAD_FAILED_MSG = ('Upload failed. please run "%s" yourself.') +HERE = os.path.abspath(os.path.dirname(__file__)) class PublishCommand(Command): @@ -70,18 +74,37 @@ class PublishCommand(Command): def run(self): try: - self.status('Removing previous builds…') - rmtree(os.path.join(here, 'dist')) + self.status('Removing previous builds...') + rmtree(os.path.join(HERE, 'dist')) except OSError: pass - self.status('Building Source and Wheel (universal) distribution…') - if os.system(GS_COMMAND) == 0: - os.system(PUBLISH_COMMAND) + self.status('Building Source and Wheel (universal) distribution...') + run_status = True + if has_gease(): + run_status = os.system(GS_COMMAND) == 0 + else: + self.status(NO_GS_MESSAGE) + if run_status: + if os.system(PUBLISH_COMMAND) != 0: + self.status(UPLOAD_FAILED_MSG % PUBLISH_COMMAND) sys.exit() +def has_gease(): + """ + test if github release command is installed + + visit http://github.com/moremoban/gease for more info + """ + try: + import gease # noqa + return True + except ImportError: + return False + + def read_files(*files): """Read files into setup""" text = "" @@ -142,7 +165,6 @@ if __name__ == '__main__': include_package_data=True, zip_safe=False, classifiers=CLASSIFIERS, - setup_requires=['gease'], cmdclass={ 'publish': PublishCommand, } From 6b80080fd267abf29e492e8f183d81874c24c5aa Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 May 2018 08:15:54 +0100 Subject: [PATCH 069/111] :sparkles: ignore comment in the cell. fix #24 --- pyexcel_ods/odsr.py | 6 ++++-- tests/fixtures/comment-in-cell.ods | Bin 0 -> 7936 bytes tests/test_bug_fixes.py | 6 ++++++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 tests/fixtures/comment-in-cell.ods diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index f4b6c9e..d636b5c 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -88,8 +88,10 @@ class ODSSheet(SheetReader): paragraphs = cell.getElementsByType(P) # for each text node for paragraph in paragraphs: - data = extractText(paragraph) - text_content.append(data) + name_space, tag = paragraph.parentNode.qname + if tag != str('annotation'): + data = extractText(paragraph) + text_content.append(data) return '\n'.join(text_content) diff --git a/tests/fixtures/comment-in-cell.ods b/tests/fixtures/comment-in-cell.ods new file mode 100644 index 0000000000000000000000000000000000000000..b87ce6ee612d010e11969452ac6a797aae258d07 GIT binary patch literal 7936 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 Date: Wed, 23 May 2018 08:22:35 +0100 Subject: [PATCH 070/111] :sparkles: no longer change log is written in rst but yml --- .moban.yml | 3 + CHANGELOG.rst | 131 ++++++++++++++++++++----------------- changelog.yml | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+), 61 deletions(-) create mode 100644 changelog.yml diff --git a/.moban.yml b/.moban.yml index eed4989..4834354 100644 --- a/.moban.yml +++ b/.moban.yml @@ -22,3 +22,6 @@ targets: - "tests/test_stringio.py": "tests/test_stringio.py.jj2" - "tests/test_writer.py": "tests/test_writer.py.jj2" - "tests/base.py": "tests/base.py.jj2" + - output: CHANGELOG.rst + configuration: changelog.yml + template: CHANGELOG.rst.jj2 \ No newline at end of file diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 114af9b..74e06f1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,47 +1,57 @@ Change log ================================================================================ +0.5.3 - unreleased +-------------------------------------------------------------------------------- + +added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `#24 `_, ignore + comments() in cell + 0.5.2 - 23.10.2017 -------------------------------------------------------------------------------- updated -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -#. pyexcel `#105 `_, remove gease - from setup_requires, introduced by 0.5.1. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. pyexcel `pyexcel#105 `_, + remove gease from setup_requires, introduced by 0.5.1. #. remove python2.6 test support 0.5.1 - 20.10.2017 -------------------------------------------------------------------------------- added -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. `#103 `_, include LICENSE file - in MANIFEST.in, meaning LICENSE file will appear in the released tar ball. +#. `pyexcel#103 `_, include + LICENSE file in MANIFEST.in, meaning LICENSE file will appear in the released + tar ball. 0.5.0 - 30.08.2017 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. put dependency on pyexcel-io 0.5.0, which uses cStringIO instead of StringIO. Hence, there will be performance boost in handling files in memory. Relocated --------------------------------------------------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. All ods type conversion code lives in pyexcel_io.service module - 0.4.1 - 25.08.2017 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. `#23 `_, handle unseekable - stream given by http response +#. `pyexcel#23 `_, handle + unseekable stream given by http response #. PR `#22 `_, hanle white spaces in a cell. @@ -49,39 +59,38 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. `#14 `_, close file +#. `pyexcel#14 `_, close file handle -#. pyexcel-io plugin interface now updated to use - `lml `_. - +#. pyexcel-io plugin interface now updated to use `lml + `_. 0.3.3 - 07.05.2017 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. issue `#19 `_, not all texts - in a multi-node cell were extracted. +#. issue `pyexcel#19 `_, not all + texts in a multi-node cell were extracted. 0.3.2 - 13.04.2017 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. issue `#17 `_, empty - new line is ignored -#. issue `#6 `_, PT288H00M00S - is valid duration +#. issue `pyexcel#17 `_, empty new + line is ignored +#. issue `pyexcel#6 `_, + PT288H00M00S is valid duration 0.3.1 - 02.02.2017 -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. Recognize currency type @@ -89,26 +98,24 @@ Added -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. Code refactoring with pyexcel-io v 0.3.0 - 0.2.2 - 24.10.2016 -------------------------------------------------------------------------------- Updated -******************************************************************************** - -#. issue `#14 `_, index error - when reading a ods file that has non-uniform columns repeated property. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. issue `pyexcel#14 `_, index + error when reading a ods file that has non-uniform columns repeated property. 0.2.1 - 31.08.2016 -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. support pagination. two pairs: start_row, row_limit and start_column, column_limit help you deal with large files. @@ -118,114 +125,116 @@ Added -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. By default, `float` will be converted to `int` where fits. `auto_detect_int`, a flag to switch off the autoatic conversion from `float` to `int`. #. 'library=pyexcel-ods' was added so as to inform pyexcel to use it instead of other libraries, in the situation where multiple plugins were installed. - Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. support the auto-import feature of pyexcel-io 0.2.0 - 0.1.1 - 30.01.2016 -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. 'streaming' is an extra option given to get_data. Only when 'streaming' - is explicitly set to True, the data will be consisted of generators, - hence will break your existing code. +#. 'streaming' is an extra option given to get_data. Only when 'streaming' is + explicitly set to True, the data will be consisted of generators, hence will + break your existing code. #. uses yield in to_array and returns a generator #. support multi-line text cell #5 #. feature migration from pyexcel-ods3 pyexcel/pyexcel-ods3#5 Updated -******************************************************************************** -#. compatibility with pyexcel-io 0.1.1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. compatibility with pyexcel-io 0.1.1 0.0.12 - 10.10.2015 -------------------------------------------------------------------------------- Updated -******************************************************************************** -#. Bug fix: excessive trailing columns with empty values +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. Bug fix: excessive trailing columns with empty values 0.0.11 - 26.09.2015 -------------------------------------------------------------------------------- Updated -******************************************************************************** -#. Complete fix for libreoffice datetime field +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. Complete fix for libreoffice datetime field 0.0.10 - 15.09.2015 -------------------------------------------------------------------------------- Updated -******************************************************************************** -#. Bug fix: date field could have datetime from libreoffice +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. Bug fix: date field could have datetime from libreoffice 0.0.9 - 21.08.2015 -------------------------------------------------------------------------------- Updated -******************************************************************************** -#. Bug fix: utf-8 string throw unicode exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. Bug fix: utf-8 string throw unicode exceptions 0.0.8 - 28.06.2015 -------------------------------------------------------------------------------- Updated -******************************************************************************** -#. Pin dependency odfpy 0.9.6 to avoid buggy odfpy 1.3.0 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. Pin dependency odfpy 0.9.6 to avoid buggy odfpy 1.3.0 0.0.7 - 28.05.2015 -------------------------------------------------------------------------------- Updated -******************************************************************************** -#. Bug fix: "number-columns-repeated" is now respected +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. Bug fix: "number-columns-repeated" is now respected 0.0.6 - 21.05.2015 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. get_data and save_data are seen across pyexcel-* extensions. remember them once and use them across all extensions. - 0.0.5 - 22.02.2015 -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. Loads only one sheet from a multiple sheet book #. Use New BSD License - 0.0.4 - 14.12.2014 -------------------------------------------------------------------------------- Updated -******************************************************************************** -#. IO interface update as pyexcel-io introduced keywords. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. IO interface update as pyexcel-io introduced keywords. +#. initial release 0.0.3 - 08.12.2014 -------------------------------------------------------------------------------- +Updated +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. IO interface update as pyexcel-io introduced keywords. #. initial release diff --git a/changelog.yml b/changelog.yml new file mode 100644 index 0000000..82b2de1 --- /dev/null +++ b/changelog.yml @@ -0,0 +1,177 @@ +name: pyexcel-ods +organisation: pyexcel +releases: +- changes: + - action: added + details: + - '`#24`, ignore comments() in cell' + date: unreleased + version: 0.5.3 +- changes: + - action: updated + details: + - pyexcel `pyexcel#105`, remove gease from setup_requires, introduced by 0.5.1. + - remove python2.6 test support + date: 23.10.2017 + version: 0.5.2 +- changes: + - action: added + details: + - '`pyexcel#103`, include LICENSE file in MANIFEST.in, meaning LICENSE file will + appear in the released tar ball.' + date: 20.10.2017 + version: 0.5.1 +- changes: + - action: Updated + details: + - put dependency on pyexcel-io 0.5.0, which uses cStringIO instead of StringIO. Hence, + there will be performance boost in handling files in memory. + - action: Relocated + details: + - All ods type conversion code lives in pyexcel_io.service module + date: 30.08.2017 + version: 0.5.0 +- changes: + - action: Updated + details: + - '`pyexcel#pyexcel-ods#23`, handle unseekable stream given by http response' + - PR `pyexcel#pyexcel-ods#PR#22`, hanle white spaces in a cell. + date: 25.08.2017 + version: 0.4.1 +- changes: + - action: Updated + details: + - '`pyexcel#pyexcel-xlsx#14`, close file handle' + - pyexcel-io plugin interface now updated to use `lml `_. + date: 19.06.2017 + version: 0.4.0 +- changes: + - action: Updated + details: + - issue `pyexcel#pyexcel-odsr#19`, not all texts in a multi-node cell were extracted. + date: 07.05.2017 + version: 0.3.3 +- changes: + - action: Updated + details: + - issue `pyexcel#pyexcel-ods#17`, empty new line is ignored + - issue `pyexcel#pyexcel-ods#6`, PT288H00M00S is valid duration + date: 13.04.2017 + version: 0.3.2 +- changes: + - action: Added + details: + - Recognize currency type + date: 02.02.2017 + version: 0.3.1 +- changes: + - action: Updated + details: + - Code refactoring with pyexcel-io v 0.3.0 + date: 22.12.2016 + version: 0.3.0 +- changes: + - action: Updated + details: + - issue `pyexcel#pyexcel-ods#14`, index error when reading a ods file that has + non-uniform columns repeated property. + date: 24.10.2016 + version: 0.2.2 +- changes: + - action: Added + details: + - 'support pagination. two pairs: start_row, row_limit and start_column, column_limit + help you deal with large files.' + - use odfpy 1.3.3 as compulsory package. offically support python 3 + date: 31.08.2016 + version: 0.2.1 +- changes: + - action: Added + details: + - By default, `float` will be converted to `int` where fits. `auto_detect_int`, a + flag to switch off the autoatic conversion from `float` to `int`. + - '''library=pyexcel-ods'' was added so as to inform pyexcel to use it instead + of other libraries, in the situation where multiple plugins were installed.' + - action: Updated + details: + - support the auto-import feature of pyexcel-io 0.2.0 + date: 01.06.2016 + version: 0.2.0 +- changes: + - action: Added + details: + - '''streaming'' is an extra option given to get_data. Only when ''streaming'' is + explicitly set to True, the data will be consisted of generators, hence will + break your existing code.' + - uses yield in to_array and returns a generator + - 'support multi-line text cell #5' + - feature migration from pyexcel-ods3 pyexcel/pyexcel-ods3#5 + - action: Updated + details: + - compatibility with pyexcel-io 0.1.1 + date: 30.01.2016 + version: 0.1.1 +- changes: + - action: Updated + details: + - 'Bug fix: excessive trailing columns with empty values' + date: 10.10.2015 + version: 0.0.12 +- changes: + - action: Updated + details: + - Complete fix for libreoffice datetime field + date: 26.09.2015 + version: 0.0.11 +- changes: + - action: Updated + details: + - 'Bug fix: date field could have datetime from libreoffice' + date: 15.09.2015 + version: 0.0.10 +- changes: + - action: Updated + details: + - 'Bug fix: utf-8 string throw unicode exceptions' + date: 21.08.2015 + version: 0.0.9 +- changes: + - action: Updated + details: + - Pin dependency odfpy 0.9.6 to avoid buggy odfpy 1.3.0 + date: 28.06.2015 + version: 0.0.8 +- changes: + - action: Updated + details: + - 'Bug fix: "number-columns-repeated" is now respected' + date: 28.05.2015 + version: 0.0.7 +- changes: + - action: Updated + details: + - get_data and save_data are seen across pyexcel-* extensions. remember them once + and use them across all extensions. + date: 21.05.2015 + version: 0.0.6 +- changes: + - action: Added + details: + - Loads only one sheet from a multiple sheet book + - Use New BSD License + date: 22.02.2015 + version: 0.0.5 +- changes: + - action: Updated + details: + - IO interface update as pyexcel-io introduced keywords. + - initial release + date: 14.12.2014 + version: 0.0.4 +- changes: + - action: Updated + details: + - IO interface update as pyexcel-io introduced keywords. + - initial release + date: 08.12.2014 + version: 0.0.3 From 35a0a7440198fce01e48836f8e8b34e82041bb0f Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 May 2018 08:22:53 +0100 Subject: [PATCH 071/111] :handshake: sync using moban --- .gitignore | 1 - LICENSE | 2 +- README.rst | 16 +++++++++++----- docs/source/conf.py | 6 ++---- pyexcel_ods.yaml | 4 ++-- setup.py | 31 +++++++++++++++++++------------ tests/test_formatters.py | 28 +++++++++++++++++----------- tests/test_stringio.py | 6 ++++-- 8 files changed, 56 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index f32c742..e13e7e6 100644 --- a/.gitignore +++ b/.gitignore @@ -96,4 +96,3 @@ ENV/ # moban hashes .moban.hashes .DS_store - diff --git a/LICENSE b/LICENSE index fea8f2d..a038826 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2017 by Onni Software Ltd. and its contributors +Copyright (c) 2015-2018 by Onni Software Ltd. and its contributors All rights reserved. Redistribution and use in source and binary forms of the software as well diff --git a/README.rst b/README.rst index c319864..099fb92 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,10 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png :target: https://www.patreon.com/pyexcel -.. image:: https://api.travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master +.. image:: https://api.bountysource.com/badge/team?team_id=288537 + :target: https://salt.bountysource.com/teams/chfw-pyexcel + +.. image:: https://travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-ods .. image:: https://codecov.io/gh/pyexcel/pyexcel-ods/branch/master/graph/badge.svg @@ -50,13 +53,16 @@ Support the project ================================================================================ If your company has embedded pyexcel and its components into a revenue generating -product, please `support me on patreon `_ to -maintain the project and develop it further. +product, please support me on `patreon `_ +or `bounty source `_ to maintain +the project and develop it further. -If you are an individual, you are welcome to support me too on patreon and for however long -you feel like. As a patreon, you will receive +If you are an individual, you are welcome to support me too and for however long +you feel like. As my backer, you will receive `early access to pyexcel related contents `_. +And your issues will get prioritized if you would like to become my patreon as `pyexcel pro user`. + With your financial support, I will be able to invest a little bit more time in coding, documentation and writing interesting posts. diff --git a/docs/source/conf.py b/docs/source/conf.py index ffdfa2b..4a12bc8 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -9,19 +9,17 @@ extensions = [ 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', ] - intersphinx_mapping = { 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), } -spelling_word_list_filename = 'spelling_wordlist.txt' templates_path = ['_templates'] source_suffix = '.rst' master_doc = 'index' project = u'pyexcel-ods' -copyright = u'2015-2017 Onni Software Ltd.' +copyright = u'2015-2018 Onni Software Ltd.' version = '0.5.2' -release = '0.5.2' +release = '0.5.3' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index 5136e84..f0faac2 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.5.2 -current_version: 0.5.2 +version: 0.5.3 +current_version: 0.5.3 release: 0.5.2 file_type: ods dependencies: diff --git a/setup.py b/setup.py index ff55dd0..e135de3 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,6 @@ -# Template by setupmobans +#!/usr/bin/env python3 + +# Template by pypi-mobans import os import sys import codecs @@ -7,23 +9,20 @@ from setuptools import setup, find_packages, Command NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.5.2' +VERSION = '0.5.3' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( - 'A wrapper library to read, manipulate and write data in ods format' + - '' + 'A wrapper library to read, manipulate and write data in ods format' ) URL = 'https://github.com/pyexcel/pyexcel-ods' DOWNLOAD_URL = '%s/archive/0.5.2.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python' ] CLASSIFIERS = [ - 'Topic :: Office/Business', - 'Topic :: Utilities', 'Topic :: Software Development :: Libraries', 'Programming Language :: Python', 'Intended Audience :: Developers', @@ -39,6 +38,7 @@ INSTALL_REQUIRES = [ 'pyexcel-io>=0.5.3', 'odfpy>=1.3.3', ] +SETUP_COMMANDS = {} PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) @@ -51,7 +51,8 @@ GS_COMMAND = ('gs pyexcel-ods v0.5.2 ' + "Find 0.5.2 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') -UPLOAD_FAILED_MSG = ('Upload failed. please run "%s" yourself.') +UPLOAD_FAILED_MSG = ( + 'Upload failed. please run "%s" yourself.' % PUBLISH_COMMAND) HERE = os.path.abspath(os.path.dirname(__file__)) @@ -76,6 +77,8 @@ class PublishCommand(Command): try: self.status('Removing previous builds...') rmtree(os.path.join(HERE, 'dist')) + rmtree(os.path.join(HERE, 'build')) + rmtree(os.path.join(HERE, 'pyexcel_ods.egg-info')) except OSError: pass @@ -92,6 +95,11 @@ class PublishCommand(Command): sys.exit() +SETUP_COMMANDS.update({ + 'publish': PublishCommand +}) + + def has_gease(): """ test if github release command is installed @@ -116,7 +124,8 @@ def read_files(*files): def read(afile): """Read a file into setup""" - with codecs.open(afile, 'r', 'utf-8') as opened_file: + the_relative_file = os.path.join(HERE, afile) + with codecs.open(the_relative_file, 'r', 'utf-8') as opened_file: content = filter_out_test_code(opened_file) content = "".join(list(content)) return content @@ -165,7 +174,5 @@ if __name__ == '__main__': include_package_data=True, zip_safe=False, classifiers=CLASSIFIERS, - cmdclass={ - 'publish': PublishCommand, - } + cmdclass=SETUP_COMMANDS ) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 79af6b0..e8c907a 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -1,51 +1,57 @@ import os -from unittest import TestCase from textwrap import dedent +from nose.tools import eq_ import pyexcel as pe -class TestAutoDetectInt(TestCase): + + +class TestAutoDetectInt: def setUp(self): self.content = [[1, 2, 3.1]] self.test_file = "test_auto_detect_init.ods" - pe.save_as(array=self.content, dest_file_name=self.test_file) + pe.save_as( + array=self.content, dest_file_name=self.test_file + ) def test_auto_detect_int(self): - sheet = pe.get_sheet(file_name=self.test_file) + sheet = pe.get_sheet(file_name=self.test_file, library="pyexcel-ods") expected = dedent(""" pyexcel_sheet1: +---+---+-----+ | 1 | 2 | 3.1 | +---+---+-----+""").strip() - self.assertEqual(str(sheet), expected) + eq_(str(sheet), expected) def test_get_book_auto_detect_int(self): - book = pe.get_book(file_name=self.test_file) + book = pe.get_book(file_name=self.test_file, library="pyexcel-ods") expected = dedent(""" pyexcel_sheet1: +---+---+-----+ | 1 | 2 | 3.1 | +---+---+-----+""").strip() - self.assertEqual(str(book), expected) + eq_(str(book), expected) def test_auto_detect_int_false(self): - sheet = pe.get_sheet(file_name=self.test_file, auto_detect_int=False) + sheet = pe.get_sheet(file_name=self.test_file, auto_detect_int=False, + library="pyexcel-ods") expected = dedent(""" pyexcel_sheet1: +-----+-----+-----+ | 1.0 | 2.0 | 3.1 | +-----+-----+-----+""").strip() - self.assertEqual(str(sheet), expected) + eq_(str(sheet), expected) def test_get_book_auto_detect_int_false(self): - book = pe.get_book(file_name=self.test_file, auto_detect_int=False) + book = pe.get_book(file_name=self.test_file, auto_detect_int=False, + library="pyexcel-ods") expected = dedent(""" pyexcel_sheet1: +-----+-----+-----+ | 1.0 | 2.0 | 3.1 | +-----+-----+-----+""").strip() - self.assertEqual(str(book), expected) + eq_(str(book), expected) def tearDown(self): os.unlink(self.test_file) diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 4075bb7..f29a465 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -11,7 +11,8 @@ class TestStringIO: create_sample_file1(testfile) with open(testfile, "rb") as f: content = f.read() - r = pyexcel.get_sheet(file_type="ods", file_content=content) + r = pyexcel.get_sheet(file_type="ods", file_content=content, + library="pyexcel-ods") result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] actual = list(r.enumerate()) eq_(result, actual) @@ -25,7 +26,8 @@ class TestStringIO: ] io = pyexcel.save_as(dest_file_type="ods", array=data) - r = pyexcel.get_sheet(file_type="ods", file_content=io.getvalue()) + r = pyexcel.get_sheet(file_type="ods", file_content=io.getvalue(), + library="pyexcel-ods") result = [1, 2, 3, 4, 5, 6] actual = list(r.enumerate()) eq_(result, actual) From f4f4f518842437b53f45e54454deb9e11cfdcf8e Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 May 2018 08:27:08 +0100 Subject: [PATCH 072/111] :microscope: make a test assertion. #24 --- tests/test_bug_fixes.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index bbfa7ef..a723b35 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -129,6 +129,12 @@ def test_issue_23(): def test_issue_24(): + test_file = get_fixtures("comment-in-cell.ods") + data = get_data(test_file) + eq_(data['Sheet1'], [['test']]) + + +def test_issue_25(): test_file = get_fixtures("comment-in-cell.ods") data = get_data(test_file) print(data) From 2b339183ef5c2921160f4e3a21b7f3c7f3133642 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 May 2018 08:35:20 +0100 Subject: [PATCH 073/111] :bug: exception when the type of currency is missing. fix #27 --- pyexcel_ods.yaml | 2 +- pyexcel_ods/odsr.py | 5 ++++- requirements.txt | 2 +- setup.py | 2 +- tests/test_bug_fixes.py | 8 ++++---- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index f0faac2..2993b38 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -7,5 +7,5 @@ release: 0.5.2 file_type: ods dependencies: - pyexcel-io>=0.5.3 - - odfpy>=1.3.3 + - odfpy==1.3.5 description: A wrapper library to read, manipulate and write data in ods format diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index d636b5c..a76a2f3 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -69,7 +69,10 @@ class ODSSheet(SheetReader): elif cell_type == "currency": value = cell.getAttrNS(OFFICENS, value_token) currency = cell.getAttrNS(OFFICENS, cell_type) - ret = value + ' ' + currency + if currency: + ret = value + ' ' + currency + else: + ret = value else: if cell_type in service.VALUE_CONVERTERS: value = cell.getAttrNS(OFFICENS, value_token) diff --git a/requirements.txt b/requirements.txt index 61e8b85..f2d1c2a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ pyexcel-io>=0.5.3 -odfpy>=1.3.3 +odfpy==1.3.5 diff --git a/setup.py b/setup.py index e135de3..78bbbc9 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ CLASSIFIERS = [ INSTALL_REQUIRES = [ 'pyexcel-io>=0.5.3', - 'odfpy>=1.3.3', + 'odfpy==1.3.5', ] SETUP_COMMANDS = {} diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index a723b35..cedfe3d 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -134,10 +134,10 @@ def test_issue_24(): eq_(data['Sheet1'], [['test']]) -def test_issue_25(): - test_file = get_fixtures("comment-in-cell.ods") - data = get_data(test_file) - print(data) +def test_issue_27(): + test_file = get_fixtures("issue_27.ods") + data = get_data(test_file, skip_empty_rows=True) + eq_(data['VGPMX'], [['', 'Cost Basis', '0']]) def get_fixtures(filename): From 66c31c2114ce9328057f8165fdd7580f7535f473 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 May 2018 08:37:22 +0100 Subject: [PATCH 074/111] :newspaper: adding the test fixture. #27 --- tests/fixtures/issue_27.ods | Bin 0 -> 10960 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/fixtures/issue_27.ods diff --git a/tests/fixtures/issue_27.ods b/tests/fixtures/issue_27.ods new file mode 100644 index 0000000000000000000000000000000000000000..86296d2dd9d53f761cc029a3e716426b10b8d03b GIT binary patch literal 10960 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 literal 0 HcmV?d00001 From 1bf415180b6820571965b5106354bf709f2e9c41 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 May 2018 08:39:09 +0100 Subject: [PATCH 075/111] :green_heart: make flake8 happy --- tests/test_formatters.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index e8c907a..b0f261f 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -5,8 +5,6 @@ from nose.tools import eq_ import pyexcel as pe - - class TestAutoDetectInt: def setUp(self): self.content = [[1, 2, 3.1]] From 9839d93a07d8347488a12b898c6f49b2a8f8d7f3 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 May 2018 08:43:43 +0100 Subject: [PATCH 076/111] :egg: :ferris_wheel: release 0.5.3 --- .moban.yml | 2 +- CHANGELOG.rst | 3 +++ changelog.yml | 2 ++ docs/source/conf.py | 2 +- pyexcel_ods.yaml => pyexcel-ods.yml | 2 +- setup.py | 6 +++--- 6 files changed, 11 insertions(+), 6 deletions(-) rename pyexcel_ods.yaml => pyexcel-ods.yml (94%) diff --git a/.moban.yml b/.moban.yml index 4834354..7fa7f64 100644 --- a/.moban.yml +++ b/.moban.yml @@ -4,7 +4,7 @@ configuration: - "commons/templates" - "setupmobans/templates" - ".moban.d" - configuration: pyexcel_ods.yaml + configuration: pyexcel-ods.yml targets: - README.rst: README.rst - setup.py: setup.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 74e06f1..835ec48 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,9 @@ added #. `#24 `_, ignore comments() in cell +#. `#27 `_, exception raised + when currency type is missing +#. fix odfpy version on 1.3.5. 0.5.2 - 23.10.2017 -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index 82b2de1..d8a8f1c 100644 --- a/changelog.yml +++ b/changelog.yml @@ -5,6 +5,8 @@ releases: - action: added details: - '`#24`, ignore comments() in cell' + - '`#27`, exception raised when currency type is missing' + - fix odfpy version on 1.3.5. date: unreleased version: 0.5.3 - changes: diff --git a/docs/source/conf.py b/docs/source/conf.py index 4a12bc8..724852b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,7 +18,7 @@ master_doc = 'index' project = u'pyexcel-ods' copyright = u'2015-2018 Onni Software Ltd.' -version = '0.5.2' +version = '0.5.3' release = '0.5.3' exclude_patterns = [] pygments_style = 'sphinx' diff --git a/pyexcel_ods.yaml b/pyexcel-ods.yml similarity index 94% rename from pyexcel_ods.yaml rename to pyexcel-ods.yml index 2993b38..e7bc035 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel-ods.yml @@ -3,7 +3,7 @@ name: "pyexcel-ods" nick_name: ods version: 0.5.3 current_version: 0.5.3 -release: 0.5.2 +release: 0.5.3 file_type: ods dependencies: - pyexcel-io>=0.5.3 diff --git a/setup.py b/setup.py index 78bbbc9..4e54963 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' ) URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.5.2.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.3.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python' @@ -47,8 +47,8 @@ EXTRAS_REQUIRE = { # You do not need to read beyond this line PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( sys.executable) -GS_COMMAND = ('gs pyexcel-ods v0.5.2 ' + - "Find 0.5.2 in changelog for more details") +GS_COMMAND = ('gs pyexcel-ods v0.5.3 ' + + "Find 0.5.3 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') UPLOAD_FAILED_MSG = ( From da8a864004a503ddc0b5335251a8e951b8e748ad Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 14 Jul 2018 10:49:14 +0100 Subject: [PATCH 077/111] :books: :handshake: sync with pypi-mobans and fix #29, test it against python 3.7 --- .gitignore | 395 +++++++++++++++++++++++++++++++++++++-- LICENSE | 6 +- MANIFEST.in | 1 + README.rst | 19 +- docs/source/conf.py | 168 +++++++++++++++-- setup.py | 93 +++++++-- test.bat | 2 +- test.sh | 2 +- tests/test_formatters.py | 26 +-- tests/test_stringio.py | 6 +- 10 files changed, 654 insertions(+), 64 deletions(-) diff --git a/.gitignore b/.gitignore index f32c742..d09b336 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ -# April 2016 -# reference: https://github.com/github/gitignore/blob/master/Python.gitignore +# moban hashes +.moban.hashes + +# Extra rules from https://github.com/github/gitignore/ +# Python rules # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -10,7 +13,6 @@ __pycache__/ # Distribution / packaging .Python -env/ build/ develop-eggs/ dist/ @@ -22,9 +24,11 @@ lib64/ parts/ sdist/ var/ +wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -44,8 +48,9 @@ htmlcov/ .cache nosetests.xml coverage.xml -*,cover +*.cover .hypothesis/ +.pytest_cache/ # Translations *.mo @@ -54,6 +59,7 @@ coverage.xml # Django stuff: *.log local_settings.py +db.sqlite3 # Flask stuff: instance/ @@ -68,7 +74,7 @@ docs/_build/ # PyBuilder target/ -# IPython Notebook +# Jupyter Notebook .ipynb_checkpoints # pyenv @@ -77,23 +83,388 @@ target/ # celery beat schedule file celerybeat-schedule -# dotenv -.env +# SageMath parsed files +*.sage.py -# virtualenv +# Environments +.env +.venv +env/ venv/ ENV/ +env.bak/ +venv.bak/ # Spyder project settings .spyderproject +.spyproject # Rope project settings .ropeproject -# emacs +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# VirtualEnv rules +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json + +# Linux rules *~ -# moban hashes -.moban.hashes -.DS_store +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# Windows rules +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# macOS rules +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Emacs rules +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# Vim rules +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +# JetBrains rules +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# SublimeText rules +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +# KDevelop4 rules +*.kdev4 +.kdev4/ + +# Kate rules +# Swap Files # +.*.kate-swp +.swp.* + +# TextMate rules +*.tmproj +*.tmproject +tmtags + +# VisualStudioCode rules +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# Xcode rules +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +# Eclipse rules + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# TortoiseGit rules +# Project-level settings +/.tgitconfig + +# Tags rules +# Ignore tags created by etags, ctags, gtags (GNU global) and cscope +TAGS +.TAGS +!TAGS/ +tags +.tags +!tags/ +gtags.files +GTAGS +GRTAGS +GPATH +GSYMS +cscope.files +cscope.out +cscope.in.out +cscope.po.out diff --git a/LICENSE b/LICENSE index fea8f2d..6eef51e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2017 by Onni Software Ltd. and its contributors +Copyright (c) 2015-2018 by Onni Software Ltd. and its contributors All rights reserved. Redistribution and use in source and binary forms of the software as well @@ -13,7 +13,7 @@ that the following conditions are met: and/or other materials provided with the distribution. * Neither the name of 'pyexcel-ods' nor the names of the contributors - may not be used to endorse or promote products derived from this software + may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND @@ -27,4 +27,4 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. \ No newline at end of file +DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in index 5f13ef0..c2e4b1b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,3 @@ include README.rst +include LICENSE include CHANGELOG.rst diff --git a/README.rst b/README.rst index 9beea66..099fb92 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,10 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png :target: https://www.patreon.com/pyexcel -.. image:: https://api.travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master +.. image:: https://api.bountysource.com/badge/team?team_id=288537 + :target: https://salt.bountysource.com/teams/chfw-pyexcel + +.. image:: https://travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-ods .. image:: https://codecov.io/gh/pyexcel/pyexcel-ods/branch/master/graph/badge.svg @@ -30,7 +33,8 @@ Fonts, colors and charts are not supported. Installation ================================================================================ -You can install it via pip: + +You can install pyexcel-ods via pip: .. code-block:: bash @@ -49,13 +53,16 @@ Support the project ================================================================================ If your company has embedded pyexcel and its components into a revenue generating -product, please `support me on patreon `_ to -maintain the project and develop it further. +product, please support me on `patreon `_ +or `bounty source `_ to maintain +the project and develop it further. -If you are an individual, you are welcome to support me too on patreon and for however long -you feel like to. As a patreon, you will receive +If you are an individual, you are welcome to support me too and for however long +you feel like. As my backer, you will receive `early access to pyexcel related contents `_. +And your issues will get prioritized if you would like to become my patreon as `pyexcel pro user`. + With your financial support, I will be able to invest a little bit more time in coding, documentation and writing interesting posts. diff --git a/docs/source/conf.py b/docs/source/conf.py index 4423ccb..93776c7 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -3,6 +3,45 @@ DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' + '' ) +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +# -- Project information ----------------------------------------------------- + +project = u'pyexcel-ods' +copyright = u'2015-2018 Onni Software Ltd.' +author = u'C.W.' + +# The short X.Y version +version = u'0.4.1' +# The full version, including alpha/beta/rc tags +release = u'0.4.1' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', @@ -10,34 +49,128 @@ extensions = [ 'sphinx.ext.viewcode', ] -intersphinx_mapping = { - 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), -} -spelling_word_list_filename = 'spelling_wordlist.txt' +# Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] source_suffix = '.rst' + +# The master toctree document. master_doc = 'index' -project = u'pyexcel-ods' -copyright = u'2015-2017 Onni Software Ltd.' -version = '0.4.1' -release = '0.4.1' +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' -html_theme = 'default' + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. htmlhelp_basename = 'pyexcel-odsdoc' -latex_elements = {} + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'pyexcel-ods.tex', - 'pyexcel-ods Documentation', - 'Onni Software Ltd.', 'manual'), + (master_doc, 'pyexcel-ods.tex', u'pyexcel-ods Documentation', + u'Onni Software Ltd.', 'manual'), ] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'pyexcel-ods', - 'pyexcel-ods Documentation', - [u'Onni Software Ltd.'], 1) + (master_doc, 'pyexcel-ods', u'pyexcel-ods Documentation', + [author], 1) ] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pyexcel-ods', u'pyexcel-ods Documentation', + author, 'pyexcel-ods', 'One line description of project.', + 'Miscellaneous'), +] + +# -- Extension configuration ------------------------------------------------- +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} +# TODO: html_theme not configurable upstream +html_theme = 'default' + +# TODO: DESCRIPTION not configurable upstream texinfo_documents = [ ('index', 'pyexcel-ods', 'pyexcel-ods Documentation', @@ -45,3 +178,6 @@ texinfo_documents = [ DESCRIPTION, 'Miscellaneous'), ] +intersphinx_mapping.update({ + 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), +}) diff --git a/setup.py b/setup.py index e97928e..48b5f7f 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,11 @@ -try: - from setuptools import setup, find_packages -except ImportError: - from ez_setup import use_setuptools - use_setuptools() - from setuptools import setup, find_packages +#!/usr/bin/env python3 + +# Template by pypi-mobans +import os +import sys +import codecs +from shutil import rmtree +from setuptools import setup, find_packages, Command NAME = 'pyexcel-ods' AUTHOR = 'C.W.' @@ -11,8 +13,7 @@ VERSION = '0.4.1' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( - 'A wrapper library to read, manipulate and write data in ods format' + - '' + 'A wrapper library to read, manipulate and write data in ods format' ) URL = 'https://github.com/pyexcel/pyexcel-ods' DOWNLOAD_URL = '%s/archive/0.4.1.tar.gz' % URL @@ -22,8 +23,6 @@ KEYWORDS = [ ] CLASSIFIERS = [ - 'Topic :: Office/Business', - 'Topic :: Utilities', 'Topic :: Software Development :: Libraries', 'Programming Language :: Python', 'Intended Audience :: Developers', @@ -39,11 +38,79 @@ INSTALL_REQUIRES = [ 'pyexcel-io>=0.4.0', 'odfpy>=1.3.3', ] +SETUP_COMMANDS = {} PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) EXTRAS_REQUIRE = { } +# You do not need to read beyond this line +PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( + sys.executable) +GS_COMMAND = ('gs pyexcel-ods v0.4.1 ' + + "Find 0.4.1 in changelog for more details") +NO_GS_MESSAGE = ('Automatic github release is disabled. ' + + 'Please install gease to enable it.') +UPLOAD_FAILED_MSG = ( + 'Upload failed. please run "%s" yourself.' % PUBLISH_COMMAND) +HERE = os.path.abspath(os.path.dirname(__file__)) + + +class PublishCommand(Command): + """Support setup.py upload.""" + + description = 'Build and publish the package on github and pypi' + user_options = [] + + @staticmethod + def status(s): + """Prints things in bold.""" + print('\033[1m{0}\033[0m'.format(s)) + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + try: + self.status('Removing previous builds...') + rmtree(os.path.join(HERE, 'dist')) + rmtree(os.path.join(HERE, 'build')) + rmtree(os.path.join(HERE, 'pyexcel_ods.egg-info')) + except OSError: + pass + + self.status('Building Source and Wheel (universal) distribution...') + run_status = True + if has_gease(): + run_status = os.system(GS_COMMAND) == 0 + else: + self.status(NO_GS_MESSAGE) + if run_status: + if os.system(PUBLISH_COMMAND) != 0: + self.status(UPLOAD_FAILED_MSG % PUBLISH_COMMAND) + + sys.exit() + + +SETUP_COMMANDS.update({ + 'publish': PublishCommand +}) + + +def has_gease(): + """ + test if github release command is installed + + visit http://github.com/moremoban/gease for more info + """ + try: + import gease # noqa + return True + except ImportError: + return False def read_files(*files): @@ -57,7 +124,8 @@ def read_files(*files): def read(afile): """Read a file into setup""" - with open(afile, 'r') as opened_file: + the_relative_file = os.path.join(HERE, afile) + with codecs.open(the_relative_file, 'r', 'utf-8') as opened_file: content = filter_out_test_code(opened_file) content = "".join(list(content)) return content @@ -105,5 +173,6 @@ if __name__ == '__main__': packages=PACKAGES, include_package_data=True, zip_safe=False, - classifiers=CLASSIFIERS + classifiers=CLASSIFIERS, + cmdclass=SETUP_COMMANDS ) diff --git a/test.bat b/test.bat index 7e4a6fa..ae229d9 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index 7e4a6fa..ae229d9 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 79af6b0..b0f261f 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -1,51 +1,55 @@ import os -from unittest import TestCase from textwrap import dedent +from nose.tools import eq_ import pyexcel as pe -class TestAutoDetectInt(TestCase): +class TestAutoDetectInt: def setUp(self): self.content = [[1, 2, 3.1]] self.test_file = "test_auto_detect_init.ods" - pe.save_as(array=self.content, dest_file_name=self.test_file) + pe.save_as( + array=self.content, dest_file_name=self.test_file + ) def test_auto_detect_int(self): - sheet = pe.get_sheet(file_name=self.test_file) + sheet = pe.get_sheet(file_name=self.test_file, library="pyexcel-ods") expected = dedent(""" pyexcel_sheet1: +---+---+-----+ | 1 | 2 | 3.1 | +---+---+-----+""").strip() - self.assertEqual(str(sheet), expected) + eq_(str(sheet), expected) def test_get_book_auto_detect_int(self): - book = pe.get_book(file_name=self.test_file) + book = pe.get_book(file_name=self.test_file, library="pyexcel-ods") expected = dedent(""" pyexcel_sheet1: +---+---+-----+ | 1 | 2 | 3.1 | +---+---+-----+""").strip() - self.assertEqual(str(book), expected) + eq_(str(book), expected) def test_auto_detect_int_false(self): - sheet = pe.get_sheet(file_name=self.test_file, auto_detect_int=False) + sheet = pe.get_sheet(file_name=self.test_file, auto_detect_int=False, + library="pyexcel-ods") expected = dedent(""" pyexcel_sheet1: +-----+-----+-----+ | 1.0 | 2.0 | 3.1 | +-----+-----+-----+""").strip() - self.assertEqual(str(sheet), expected) + eq_(str(sheet), expected) def test_get_book_auto_detect_int_false(self): - book = pe.get_book(file_name=self.test_file, auto_detect_int=False) + book = pe.get_book(file_name=self.test_file, auto_detect_int=False, + library="pyexcel-ods") expected = dedent(""" pyexcel_sheet1: +-----+-----+-----+ | 1.0 | 2.0 | 3.1 | +-----+-----+-----+""").strip() - self.assertEqual(str(book), expected) + eq_(str(book), expected) def tearDown(self): os.unlink(self.test_file) diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 4075bb7..f29a465 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -11,7 +11,8 @@ class TestStringIO: create_sample_file1(testfile) with open(testfile, "rb") as f: content = f.read() - r = pyexcel.get_sheet(file_type="ods", file_content=content) + r = pyexcel.get_sheet(file_type="ods", file_content=content, + library="pyexcel-ods") result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] actual = list(r.enumerate()) eq_(result, actual) @@ -25,7 +26,8 @@ class TestStringIO: ] io = pyexcel.save_as(dest_file_type="ods", array=data) - r = pyexcel.get_sheet(file_type="ods", file_content=io.getvalue()) + r = pyexcel.get_sheet(file_type="ods", file_content=io.getvalue(), + library="pyexcel-ods") result = [1, 2, 3, 4, 5, 6] actual = list(r.enumerate()) eq_(result, actual) From f61c9ebd43a9000e43356761d7901873caad7077 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 14 Jul 2018 10:50:38 +0100 Subject: [PATCH 078/111] :sparkles: fix #29, test it against python 3.7-dev --- .moban.d/travis.yml | 1 + .travis.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.moban.d/travis.yml b/.moban.d/travis.yml index 006a222..a40a09c 100644 --- a/.moban.d/travis.yml +++ b/.moban.d/travis.yml @@ -2,6 +2,7 @@ {%block custom_python_versions%} python: + - 3.7-dev - 3.6 - 3.5 - 3.4 diff --git a/.travis.yml b/.travis.yml index 8f123a4..d0f4dc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: python notifications: email: false python: + - 3.7-dev - 3.6 - 3.5 - 3.4 From 60aea378aecdf6d87486cf9fe32a78b0827642a0 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 26 Nov 2018 07:50:08 +0000 Subject: [PATCH 079/111] :sparkles: make an exception when integer precision loss happens. resolve #30 --- pyexcel-ods.yml | 6 +++--- tests/test_bug_fixes.py | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index e7bc035..c8201fd 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -1,11 +1,11 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.5.3 -current_version: 0.5.3 +version: 0.5.4 +current_version: 0.5.4 release: 0.5.3 file_type: ods dependencies: - - pyexcel-io>=0.5.3 + - pyexcel-io>=0.5.9 - odfpy==1.3.5 description: A wrapper library to read, manipulate and write data in ods format diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index cedfe3d..a99b9cc 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -4,6 +4,7 @@ import os import psutil import pyexcel as pe from pyexcel_ods import get_data, save_data +from pyexcel_io.exceptions import IntegerAccuracyLossError from nose.tools import raises, eq_ from nose import SkipTest @@ -125,7 +126,7 @@ def test_pr_22(): def test_issue_23(): if not IN_TRAVIS: raise SkipTest() - pe.get_book(url="https://github.com/pyexcel/pyexcel-ods/raw/master/tests/fixtures/white_space.ods"); # flake8: noqa + pe.get_book(url="https://github.com/pyexcel/pyexcel-ods/raw/master/tests/fixtures/white_space.ods") # noqa: E501 def test_issue_24(): @@ -140,5 +141,23 @@ def test_issue_27(): eq_(data['VGPMX'], [['', 'Cost Basis', '0']]) +def test_issue_30(): + test_file = "issue_30.ods" + sheet = pe.Sheet() + sheet[0, 0] = 999999999999999 + sheet.save_as(test_file) + sheet2 = pe.get_sheet(file_name=test_file) + eq_(sheet[0, 0], sheet2[0, 0]) + os.unlink(test_file) + + +@raises(IntegerAccuracyLossError) +def test_issue_30_precision_loss(): + test_file = "issue_30_2.ods" + sheet = pe.Sheet() + sheet[0, 0] = 9999999999999999 + sheet.save_as(test_file) + + def get_fixtures(filename): return os.path.join("tests", "fixtures", filename) From 6da58d919068e54bcbbb661bc6e73abc8ee7799f Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 26 Nov 2018 07:50:33 +0000 Subject: [PATCH 080/111] :handshake: update to latest moban, pypi-mobans --- .gitignore | 396 +++++++++++++++++++++++++++++++- .moban.d/tests/requirements.txt | 3 + .moban.yml | 11 +- LICENSE | 4 +- Makefile | 4 + docs/source/conf.py | 197 ++++++++++++++-- requirements.txt | 2 +- rnd_requirements.txt | 2 +- setup.py | 10 +- test.bat | 2 +- test.sh | 2 +- 11 files changed, 585 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index e13e7e6..d09b336 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ -# April 2016 -# reference: https://github.com/github/gitignore/blob/master/Python.gitignore +# moban hashes +.moban.hashes + +# Extra rules from https://github.com/github/gitignore/ +# Python rules # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -10,7 +13,6 @@ __pycache__/ # Distribution / packaging .Python -env/ build/ develop-eggs/ dist/ @@ -22,9 +24,11 @@ lib64/ parts/ sdist/ var/ +wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -44,8 +48,9 @@ htmlcov/ .cache nosetests.xml coverage.xml -*,cover +*.cover .hypothesis/ +.pytest_cache/ # Translations *.mo @@ -54,6 +59,7 @@ coverage.xml # Django stuff: *.log local_settings.py +db.sqlite3 # Flask stuff: instance/ @@ -68,7 +74,7 @@ docs/_build/ # PyBuilder target/ -# IPython Notebook +# Jupyter Notebook .ipynb_checkpoints # pyenv @@ -77,22 +83,388 @@ target/ # celery beat schedule file celerybeat-schedule -# dotenv -.env +# SageMath parsed files +*.sage.py -# virtualenv +# Environments +.env +.venv +env/ venv/ ENV/ +env.bak/ +venv.bak/ # Spyder project settings .spyderproject +.spyproject # Rope project settings .ropeproject -# emacs +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# VirtualEnv rules +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json + +# Linux rules *~ -# moban hashes -.moban.hashes -.DS_store +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# Windows rules +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# macOS rules +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Emacs rules +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# Vim rules +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +# JetBrains rules +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# SublimeText rules +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +# KDevelop4 rules +*.kdev4 +.kdev4/ + +# Kate rules +# Swap Files # +.*.kate-swp +.swp.* + +# TextMate rules +*.tmproj +*.tmproject +tmtags + +# VisualStudioCode rules +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# Xcode rules +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +# Eclipse rules + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# TortoiseGit rules +# Project-level settings +/.tgitconfig + +# Tags rules +# Ignore tags created by etags, ctags, gtags (GNU global) and cscope +TAGS +.TAGS +!TAGS/ +tags +.tags +!tags/ +gtags.files +GTAGS +GRTAGS +GPATH +GSYMS +cscope.files +cscope.out +cscope.in.out +cscope.po.out diff --git a/.moban.d/tests/requirements.txt b/.moban.d/tests/requirements.txt index 962ea54..c2b0c7e 100644 --- a/.moban.d/tests/requirements.txt +++ b/.moban.d/tests/requirements.txt @@ -1,5 +1,8 @@ {% extends 'tests/requirements.txt.jj2' %} {%block extras %} +moban +black;python_version>="3.6" +isort;python_version>="3.6" psutil pyexcel pyexcel-xls diff --git a/.moban.yml b/.moban.yml index 7fa7f64..7d0fe4d 100644 --- a/.moban.yml +++ b/.moban.yml @@ -1,8 +1,13 @@ +requires: + - type: git + url: https://github.com/moremoban/pypi-mobans + submodule: true + - https://github.com/pyexcel/pyexcel-mobans configuration: - configuration_dir: "commons/config" + configuration_dir: "pyexcel-mobans:config" template_dir: - - "commons/templates" - - "setupmobans/templates" + - "pyexcel-mobans:templates" + - "pypi-mobans:templates" - ".moban.d" configuration: pyexcel-ods.yml targets: diff --git a/LICENSE b/LICENSE index a038826..6eef51e 100644 --- a/LICENSE +++ b/LICENSE @@ -13,7 +13,7 @@ that the following conditions are met: and/or other materials provided with the distribution. * Neither the name of 'pyexcel-ods' nor the names of the contributors - may not be used to endorse or promote products derived from this software + may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND @@ -27,4 +27,4 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. \ No newline at end of file +DAMAGE. diff --git a/Makefile b/Makefile index 10b28ae..62b93c1 100644 --- a/Makefile +++ b/Makefile @@ -3,3 +3,7 @@ all: test test: bash test.sh +format: + isort -y $(find pyexcel_ods -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) + black -l 79 pyexcel_ods + black -l 79 tests diff --git a/docs/source/conf.py b/docs/source/conf.py index 724852b..cc38149 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -3,39 +3,187 @@ DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' + '' ) -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.viewcode', -] -intersphinx_mapping = { - 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), -} -templates_path = ['_templates'] -source_suffix = '.rst' -master_doc = 'index' +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +# -- Project information ----------------------------------------------------- project = u'pyexcel-ods' copyright = u'2015-2018 Onni Software Ltd.' -version = '0.5.3' -release = '0.5.3' +author = u'C.W.' + +# The short X.Y version +version = u'0.5.3' +# The full version, including alpha/beta/rc tags +release = u'0.5.4' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode',] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] -pygments_style = 'sphinx' -html_theme = 'default' + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. htmlhelp_basename = 'pyexcel-odsdoc' -latex_elements = {} + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'pyexcel-ods.tex', - 'pyexcel-ods Documentation', - 'Onni Software Ltd.', 'manual'), + (master_doc, 'pyexcel-ods.tex', u'pyexcel-ods Documentation', + u'Onni Software Ltd.', 'manual'), ] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'pyexcel-ods', - 'pyexcel-ods Documentation', - [u'Onni Software Ltd.'], 1) + (master_doc, 'pyexcel-ods', u'pyexcel-ods Documentation', + [author], 1) ] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pyexcel-ods', u'pyexcel-ods Documentation', + author, 'pyexcel-ods', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + +# -- Extension configuration ------------------------------------------------- +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} +# TODO: html_theme not configurable upstream +html_theme = 'default' + +# TODO: DESCRIPTION not configurable upstream texinfo_documents = [ ('index', 'pyexcel-ods', 'pyexcel-ods Documentation', @@ -43,3 +191,6 @@ texinfo_documents = [ DESCRIPTION, 'Miscellaneous'), ] +intersphinx_mapping.update({ + 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), +}) diff --git a/requirements.txt b/requirements.txt index f2d1c2a..0827da9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.5.3 +pyexcel-io>=0.5.9 odfpy==1.3.5 diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 2ce1c92..8daba26 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,2 +1,2 @@ -https://github.com/pyexcel/pyexcel/archive/master.zip +https://github.com/pyexcel/pyexcel-io/archive/v0.5.10.zip diff --git a/setup.py b/setup.py index 4e54963..1199d49 100644 --- a/setup.py +++ b/setup.py @@ -5,11 +5,13 @@ import os import sys import codecs from shutil import rmtree -from setuptools import setup, find_packages, Command + +from setuptools import Command, setup, find_packages + NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.5.3' +VERSION = '0.5.4' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -19,7 +21,7 @@ URL = 'https://github.com/pyexcel/pyexcel-ods' DOWNLOAD_URL = '%s/archive/0.5.3.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ - 'python' + 'python', ] CLASSIFIERS = [ @@ -35,7 +37,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.5.3', + 'pyexcel-io>=0.5.9', 'odfpy==1.3.5', ] SETUP_COMMANDS = {} diff --git a/test.bat b/test.bat index ae229d9..ad920bb 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_ods && flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index ae229d9..ad920bb 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_ods && flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long From 902e0b4e0e9fe480253ae28ecb1d387ab551efce Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 26 Nov 2018 07:55:41 +0000 Subject: [PATCH 081/111] :fire: remove python 3.3 and 2.6 test and adding 3.7-dev --- .moban.d/travis.yml | 3 +-- .travis.yml | 3 +-- tests/requirements.txt | 3 +++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.moban.d/travis.yml b/.moban.d/travis.yml index 006a222..8da65a9 100644 --- a/.moban.d/travis.yml +++ b/.moban.d/travis.yml @@ -2,11 +2,10 @@ {%block custom_python_versions%} python: + - 3.7-dev - 3.6 - 3.5 - 3.4 - - 3.3 - 2.7 - - 2.6 {%endblock%} diff --git a/.travis.yml b/.travis.yml index 8f123a4..e02c27d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,11 @@ language: python notifications: email: false python: + - 3.7-dev - 3.6 - 3.5 - 3.4 - - 3.3 - 2.7 - - 2.6 before_install: - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install flake8==2.6.2; fi - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then diff --git a/tests/requirements.txt b/tests/requirements.txt index 4b23de1..7a755ef 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,6 +3,9 @@ mock;python_version<"3" codecov coverage flake8 +moban +black;python_version>="3.6" +isort;python_version>="3.6" psutil pyexcel pyexcel-xls From ce04e9e6797df477e5310ec7ac3881e4a16570e7 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 26 Nov 2018 07:56:21 +0000 Subject: [PATCH 082/111] :hammer: make format using isort and black --- pyexcel_ods/__init__.py | 16 ++++++---- pyexcel_ods/odsr.py | 34 ++++++++++++--------- pyexcel_ods/odsw.py | 23 +++++++------- setup.py | 5 ++-- tests/base.py | 30 ++++++++++--------- tests/test_bug_fixes.py | 53 ++++++++++++++++----------------- tests/test_filter.py | 49 +++++++++++++++++------------- tests/test_formatters.py | 44 +++++++++++++++++---------- tests/test_multiline_feature.py | 5 ++-- tests/test_multiple_sheets.py | 25 ++++++++-------- tests/test_ods_reader.py | 11 +++---- tests/test_stringio.py | 23 +++++++------- tests/test_writer.py | 7 +++-- 13 files changed, 179 insertions(+), 146 deletions(-) diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index 70c50de..3c2a28b 100644 --- a/pyexcel_ods/__init__.py +++ b/pyexcel_ods/__init__.py @@ -9,17 +9,21 @@ # this line has to be place above all else # because of dynamic import from pyexcel_io.plugins import IOPluginInfoChain -from pyexcel_io.io import get_data as read_data, isstream, store_data as write_data +from pyexcel_io.io import ( + get_data as read_data, + isstream, + store_data as write_data, +) -__FILE_TYPE__ = 'ods' +__FILE_TYPE__ = "ods" IOPluginInfoChain(__name__).add_a_reader( - relative_plugin_class_path='odsr.ODSBook', + relative_plugin_class_path="odsr.ODSBook", file_types=[__FILE_TYPE__], - stream_type='binary' + stream_type="binary", ).add_a_writer( - relative_plugin_class_path='odsw.ODSWriter', + relative_plugin_class_path="odsw.ODSWriter", file_types=[__FILE_TYPE__], - stream_type='binary' + stream_type="binary", ) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index a76a2f3..3559ffe 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -21,21 +21,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Thanks to grt for the fixes -from odf.teletype import extractText -from odf.table import TableRow, TableCell, Table -from odf.text import P +import pyexcel_io.service as service from odf.namespaces import OFFICENS from odf.opendocument import load +from odf.table import Table, TableCell, TableRow +# Thanks to grt for the fixes +from odf.teletype import extractText +from odf.text import P +from pyexcel_io._compact import OrderedDict from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader -from pyexcel_io._compact import OrderedDict -import pyexcel_io.service as service class ODSSheet(SheetReader): """native ods sheet""" + def __init__(self, sheet, auto_detect_int=True, **keywords): SheetReader.__init__(self, sheet, **keywords) self.__auto_detect_int = auto_detect_int @@ -70,14 +71,14 @@ class ODSSheet(SheetReader): value = cell.getAttrNS(OFFICENS, value_token) currency = cell.getAttrNS(OFFICENS, cell_type) if currency: - ret = value + ' ' + currency + ret = value + " " + currency else: ret = value else: if cell_type in service.VALUE_CONVERTERS: value = cell.getAttrNS(OFFICENS, value_token) n_value = service.VALUE_CONVERTERS[cell_type](value) - if cell_type == 'float' and self.__auto_detect_int: + if cell_type == "float" and self.__auto_detect_int: if service.has_no_digits_in_float(n_value): n_value = int(n_value) ret = n_value @@ -92,14 +93,15 @@ class ODSSheet(SheetReader): # for each text node for paragraph in paragraphs: name_space, tag = paragraph.parentNode.qname - if tag != str('annotation'): + if tag != str("annotation"): data = extractText(paragraph) text_content.append(data) - return '\n'.join(text_content) + return "\n".join(text_content) class ODSBook(BookReader): """read ods book""" + def open(self, file_name, **keywords): """open ods file""" BookReader.open(self, file_name, **keywords) @@ -113,8 +115,11 @@ class ODSBook(BookReader): 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] + 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: @@ -127,8 +132,9 @@ class ODSBook(BookReader): if sheet_index < length: return self.read_sheet(tables[sheet_index]) else: - raise IndexError("Index %d of out bound %d" % ( - sheet_index, length)) + raise IndexError( + "Index %d of out bound %d" % (sheet_index, length) + ) def read_all(self): """read all sheets""" diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index 3be88c2..c911517 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -9,16 +9,14 @@ """ import sys -from odf.table import TableRow, TableCell, Table -from odf.text import P +import pyexcel_io.service as converter from odf.namespaces import OFFICENS from odf.opendocument import OpenDocumentSpreadsheet - +from odf.table import Table, TableCell, TableRow +from odf.text import P from pyexcel_io.book import BookWriter from pyexcel_io.sheet import SheetWriter -import pyexcel_io.service as converter - PY2 = sys.version_info[0] == 2 PY27_BELOW = PY2 and sys.version_info[1] < 7 @@ -28,6 +26,7 @@ class ODSSheetWriter(SheetWriter): """ ODS sheet writer """ + def set_sheet_name(self, name): """initialize the native table""" self._native_sheet = Table(name=name) @@ -41,19 +40,22 @@ class ODSSheetWriter(SheetWriter): cell_to_be_written = TableCell() cell_type = type(cell) cell_odf_type = converter.ODS_WRITE_FORMAT_COVERSION.get( - cell_type, "string") + cell_type, "string" + ) cell_to_be_written.setAttrNS(OFFICENS, "value-type", cell_odf_type) cell_odf_value_token = converter.VALUE_TOKEN.get( - cell_odf_type, "value") + cell_odf_type, "value" + ) converter_func = converter.ODS_VALUE_CONVERTERS.get( - cell_odf_type, None) + cell_odf_type, None + ) if converter_func: cell = converter_func(cell) - if cell_odf_type != 'string': + if cell_odf_type != "string": cell_to_be_written.setAttrNS(OFFICENS, cell_odf_value_token, cell) cell_to_be_written.addElement(P(text=cell)) else: - lines = cell.split('\n') + lines = cell.split("\n") for line in lines: cell_to_be_written.addElement(P(text=line)) row.addElement(cell_to_be_written) @@ -80,6 +82,7 @@ class ODSWriter(BookWriter): open document spreadsheet writer """ + def __init__(self): BookWriter.__init__(self) self._native_book = OpenDocumentSpreadsheet() diff --git a/setup.py b/setup.py index 1199d49..98d8564 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,12 @@ #!/usr/bin/env python3 +import codecs # Template by pypi-mobans import os import sys -import codecs from shutil import rmtree -from setuptools import Command, setup, find_packages - +from setuptools import Command, find_packages, setup NAME = 'pyexcel-ods' AUTHOR = 'C.W.' diff --git a/tests/base.py b/tests/base.py index e469574..c312a6a 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,11 +1,12 @@ -import os # noqa -import pyexcel import datetime # noqa -from nose.tools import raises, eq_ # noqa +import os # noqa + +import pyexcel +from nose.tools import eq_, raises # noqa def create_sample_file1(file): - data = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] + data = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", 1.1, 1] table = [] table.append(data[:4]) table.append(data[4:8]) @@ -17,10 +18,11 @@ class PyexcelHatWriterBase: """ Abstract functional test for hat writers """ + content = { "X": [1, 2, 3, 4, 5], "Y": [6, 7, 8, 9, 10], - "Z": [11, 12, 13, 14, 15] + "Z": [11, 12, 13, 14, 15], } def test_series_table(self): @@ -36,11 +38,12 @@ class PyexcelWriterBase: testfile and testfile2 have to be initialized before it is used for testing """ + content = [ [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], - [1, 2, 3, 4, 5] + [1, 2, 3, 4, 5], ] def _create_a_file(self, file): @@ -54,7 +57,6 @@ class PyexcelWriterBase: class PyexcelMultipleSheetBase: - def _write_test_file(self, filename): pyexcel.save_book_as(bookdict=self.content, dest_file_name=filename) @@ -80,7 +82,7 @@ class PyexcelMultipleSheetBase: expected = [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]] assert data == expected data = list(b["Sheet3"].rows()) - expected = [[u'X', u'Y', u'Z'], [1, 4, 7], [2, 5, 8], [3, 6, 9]] + expected = [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]] assert data == expected sheet3 = b["Sheet3"] sheet3.name_columns_by_row(0) @@ -90,7 +92,6 @@ class PyexcelMultipleSheetBase: class ODSCellTypes: - def test_formats(self): # date formats date_format = "%d/%m/%Y" @@ -104,9 +105,10 @@ class ODSCellTypes: eq_(self.data["Sheet1"][1][1].strftime(time_format), "12:12:11") eq_(self.data["Sheet1"][2][1].strftime(time_format), "12:00:00") eq_(self.data["Sheet1"][3][1], 0) - eq_(self.data["Sheet1"][4][1], datetime.timedelta(hours=27, - minutes=17, - seconds=54)) + eq_( + self.data["Sheet1"][4][1], + datetime.timedelta(hours=27, minutes=17, seconds=54), + ) eq_(self.data["Sheet1"][5][1], "Other") # boolean eq_(self.data["Sheet1"][0][2], "Boolean") @@ -117,8 +119,8 @@ class ODSCellTypes: eq_(self.data["Sheet1"][1][3], 11.11) # Currency eq_(self.data["Sheet1"][0][4], "Currency") - eq_(self.data["Sheet1"][1][4], '1 GBP') - eq_(self.data["Sheet1"][2][4], '-10000 GBP') + eq_(self.data["Sheet1"][1][4], "1 GBP") + eq_(self.data["Sheet1"][2][4], "-10000 GBP") # Percentage eq_(self.data["Sheet1"][0][5], "Percentage") eq_(self.data["Sheet1"][1][5], 2) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index a99b9cc..72ab370 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -1,19 +1,21 @@ #!/usr/bin/python # -*- encoding: utf-8 -*- import os + import psutil import pyexcel as pe -from pyexcel_ods import get_data, save_data -from pyexcel_io.exceptions import IntegerAccuracyLossError -from nose.tools import raises, eq_ from nose import SkipTest +from nose.tools import eq_, raises +from pyexcel_io.exceptions import IntegerAccuracyLossError -IN_TRAVIS = 'TRAVIS' in os.environ +from pyexcel_ods import get_data, save_data + +IN_TRAVIS = "TRAVIS" in os.environ def test_bug_fix_for_issue_1(): data = get_data(get_fixtures("repeated.ods")) - eq_(data["Sheet1"], [['repeated', 'repeated', 'repeated', 'repeated']]) + eq_(data["Sheet1"], [["repeated", "repeated", "repeated", "repeated"]]) def test_bug_fix_for_issue_2(): @@ -22,12 +24,13 @@ def test_bug_fix_for_issue_2(): data.update({"Sheet 2": [[u"row 1", u"Héllô!", u"HolÁ!"]]}) save_data("your_file.ods", data) new_data = get_data("your_file.ods") - assert new_data["Sheet 2"] == [[u'row 1', u'H\xe9ll\xf4!', u'Hol\xc1!']] + assert new_data["Sheet 2"] == [[u"row 1", u"H\xe9ll\xf4!", u"Hol\xc1!"]] @raises(Exception) def test_invalid_date(): from pyexcel_ods.ods import date_value + value = "2015-08-" date_value(value) @@ -35,30 +38,27 @@ def test_invalid_date(): @raises(Exception) def test_fake_date_time_10(): from pyexcel_ods.ods import date_value + date_value("1234567890") @raises(Exception) def test_fake_date_time_19(): from pyexcel_ods.ods import date_value + date_value("1234567890123456789") @raises(Exception) def test_fake_date_time_20(): from pyexcel_ods.ods import date_value + date_value("12345678901234567890") def test_issue_13(): test_file = "test_issue_13.ods" - data = [ - [1, 2], - [], - [], - [], - [3, 4] - ] + data = [[1, 2], [], [], [], [3, 4]] save_data(test_file, {test_file: data}) written_data = get_data(test_file, skip_empty_rows=False) eq_(data, written_data[test_file]) @@ -68,23 +68,20 @@ def test_issue_13(): def test_issue_14(): # pyexcel issue 61 test_file = "issue_61.ods" - data = get_data(get_fixtures(test_file), - skip_empty_rows=True) - eq_(data['S-LMC'], [[u'aaa'], [0]]) + data = get_data(get_fixtures(test_file), skip_empty_rows=True) + eq_(data["S-LMC"], [[u"aaa"], [0]]) def test_issue_6(): test_file = "12_day_as_time.ods" - data = get_data(get_fixtures(test_file), - skip_empty_rows=True) - eq_(data['Sheet1'][0][0].days, 12) + data = get_data(get_fixtures(test_file), skip_empty_rows=True) + eq_(data["Sheet1"][0][0].days, 12) def test_issue_19(): test_file = "pyexcel_81_ods_19.ods" - data = get_data(get_fixtures(test_file), - skip_empty_rows=True) - eq_(data['product.template'][1][1], 'PRODUCT NAME PMP') + data = get_data(get_fixtures(test_file), skip_empty_rows=True) + eq_(data["product.template"][1][1], "PRODUCT NAME PMP") def test_issue_83_ods_file_handle(): @@ -95,7 +92,7 @@ def test_issue_83_ods_file_handle(): open_files_l1 = proc.open_files() # start with a csv file - data = pe.iget_array(file_name=test_file, library='pyexcel-ods') + data = pe.iget_array(file_name=test_file, library="pyexcel-ods") open_files_l2 = proc.open_files() delta = len(open_files_l2) - len(open_files_l1) # cannot catch open file handle @@ -120,25 +117,27 @@ def test_pr_22(): test_file = get_fixtures("white_space.ods") data = get_data(test_file) # OrderedDict([(u'Sheet1', [[u'paragraph with tab, space, new line']])]) - eq_(data['Sheet1'][0][0], 'paragraph with tab(\t), space, \nnew line') + eq_(data["Sheet1"][0][0], "paragraph with tab(\t), space, \nnew line") def test_issue_23(): if not IN_TRAVIS: raise SkipTest() - pe.get_book(url="https://github.com/pyexcel/pyexcel-ods/raw/master/tests/fixtures/white_space.ods") # noqa: E501 + pe.get_book( + url="https://github.com/pyexcel/pyexcel-ods/raw/master/tests/fixtures/white_space.ods" + ) # noqa: E501 def test_issue_24(): test_file = get_fixtures("comment-in-cell.ods") data = get_data(test_file) - eq_(data['Sheet1'], [['test']]) + eq_(data["Sheet1"], [["test"]]) def test_issue_27(): test_file = get_fixtures("issue_27.ods") data = get_data(test_file, skip_empty_rows=True) - eq_(data['VGPMX'], [['', 'Cost Basis', '0']]) + eq_(data["VGPMX"], [["", "Cost Basis", "0"]]) def test_issue_30(): diff --git a/tests/test_filter.py b/tests/test_filter.py index b74bc4c..67d8876 100644 --- a/tests/test_filter.py +++ b/tests/test_filter.py @@ -1,7 +1,7 @@ import os -from pyexcel_io import get_data, save_data from nose.tools import eq_ +from pyexcel_io import get_data, save_data class TestFilter: @@ -13,49 +13,58 @@ class TestFilter: [3, 23, 33], [4, 24, 34], [5, 25, 35], - [6, 26, 36] + [6, 26, 36], ] save_data(self.test_file, sample) self.sheet_name = "pyexcel_sheet1" def test_filter_row(self): - filtered_data = get_data(self.test_file, start_row=3, - library="pyexcel-ods") + filtered_data = get_data( + self.test_file, start_row=3, library="pyexcel-ods" + ) expected = [[4, 24, 34], [5, 25, 35], [6, 26, 36]] eq_(filtered_data[self.sheet_name], expected) def test_filter_row_2(self): - filtered_data = get_data(self.test_file, start_row=3, row_limit=1, - library="pyexcel-ods") + filtered_data = get_data( + self.test_file, start_row=3, row_limit=1, library="pyexcel-ods" + ) expected = [[4, 24, 34]] eq_(filtered_data[self.sheet_name], expected) def test_filter_column(self): - filtered_data = get_data(self.test_file, start_column=1, - library="pyexcel-ods") - expected = [[21, 31], [22, 32], [23, 33], - [24, 34], [25, 35], [26, 36]] + filtered_data = get_data( + self.test_file, start_column=1, library="pyexcel-ods" + ) + expected = [[21, 31], [22, 32], [23, 33], [24, 34], [25, 35], [26, 36]] eq_(filtered_data[self.sheet_name], expected) def test_filter_column_2(self): - filtered_data = get_data(self.test_file, - start_column=1, column_limit=1, - library="pyexcel-ods") + filtered_data = get_data( + self.test_file, + start_column=1, + column_limit=1, + library="pyexcel-ods", + ) expected = [[21], [22], [23], [24], [25], [26]] eq_(filtered_data[self.sheet_name], expected) def test_filter_both_ways(self): - filtered_data = get_data(self.test_file, - start_column=1, start_row=3, - library="pyexcel-ods") + filtered_data = get_data( + self.test_file, start_column=1, start_row=3, library="pyexcel-ods" + ) expected = [[24, 34], [25, 35], [26, 36]] eq_(filtered_data[self.sheet_name], expected) def test_filter_both_ways_2(self): - filtered_data = get_data(self.test_file, - start_column=1, column_limit=1, - start_row=3, row_limit=1, - library="pyexcel-ods") + filtered_data = get_data( + self.test_file, + start_column=1, + column_limit=1, + start_row=3, + row_limit=1, + library="pyexcel-ods", + ) expected = [[24]] eq_(filtered_data[self.sheet_name], expected) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index b0f261f..ba78ec2 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -1,54 +1,66 @@ import os from textwrap import dedent -from nose.tools import eq_ import pyexcel as pe +from nose.tools import eq_ class TestAutoDetectInt: def setUp(self): self.content = [[1, 2, 3.1]] self.test_file = "test_auto_detect_init.ods" - pe.save_as( - array=self.content, dest_file_name=self.test_file - ) + pe.save_as(array=self.content, dest_file_name=self.test_file) def test_auto_detect_int(self): sheet = pe.get_sheet(file_name=self.test_file, library="pyexcel-ods") - expected = dedent(""" + expected = dedent( + """ pyexcel_sheet1: +---+---+-----+ | 1 | 2 | 3.1 | - +---+---+-----+""").strip() + +---+---+-----+""" + ).strip() eq_(str(sheet), expected) def test_get_book_auto_detect_int(self): book = pe.get_book(file_name=self.test_file, library="pyexcel-ods") - expected = dedent(""" + expected = dedent( + """ pyexcel_sheet1: +---+---+-----+ | 1 | 2 | 3.1 | - +---+---+-----+""").strip() + +---+---+-----+""" + ).strip() eq_(str(book), expected) def test_auto_detect_int_false(self): - sheet = pe.get_sheet(file_name=self.test_file, auto_detect_int=False, - library="pyexcel-ods") - expected = dedent(""" + sheet = pe.get_sheet( + file_name=self.test_file, + auto_detect_int=False, + library="pyexcel-ods", + ) + expected = dedent( + """ pyexcel_sheet1: +-----+-----+-----+ | 1.0 | 2.0 | 3.1 | - +-----+-----+-----+""").strip() + +-----+-----+-----+""" + ).strip() eq_(str(sheet), expected) def test_get_book_auto_detect_int_false(self): - book = pe.get_book(file_name=self.test_file, auto_detect_int=False, - library="pyexcel-ods") - expected = dedent(""" + book = pe.get_book( + file_name=self.test_file, + auto_detect_int=False, + library="pyexcel-ods", + ) + expected = dedent( + """ pyexcel_sheet1: +-----+-----+-----+ | 1.0 | 2.0 | 3.1 | - +-----+-----+-----+""").strip() + +-----+-----+-----+""" + ).strip() eq_(str(book), expected) def tearDown(self): diff --git a/tests/test_multiline_feature.py b/tests/test_multiline_feature.py index 8d049a4..aa2c870 100644 --- a/tests/test_multiline_feature.py +++ b/tests/test_multiline_feature.py @@ -1,12 +1,13 @@ import os + import pyexcel def test_reading_multiline_ods(): testfile = os.path.join("tests", "fixtures", "multilineods.ods") sheet = pyexcel.get_sheet(file_name=testfile) - assert sheet[0, 0] == '1\n2\n3\n4' - assert sheet[1, 0] == 'Line 1\n\nLine 2' + assert sheet[0, 0] == "1\n2\n3\n4" + assert sheet[1, 0] == "Line 1\n\nLine 2" def test_writing_multiline_ods(): diff --git a/tests/test_multiple_sheets.py b/tests/test_multiple_sheets.py index 6d60dbb..6360be6 100644 --- a/tests/test_multiple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -1,7 +1,9 @@ import os import sys + import pyexcel from nose.tools import raises + from base import PyexcelMultipleSheetBase if sys.version_info[0] == 2 and sys.version_info[1] < 7: @@ -42,8 +44,7 @@ class TestAddBooks: 3,3,3,3 """ self.rows = 3 - pyexcel.save_book_as(bookdict=self.content, - dest_file_name=file) + pyexcel.save_book_as(bookdict=self.content, dest_file_name=file) def setUp(self): self.testfile = "multiple1.ods" @@ -55,12 +56,12 @@ class TestAddBooks: def test_load_a_single_sheet(self): b1 = pyexcel.get_book(file_name=self.testfile, sheet_name="Sheet1") assert len(b1.sheet_names()) == 1 - assert b1['Sheet1'].to_array() == self.content['Sheet1'] + assert b1["Sheet1"].to_array() == self.content["Sheet1"] def test_load_a_single_sheet2(self): b1 = pyexcel.load_book(self.testfile, sheet_index=0) assert len(b1.sheet_names()) == 1 - assert b1['Sheet1'].to_array() == self.content['Sheet1'] + assert b1["Sheet1"].to_array() == self.content["Sheet1"] @raises(IndexError) def test_load_a_single_sheet3(self): @@ -229,17 +230,17 @@ class TestMultiSheetReader: self.testfile = "file_with_an_empty_sheet.ods" def test_reader_with_correct_sheets(self): - r = pyexcel.BookReader(os.path.join("tests", "fixtures", - self.testfile)) + r = pyexcel.BookReader( + os.path.join("tests", "fixtures", self.testfile) + ) assert r.number_of_sheets() == 3 def _produce_ordered_dict(): data_dict = OrderedDict() - data_dict.update({ - "Sheet1": [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]}) - data_dict.update({ - "Sheet2": [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]]}) - data_dict.update({ - "Sheet3": [[u'X', u'Y', u'Z'], [1, 4, 7], [2, 5, 8], [3, 6, 9]]}) + data_dict.update({"Sheet1": [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]}) + data_dict.update({"Sheet2": [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]]}) + data_dict.update( + {"Sheet3": [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]]} + ) return data_dict diff --git a/tests/test_ods_reader.py b/tests/test_ods_reader.py index cf7c1f3..69bb030 100644 --- a/tests/test_ods_reader.py +++ b/tests/test_ods_reader.py @@ -1,15 +1,14 @@ import os + +from base import ODSCellTypes from pyexcel_ods.odsr import ODSBook from pyexcel_ods.odsw import ODSWriter -from base import ODSCellTypes class TestODSReader(ODSCellTypes): def setUp(self): r = ODSBook() - r.open(os.path.join("tests", - "fixtures", - "ods_formats.ods")) + r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) self.data = r.read_all() for key in self.data.keys(): self.data[key] = list(self.data[key]) @@ -19,9 +18,7 @@ class TestODSReader(ODSCellTypes): class TestODSWriter(ODSCellTypes): def setUp(self): r = ODSBook() - r.open(os.path.join("tests", - "fixtures", - "ods_formats.ods")) + r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) self.data1 = r.read_all() self.testfile = "odswriter.ods" w = ODSWriter() diff --git a/tests/test_stringio.py b/tests/test_stringio.py index f29a465..442a464 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -1,33 +1,32 @@ import os + import pyexcel from nose.tools import eq_ + from base import create_sample_file1 class TestStringIO: - def test_ods_stringio(self): testfile = "cute.ods" create_sample_file1(testfile) with open(testfile, "rb") as f: content = f.read() - r = pyexcel.get_sheet(file_type="ods", file_content=content, - library="pyexcel-ods") - result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] + r = pyexcel.get_sheet( + file_type="ods", file_content=content, library="pyexcel-ods" + ) + result = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", 1.1, 1] actual = list(r.enumerate()) eq_(result, actual) if os.path.exists(testfile): os.unlink(testfile) def test_ods_output_stringio(self): - data = [ - [1, 2, 3], - [4, 5, 6] - ] - io = pyexcel.save_as(dest_file_type="ods", - array=data) - r = pyexcel.get_sheet(file_type="ods", file_content=io.getvalue(), - library="pyexcel-ods") + data = [[1, 2, 3], [4, 5, 6]] + io = pyexcel.save_as(dest_file_type="ods", array=data) + r = pyexcel.get_sheet( + file_type="ods", file_content=io.getvalue(), library="pyexcel-ods" + ) result = [1, 2, 3, 4, 5, 6] actual = list(r.enumerate()) eq_(result, actual) diff --git a/tests/test_writer.py b/tests/test_writer.py index 5dec2db..ab5a976 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,7 +1,8 @@ import os -from pyexcel_ods.odsw import ODSWriter as Writer + +from base import PyexcelHatWriterBase, PyexcelWriterBase from pyexcel_ods.odsr import ODSBook as Reader -from base import PyexcelWriterBase, PyexcelHatWriterBase +from pyexcel_ods.odsw import ODSWriter as Writer class TestNativeODSWriter: @@ -9,7 +10,7 @@ class TestNativeODSWriter: self.content = { "Sheet1": [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], "Sheet2": [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]], - "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" writer = Writer() From f3b2ad05104524b0822a00cdbb34bf663d562a9c Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 26 Nov 2018 08:10:27 +0000 Subject: [PATCH 083/111] :green_heart: make unit test pass --- tests/test_bug_fixes.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 72ab370..128934a 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -116,7 +116,6 @@ def test_issue_83_ods_file_handle(): def test_pr_22(): test_file = get_fixtures("white_space.ods") data = get_data(test_file) - # OrderedDict([(u'Sheet1', [[u'paragraph with tab, space, new line']])]) eq_(data["Sheet1"][0][0], "paragraph with tab(\t), space, \nnew line") @@ -124,8 +123,11 @@ def test_issue_23(): if not IN_TRAVIS: raise SkipTest() pe.get_book( - url="https://github.com/pyexcel/pyexcel-ods/raw/master/tests/fixtures/white_space.ods" - ) # noqa: E501 + url=( + "https://github.com/pyexcel/pyexcel-ods/" + + "raw/master/tests/fixtures/white_space.ods" + ) + ) def test_issue_24(): From f1bf7616584400bd8eaaadb463d0c3d96ed4b308 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 27 Nov 2018 07:53:45 +0000 Subject: [PATCH 084/111] :egg: :ferris_wheel: release 0.5.4 --- CHANGELOG.rst | 11 +++++++++++ changelog.yml | 6 ++++++ docs/source/conf.py | 2 +- pyexcel-ods.yml | 2 +- setup.py | 6 +++--- 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 835ec48..6d621ca 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,17 @@ Change log ================================================================================ +0.5.4 - 27.11.2018 +-------------------------------------------------------------------------------- + +added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `#30 `_, long type will not + be written in ods. please use string type. And if the integer is equal or + greater than 10 to the power of 16, it will not be written either in ods. In + both situation, IntegerPrecisionLossError will be raised. + 0.5.3 - unreleased -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index d8a8f1c..fc2e04f 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-ods organisation: pyexcel releases: +- changes: + - action: added + details: + - '`#30`, long type will not be written in ods. please use string type. And if the integer is equal or greater than 10 to the power of 16, it will not be written either in ods. In both situation, IntegerPrecisionLossError will be raised.' + date: 27.11.2018 + version: 0.5.4 - changes: - action: added details: diff --git a/docs/source/conf.py b/docs/source/conf.py index cc38149..5d14f4c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -28,7 +28,7 @@ copyright = u'2015-2018 Onni Software Ltd.' author = u'C.W.' # The short X.Y version -version = u'0.5.3' +version = u'0.5.4' # The full version, including alpha/beta/rc tags release = u'0.5.4' diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index c8201fd..95c101a 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -3,7 +3,7 @@ name: "pyexcel-ods" nick_name: ods version: 0.5.4 current_version: 0.5.4 -release: 0.5.3 +release: 0.5.4 file_type: ods dependencies: - pyexcel-io>=0.5.9 diff --git a/setup.py b/setup.py index 98d8564..02530fd 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' ) URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.5.3.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.4.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python', @@ -48,8 +48,8 @@ EXTRAS_REQUIRE = { # You do not need to read beyond this line PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( sys.executable) -GS_COMMAND = ('gs pyexcel-ods v0.5.3 ' + - "Find 0.5.3 in changelog for more details") +GS_COMMAND = ('gs pyexcel-ods v0.5.4 ' + + "Find 0.5.4 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') UPLOAD_FAILED_MSG = ( From ee6af2adf9c78c6a15d8a5bb48adacb06235814d Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 27 Nov 2018 07:54:27 +0000 Subject: [PATCH 085/111] :hammer: use pyexcel-io 0.5.10 please --- .moban.d/tests/test_formatters.py | 2 +- pyexcel-ods.yml | 2 +- requirements.txt | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.moban.d/tests/test_formatters.py b/.moban.d/tests/test_formatters.py index 0cdd0f4..919d6fb 100644 --- a/.moban.d/tests/test_formatters.py +++ b/.moban.d/tests/test_formatters.py @@ -1,4 +1,4 @@ {% extends 'tests/test_formatters.py.jj2' %} {% block test_date_format %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index 95c101a..c0d4fda 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -6,6 +6,6 @@ current_version: 0.5.4 release: 0.5.4 file_type: ods dependencies: - - pyexcel-io>=0.5.9 + - pyexcel-io>=0.5.10 - odfpy==1.3.5 description: A wrapper library to read, manipulate and write data in ods format diff --git a/requirements.txt b/requirements.txt index 0827da9..8bb3c46 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.5.9 +pyexcel-io>=0.5.10 odfpy==1.3.5 diff --git a/setup.py b/setup.py index 02530fd..4eb9252 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.5.9', + 'pyexcel-io>=0.5.10', 'odfpy==1.3.5', ] SETUP_COMMANDS = {} From 571e8826a9f721edbad4991cff45e86408879c11 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 27 Nov 2018 07:54:52 +0000 Subject: [PATCH 086/111] :fire: use pyexcel-io from pypi to test --- rnd_requirements.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 rnd_requirements.txt diff --git a/rnd_requirements.txt b/rnd_requirements.txt deleted file mode 100644 index 8daba26..0000000 --- a/rnd_requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -https://github.com/pyexcel/pyexcel-io/archive/v0.5.10.zip - From a4d5874cab5094b46cde73b40a88218c1e3d0b38 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 16 Mar 2019 13:50:00 +0000 Subject: [PATCH 087/111] :books: update with pyexcel commons and build on python 3.7 and 3.8-dev. resolve #29 --- .moban.d/travis.yml | 8 ++-- .travis.yml | 23 +++++++-- LICENSE | 2 +- MANIFEST.in | 2 + README.rst | 1 + docs/source/conf.py | 114 ++++---------------------------------------- setup.py | 22 ++++++++- test.bat | 2 +- test.sh | 2 +- 9 files changed, 57 insertions(+), 119 deletions(-) diff --git a/.moban.d/travis.yml b/.moban.d/travis.yml index a40a09c..b3700f5 100644 --- a/.moban.d/travis.yml +++ b/.moban.d/travis.yml @@ -2,12 +2,12 @@ {%block custom_python_versions%} python: - - 3.7-dev + - &pypy2 pypy2.7-6.0 + - &pypy3 pypy3.5-6.0 + - 3.8-dev + - 3.7 - 3.6 - 3.5 - - 3.4 - - 3.3 - 2.7 - - 2.6 {%endblock%} diff --git a/.travis.yml b/.travis.yml index d0f4dc3..c2c6b83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,30 @@ sudo: false +dist: xenial language: python notifications: email: false python: - - 3.7-dev + - &pypy2 pypy2.7-6.0 + - &pypy3 pypy3.5-6.0 + - 3.8-dev + - 3.7 - 3.6 - 3.5 - - 3.4 - - 3.3 - 2.7 - - 2.6 + +stages: + - test + - lint +jobs: + include: + - stage: lint + python: 3.6 + script: make lint + +stage: test + +script: make test + before_install: - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install flake8==2.6.2; fi - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then diff --git a/LICENSE b/LICENSE index 6eef51e..d6d953b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2018 by Onni Software Ltd. and its contributors +Copyright (c) by Onni Software Ltd. and its contributors All rights reserved. Redistribution and use in source and binary forms of the software as well diff --git a/MANIFEST.in b/MANIFEST.in index c2e4b1b..b1bf562 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,5 @@ include README.rst include LICENSE include CHANGELOG.rst +recursive-include tests * +recursive-include docs * diff --git a/README.rst b/README.rst index 099fb92..5c9bfc8 100644 --- a/README.rst +++ b/README.rst @@ -375,6 +375,7 @@ Acceptance criteria #. Has all code lines tested #. Passes all Travis CI builds #. Has fair amount of documentation if your change is complex +#. run 'make format' so as to confirm the pyexcel organisation's coding style #. Please update CHANGELOG.rst #. Please add yourself to CONTRIBUTORS.rst #. Agree on NEW BSD License for your contribution diff --git a/docs/source/conf.py b/docs/source/conf.py index 93776c7..a1bd0dc 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -3,12 +3,10 @@ DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' + '' ) -# -*- coding: utf-8 -*- -# # Configuration file for the Sphinx documentation builder. # -# This file does only contain a selection of the most common options. For a -# full list see the documentation: +# This file only contains a selection of the most common options. For a full +# list see the documentation: # http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- @@ -23,44 +21,24 @@ DESCRIPTION = ( # -- Project information ----------------------------------------------------- -project = u'pyexcel-ods' -copyright = u'2015-2018 Onni Software Ltd.' -author = u'C.W.' - +project = 'pyexcel' +copyright = 'copyright 2015-2019 Onni Software Ltd.' +author = 'Onni Software Ltd.' # The short X.Y version -version = u'0.4.1' +version = '0.4.1' # The full version, including alpha/beta/rc tags -release = u'0.4.1' - +release = '0.4.1' # -- General configuration --------------------------------------------------- -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.viewcode', -] +extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode',] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # @@ -73,9 +51,6 @@ language = 'en' # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - # -- Options for HTML output ------------------------------------------------- @@ -84,84 +59,11 @@ pygments_style = 'sphinx' # html_theme = 'alabaster' -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} - - -# -- Options for HTMLHelp output --------------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = 'pyexcel-odsdoc' - - -# -- Options for LaTeX output ------------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'pyexcel-ods.tex', u'pyexcel-ods Documentation', - u'Onni Software Ltd.', 'manual'), -] - - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'pyexcel-ods', u'pyexcel-ods Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'pyexcel-ods', u'pyexcel-ods Documentation', - author, 'pyexcel-ods', 'One line description of project.', - 'Miscellaneous'), -] - # -- Extension configuration ------------------------------------------------- # -- Options for intersphinx extension --------------------------------------- diff --git a/setup.py b/setup.py index 48b5f7f..10ecc81 100644 --- a/setup.py +++ b/setup.py @@ -4,8 +4,25 @@ import os import sys import codecs +import locale +import platform from shutil import rmtree -from setuptools import setup, find_packages, Command + +from setuptools import Command, setup, find_packages + + +# Work around mbcs bug in distutils. +# http://bugs.python.org/issue10945 +# This work around is only if a project supports Python < 3.4 + +# Work around for locale not being set +try: + lc = locale.getlocale() + pf = platform.system() + if pf != 'Windows' and lc == (None, None): + locale.setlocale(locale.LC_ALL, 'C.UTF-8') +except (ValueError, UnicodeError, locale.Error): + locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') NAME = 'pyexcel-ods' AUTHOR = 'C.W.' @@ -19,7 +36,7 @@ URL = 'https://github.com/pyexcel/pyexcel-ods' DOWNLOAD_URL = '%s/archive/0.4.1.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ - 'python' + 'python', ] CLASSIFIERS = [ @@ -157,6 +174,7 @@ def filter_out_test_code(file_handle): if __name__ == '__main__': setup( + test_suite="tests", name=NAME, author=AUTHOR, version=VERSION, diff --git a/test.bat b/test.bat index ae229d9..ecba1ba 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_ods diff --git a/test.sh b/test.sh index ae229d9..ecba1ba 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_ods && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_ods From 21859fc277bdc10222ea7af76f05e64a2f14374b Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 16 Mar 2019 13:56:42 +0000 Subject: [PATCH 088/111] :fire: use release version for testing and :lipstick: pump up version --- docs/source/conf.py | 2 +- pyexcel_ods.yaml | 4 ++-- rnd_requirements.txt | 4 ---- setup.py | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) delete mode 100644 rnd_requirements.txt diff --git a/docs/source/conf.py b/docs/source/conf.py index a1bd0dc..210ed93 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,7 +25,7 @@ project = 'pyexcel' copyright = 'copyright 2015-2019 Onni Software Ltd.' author = 'Onni Software Ltd.' # The short X.Y version -version = '0.4.1' +version = '0.4.2' # The full version, including alpha/beta/rc tags release = '0.4.1' diff --git a/pyexcel_ods.yaml b/pyexcel_ods.yaml index bdefd5b..7f73f86 100644 --- a/pyexcel_ods.yaml +++ b/pyexcel_ods.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.4.1 -current_version: 0.4.1 +version: 0.4.2 +current_version: 0.4.2 release: 0.4.1 file_type: ods dependencies: diff --git a/rnd_requirements.txt b/rnd_requirements.txt deleted file mode 100644 index 3d8132d..0000000 --- a/rnd_requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -https://github.com/chfw/lml/archive/master.zip -https://github.com/pyexcel/pyexcel-io/archive/dev.zip -https://github.com/pyexcel/pyexcel/archive/master.zip -https://github.com/pyexcel/pyexcel-xls/archive/dev.zip diff --git a/setup.py b/setup.py index 10ecc81..ac06910 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ except (ValueError, UnicodeError, locale.Error): NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.4.1' +VERSION = '0.4.2' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( From a8f3eecd9c048e69821f33b2fe64de3db016b4c9 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 16 Mar 2019 14:01:09 +0000 Subject: [PATCH 089/111] :green_heart: pyexcel-ods does not work on pypy nor pypy3 --- .moban.d/travis.yml | 2 -- .moban.yml | 2 +- .travis.yml | 2 -- pyexcel_ods.yaml => pyexcel-ods.yml | 0 4 files changed, 1 insertion(+), 5 deletions(-) rename pyexcel_ods.yaml => pyexcel-ods.yml (100%) diff --git a/.moban.d/travis.yml b/.moban.d/travis.yml index b3700f5..a94a221 100644 --- a/.moban.d/travis.yml +++ b/.moban.d/travis.yml @@ -2,8 +2,6 @@ {%block custom_python_versions%} python: - - &pypy2 pypy2.7-6.0 - - &pypy3 pypy3.5-6.0 - 3.8-dev - 3.7 - 3.6 diff --git a/.moban.yml b/.moban.yml index eed4989..1ec0bd0 100644 --- a/.moban.yml +++ b/.moban.yml @@ -4,7 +4,7 @@ configuration: - "commons/templates" - "setupmobans/templates" - ".moban.d" - configuration: pyexcel_ods.yaml + configuration: pyexcel-ods.yml targets: - README.rst: README.rst - setup.py: setup.py diff --git a/.travis.yml b/.travis.yml index c2c6b83..b7e8d4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,6 @@ language: python notifications: email: false python: - - &pypy2 pypy2.7-6.0 - - &pypy3 pypy3.5-6.0 - 3.8-dev - 3.7 - 3.6 diff --git a/pyexcel_ods.yaml b/pyexcel-ods.yml similarity index 100% rename from pyexcel_ods.yaml rename to pyexcel-ods.yml From 55b85cbc3282dfe68e54de3dc68196f928f36e04 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 16 Mar 2019 14:09:18 +0000 Subject: [PATCH 090/111] :newspaper: add lint file --- .moban.yml | 3 ++- CHANGELOG.rst | 8 ++++++++ Makefile | 3 +++ lint.sh | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 lint.sh diff --git a/.moban.yml b/.moban.yml index 7d0fe4d..3f061c1 100644 --- a/.moban.yml +++ b/.moban.yml @@ -29,4 +29,5 @@ targets: - "tests/base.py": "tests/base.py.jj2" - output: CHANGELOG.rst configuration: changelog.yml - template: CHANGELOG.rst.jj2 \ No newline at end of file + template: CHANGELOG.rst.jj2 + - lint.sh: lint.script.jj2 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6d621ca..aa34ddb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Change log ================================================================================ +0.5.5 - 16.03.2019 +-------------------------------------------------------------------------------- + +added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `#32 `_, fix odfpy pinning + 0.5.4 - 27.11.2018 -------------------------------------------------------------------------------- diff --git a/Makefile b/Makefile index 62b93c1..d3587b4 100644 --- a/Makefile +++ b/Makefile @@ -7,3 +7,6 @@ format: isort -y $(find pyexcel_ods -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) black -l 79 pyexcel_ods black -l 79 tests + +lint: + bash lint.sh diff --git a/lint.sh b/lint.sh new file mode 100644 index 0000000..12183c3 --- /dev/null +++ b/lint.sh @@ -0,0 +1 @@ +flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long \ No newline at end of file From 1827796f19d0f9033e2c119fffad740dc730fa4d Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 16 Mar 2019 14:14:55 +0000 Subject: [PATCH 091/111] :egg: :ferris_wheel: release 0.5.5 --- docs/source/conf.py | 2 +- pyexcel-ods.yml | 2 +- setup.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 74af414..8814fe8 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -27,7 +27,7 @@ author = 'Onni Software Ltd.' # The short X.Y version version = '0.5.5' # The full version, including alpha/beta/rc tags -release = '0.5.4' +release = '0.5.5' # -- General configuration --------------------------------------------------- diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index a70d6d9..50b7958 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -3,7 +3,7 @@ name: "pyexcel-ods" nick_name: ods version: 0.5.5 current_version: 0.5.5 -release: 0.5.4 +release: 0.5.5 file_type: ods dependencies: - pyexcel-io>=0.5.10 diff --git a/setup.py b/setup.py index be7885f..3eefeb7 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' ) URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.5.4.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.5.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python', @@ -63,8 +63,8 @@ EXTRAS_REQUIRE = { # You do not need to read beyond this line PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( sys.executable) -GS_COMMAND = ('gs pyexcel-ods v0.5.4 ' + - "Find 0.5.4 in changelog for more details") +GS_COMMAND = ('gs pyexcel-ods v0.5.5 ' + + "Find 0.5.5 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') UPLOAD_FAILED_MSG = ( From a8bbf355613f42b9c7cc8b30145e6c6e181d3f6d Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 16 Mar 2019 14:18:42 +0000 Subject: [PATCH 092/111] :bug: fix copyright year --- LICENSE | 2 +- pyexcel-ods.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index d6d953b..0f53832 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) by Onni Software Ltd. and its contributors +Copyright (c) 2015-2019 by Onni Software Ltd. and its contributors All rights reserved. Redistribution and use in source and binary forms of the software as well diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index 50b7958..199c2d2 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -4,6 +4,7 @@ nick_name: ods version: 0.5.5 current_version: 0.5.5 release: 0.5.5 +copyright_year: 2015-2019 file_type: ods dependencies: - pyexcel-io>=0.5.10 From 87e7a33fac706c9cab61194e0f8b79114a745c85 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 19 Mar 2019 08:37:19 +0000 Subject: [PATCH 093/111] :egg: :ferris_wheel: release 0.5.6. fix #33, #32 --- .travis.yml | 20 ++++++++++++++++---- CHANGELOG.rst | 10 ++++++++++ changelog.yml | 7 +++++++ docs/source/conf.py | 4 ++-- pyexcel-ods.yml | 10 +++++----- pyexcel_ods/__init__.py | 10 +++++----- pyexcel_ods/odsr.py | 7 ++++--- pyexcel_ods/odsw.py | 5 +++-- requirements.txt | 4 ++-- setup.py | 12 ++++++------ tests/base.py | 3 +-- tests/test_bug_fixes.py | 6 +++--- tests/test_filter.py | 1 - tests/test_formatters.py | 3 +-- tests/test_multiple_sheets.py | 2 +- tests/test_stringio.py | 2 +- 16 files changed, 67 insertions(+), 39 deletions(-) diff --git a/.travis.yml b/.travis.yml index b7e8d4d..31c8793 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,18 +13,30 @@ python: stages: - test - lint + +.disable_global: &disable_global + before_install: false + install: true + before_script: false + after_success: false + after_failure: false + +.lint: &lint + <<: *disable_global + python: 3.6 + stage: lint + install: pip install flake8 + script: flake8 + jobs: include: - - stage: lint - python: 3.6 - script: make lint + - *lint stage: test script: make test before_install: - - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install flake8==2.6.2; fi - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then mv min_requirements.txt requirements.txt ; fi diff --git a/CHANGELOG.rst b/CHANGELOG.rst index aa34ddb..7fb00f1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,16 @@ Change log ================================================================================ +0.5.6 - 19.03.2019 +-------------------------------------------------------------------------------- + +added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `#32 `_, fix odfpy pinning +#. `#33 `_, fix + IntegerAccuracyLossError on i586 + 0.5.5 - 16.03.2019 -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index 4f91ada..d15f3f6 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,13 @@ name: pyexcel-ods organisation: pyexcel releases: +- changes: + - action: added + details: + - '`#32`, fix odfpy pinning' + - '`#33`, fix IntegerAccuracyLossError on i586' + date: 19.03.2019 + version: 0.5.6 - changes: - action: added details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 8814fe8..9603cb6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,9 +25,9 @@ project = 'pyexcel' copyright = 'copyright 2015-2019 Onni Software Ltd.' author = 'Onni Software Ltd.' # The short X.Y version -version = '0.5.5' +version = '0.5.6' # The full version, including alpha/beta/rc tags -release = '0.5.5' +release = '0.5.6' # -- General configuration --------------------------------------------------- diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index 199c2d2..1201ffe 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -1,12 +1,12 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.5.5 -current_version: 0.5.5 -release: 0.5.5 +version: 0.5.6 +current_version: 0.5.6 +release: 0.5.6 copyright_year: 2015-2019 file_type: ods dependencies: - - pyexcel-io>=0.5.10 - - odfpy==1.3.5 + - pyexcel-io>=0.5.16 + - odfpy>=1.3.5 description: A wrapper library to read, manipulate and write data in ods format diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index 3c2a28b..60fd4f2 100644 --- a/pyexcel_ods/__init__.py +++ b/pyexcel_ods/__init__.py @@ -5,15 +5,15 @@ :copyright: (c) 2015-2017 by Onni Software Ltd & its contributors :license: New BSD License """ + # flake8: noqa +from pyexcel_io.io import get_data as read_data +from pyexcel_io.io import isstream +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.io import ( - get_data as read_data, - isstream, - store_data as write_data, -) __FILE_TYPE__ = "ods" IOPluginInfoChain(__name__).add_a_reader( diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 3559ffe..3af37fe 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -22,6 +22,10 @@ # limitations under the License. import pyexcel_io.service as service +from pyexcel_io._compact import OrderedDict +from pyexcel_io.book import BookReader +from pyexcel_io.sheet import SheetReader + from odf.namespaces import OFFICENS from odf.opendocument import load from odf.table import Table, TableCell, TableRow @@ -29,9 +33,6 @@ from odf.table import Table, TableCell, TableRow # Thanks to grt for the fixes from odf.teletype import extractText from odf.text import P -from pyexcel_io._compact import OrderedDict -from pyexcel_io.book import BookReader -from pyexcel_io.sheet import SheetReader class ODSSheet(SheetReader): diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index c911517..3f1bdd3 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -10,12 +10,13 @@ import sys import pyexcel_io.service as converter +from pyexcel_io.book import BookWriter +from pyexcel_io.sheet import SheetWriter + from odf.namespaces import OFFICENS from odf.opendocument import OpenDocumentSpreadsheet from odf.table import Table, TableCell, TableRow from odf.text import P -from pyexcel_io.book import BookWriter -from pyexcel_io.sheet import SheetWriter PY2 = sys.version_info[0] == 2 diff --git a/requirements.txt b/requirements.txt index 8bb3c46..a6599ba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.5.10 -odfpy==1.3.5 +pyexcel-io>=0.5.16 +odfpy>=1.3.5 diff --git a/setup.py b/setup.py index 3eefeb7..42a26c3 100644 --- a/setup.py +++ b/setup.py @@ -25,14 +25,14 @@ except (ValueError, UnicodeError, locale.Error): NAME = 'pyexcel-ods' AUTHOR = 'C.W.' -VERSION = '0.5.5' +VERSION = '0.5.6' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in ods format' ) URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.5.5.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.6.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'python', @@ -51,8 +51,8 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.5.10', - 'odfpy==1.3.5', + 'pyexcel-io>=0.5.16', + 'odfpy>=1.3.5', ] SETUP_COMMANDS = {} @@ -63,8 +63,8 @@ EXTRAS_REQUIRE = { # You do not need to read beyond this line PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( sys.executable) -GS_COMMAND = ('gs pyexcel-ods v0.5.5 ' + - "Find 0.5.5 in changelog for more details") +GS_COMMAND = ('gs pyexcel-ods v0.5.6 ' + + "Find 0.5.6 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/base.py b/tests/base.py index b21fc59..c312a6a 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,9 +1,8 @@ import datetime # noqa import os # noqa -from nose.tools import eq_, raises # noqa - import pyexcel +from nose.tools import eq_, raises # noqa def create_sample_file1(file): diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index f06359a..128934a 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -2,12 +2,12 @@ # -*- encoding: utf-8 -*- import os -from nose import SkipTest -from nose.tools import eq_, raises - import psutil import pyexcel as pe +from nose import SkipTest +from nose.tools import eq_, raises from pyexcel_io.exceptions import IntegerAccuracyLossError + from pyexcel_ods import get_data, save_data IN_TRAVIS = "TRAVIS" in os.environ diff --git a/tests/test_filter.py b/tests/test_filter.py index a891cce..67d8876 100644 --- a/tests/test_filter.py +++ b/tests/test_filter.py @@ -1,7 +1,6 @@ import os from nose.tools import eq_ - from pyexcel_io import get_data, save_data diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 4b0bb03..ba78ec2 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -1,9 +1,8 @@ import os from textwrap import dedent -from nose.tools import eq_ - import pyexcel as pe +from nose.tools import eq_ class TestAutoDetectInt: diff --git a/tests/test_multiple_sheets.py b/tests/test_multiple_sheets.py index 954d3e1..6360be6 100644 --- a/tests/test_multiple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -1,9 +1,9 @@ import os import sys +import pyexcel from nose.tools import raises -import pyexcel from base import PyexcelMultipleSheetBase if sys.version_info[0] == 2 and sys.version_info[1] < 7: diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 6f27ca9..442a464 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -1,8 +1,8 @@ import os +import pyexcel from nose.tools import eq_ -import pyexcel from base import create_sample_file1 From b512b1dc06f9b41d59fb5e860da2e106577f5ea2 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 19 Mar 2019 08:41:00 +0000 Subject: [PATCH 094/111] :green_heart: fix lintting command issue --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 31c8793..324d79f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ stages: python: 3.6 stage: lint install: pip install flake8 - script: flake8 + script: make lint jobs: include: From 7f54170075e312248db4dfa5f592a8786af1e3e9 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 10 Nov 2019 16:30:00 +0000 Subject: [PATCH 095/111] :shirt: coding style update --- .isort.cfg | 10 ++++++++++ .moban.d/custom_README.rst.jj2 | 30 ++++++++++++++++++++++++++++++ .moban.d/custom_setup.py.jj2 | 7 +++++++ pyexcel_ods/odsr.py | 18 +++++++++--------- pyexcel_ods/odsw.py | 10 +++++----- tests/base.py | 3 ++- tests/test_bug_fixes.py | 6 +++--- tests/test_multiple_sheets.py | 4 ++-- tests/test_stringio.py | 4 ++-- tests/test_writer.py | 2 +- 10 files changed, 71 insertions(+), 23 deletions(-) create mode 100644 .isort.cfg create mode 100644 .moban.d/custom_README.rst.jj2 create mode 100644 .moban.d/custom_setup.py.jj2 diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..f5332c5 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,10 @@ +[settings] +line_length=79 +known_first_party=lml, pyexcel, odfpy +known_third_party=nose +indent=' ' +multi_line_output=3 +length_sort=1 +default_section=FIRSTPARTY +no_lines_before=LOCALFOLDER +sections=FUTURE,STDLIB,FIRSTPARTY,THIRDPARTY,LOCALFOLDER diff --git a/.moban.d/custom_README.rst.jj2 b/.moban.d/custom_README.rst.jj2 new file mode 100644 index 0000000..83502eb --- /dev/null +++ b/.moban.d/custom_README.rst.jj2 @@ -0,0 +1,30 @@ +{%extends 'README.rst.jj2' %} + +{%block documentation_link%} +{%endblock%} + +{%block description%} +**pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in +ods format using python 2.6 and python 2.7. You are likely to use it with +`pyexcel `_. +`pyexcel-ods3 `_ is a sister library that +depends on ezodf and lxml. `pyexcel-odsr `_ +is the other sister library that has no external dependency but do ods reading only +{%endblock%} + +{% block pagination_note%} +Special notice 30/01/2017: due to the constraints of the underlying 3rd party +library, it will read the whole file before returning the paginated data. So +at the end of day, the only benefit is less data returned from the reading +function. No major performance improvement will be seen. + +With that said, please install `pyexcel-odsr `_ +and it gives better performance in pagination. +{%endblock%} + +{%block extras %} +Credits +================================================================================ + +ODSReader is originally written by `Marco Conti `_ +{%endblock%} diff --git a/.moban.d/custom_setup.py.jj2 b/.moban.d/custom_setup.py.jj2 new file mode 100644 index 0000000..b276d5a --- /dev/null +++ b/.moban.d/custom_setup.py.jj2 @@ -0,0 +1,7 @@ +{% extends 'setup.py.jj2' %} + +{%block platform_block%} +{%endblock%} + +{%block compat_block%} +{%endblock%} diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 3af37fe..9aa3cee 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -21,18 +21,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pyexcel_io.service as service -from pyexcel_io._compact import OrderedDict -from pyexcel_io.book import BookReader -from pyexcel_io.sheet import SheetReader - -from odf.namespaces import OFFICENS -from odf.opendocument import load -from odf.table import Table, TableCell, TableRow +from odf.text import P +from odf.table import Table, TableRow, TableCell # Thanks to grt for the fixes from odf.teletype import extractText -from odf.text import P +from odf.namespaces import OFFICENS +from odf.opendocument import load + +import pyexcel_io.service as service +from pyexcel_io.book import BookReader +from pyexcel_io.sheet import SheetReader +from pyexcel_io._compact import OrderedDict class ODSSheet(SheetReader): diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index 3f1bdd3..2cbe118 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -9,15 +9,15 @@ """ import sys +from odf.text import P +from odf.table import Table, TableRow, TableCell +from odf.namespaces import OFFICENS +from odf.opendocument import OpenDocumentSpreadsheet + import pyexcel_io.service as converter from pyexcel_io.book import BookWriter from pyexcel_io.sheet import SheetWriter -from odf.namespaces import OFFICENS -from odf.opendocument import OpenDocumentSpreadsheet -from odf.table import Table, TableCell, TableRow -from odf.text import P - PY2 = sys.version_info[0] == 2 PY27_BELOW = PY2 and sys.version_info[1] < 7 diff --git a/tests/base.py b/tests/base.py index c312a6a..3d40097 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,7 +1,8 @@ -import datetime # noqa import os # noqa +import datetime # noqa import pyexcel + from nose.tools import eq_, raises # noqa diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 128934a..de4d13b 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -2,14 +2,14 @@ # -*- encoding: utf-8 -*- import os -import psutil import pyexcel as pe +from pyexcel_ods import get_data, save_data + +import psutil from nose import SkipTest from nose.tools import eq_, raises from pyexcel_io.exceptions import IntegerAccuracyLossError -from pyexcel_ods import get_data, save_data - IN_TRAVIS = "TRAVIS" in os.environ diff --git a/tests/test_multiple_sheets.py b/tests/test_multiple_sheets.py index 6360be6..f82b212 100644 --- a/tests/test_multiple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -2,10 +2,10 @@ import os import sys import pyexcel -from nose.tools import raises - from base import PyexcelMultipleSheetBase +from nose.tools import raises + if sys.version_info[0] == 2 and sys.version_info[1] < 7: from ordereddict import OrderedDict else: diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 442a464..45e0ec8 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -1,10 +1,10 @@ import os import pyexcel -from nose.tools import eq_ - from base import create_sample_file1 +from nose.tools import eq_ + class TestStringIO: def test_ods_stringio(self): diff --git a/tests/test_writer.py b/tests/test_writer.py index ab5a976..ae3a300 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,6 +1,6 @@ import os -from base import PyexcelHatWriterBase, PyexcelWriterBase +from base import PyexcelWriterBase, PyexcelHatWriterBase from pyexcel_ods.odsr import ODSBook as Reader from pyexcel_ods.odsw import ODSWriter as Writer From 093dee4da20ef4da4f65c7f2b61d7630d7b875ab Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 10 Nov 2019 16:31:02 +0000 Subject: [PATCH 096/111] :handshake: apply common templates from pyexcel mobans. https://github.com/moremoban/moban/pull/348 --- .github/FUNDING.yml | 4 ++ .github/PULL_REQUEST_TEMPLATE.md | 10 +++ .gitignore | 38 +++++++++++- .moban.d/README.rst | 30 --------- .moban.d/setup.py | 7 --- .moban.yml | 23 +------ .travis.yml | 46 ++------------ CHANGELOG.rst | 90 +++++++++------------------ README.rst | 29 +++------ docs/source/conf.py | 11 ++-- lint.sh | 3 +- setup.py | 102 ++++++++++++++++--------------- test.sh | 1 + tests/test_formatters.py | 1 + 14 files changed, 161 insertions(+), 234 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md delete mode 100644 .moban.d/README.rst delete mode 100644 .moban.d/setup.py diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..0faea60 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +github: chfw +patreon: chfw diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..7b632ce --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +With your PR, here is a check list: + +- [ ] Has Test cases written +- [ ] Has all code lines tested +- [ ] Passes all Travis CI builds +- [ ] Has fair amount of documentation if your change is complex +- [ ] run 'make format' so as to confirm the pyexcel organisation's coding style +- [ ] Please update CHANGELOG.rst +- [ ] Please add yourself to CONTRIBUTORS.rst +- [ ] Agree on NEW BSD License for your contribution diff --git a/.gitignore b/.gitignore index d09b336..88bc3f6 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,8 @@ parts/ sdist/ var/ wheels/ +pip-wheel-metadata/ +share/python-wheels/ *.egg-info/ .installed.cfg *.egg @@ -43,6 +45,7 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ +.nox/ .coverage .coverage.* .cache @@ -77,9 +80,20 @@ target/ # Jupyter Notebook .ipynb_checkpoints +# IPython +profile_default/ +ipython_config.py + # pyenv .python-version +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don’t work, or not +# install all needed dependencies. +#Pipfile.lock + # celery beat schedule file celerybeat-schedule @@ -107,6 +121,11 @@ venv.bak/ # mypy .mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ # VirtualEnv rules # Virtualenv @@ -238,6 +257,10 @@ flycheck_*.el # directory configuration .dir-locals.el +# network security +/network-security.data + + # Vim rules # Swap [._]*.s[a-v][a-z] @@ -268,6 +291,9 @@ tags .idea/**/dictionaries .idea/**/shelf +# Generated files +.idea/**/contentModel.xml + # Sensitive or high-churn files .idea/**/dataSources/ .idea/**/dataSources.ids @@ -281,6 +307,14 @@ tags .idea/**/gradle.xml .idea/**/libraries +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + # CMake cmake-build-*/ @@ -311,6 +345,9 @@ fabric.properties # Editor-based Rest Client .idea/httpRequests +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + # SublimeText rules # Cache files for Sublime Text *.tmlanguage.cache @@ -390,7 +427,6 @@ DerivedData/ !default.perspectivev3 # Eclipse rules - .metadata bin/ tmp/ diff --git a/.moban.d/README.rst b/.moban.d/README.rst deleted file mode 100644 index 83502eb..0000000 --- a/.moban.d/README.rst +++ /dev/null @@ -1,30 +0,0 @@ -{%extends 'README.rst.jj2' %} - -{%block documentation_link%} -{%endblock%} - -{%block description%} -**pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in -ods format using python 2.6 and python 2.7. You are likely to use it with -`pyexcel `_. -`pyexcel-ods3 `_ is a sister library that -depends on ezodf and lxml. `pyexcel-odsr `_ -is the other sister library that has no external dependency but do ods reading only -{%endblock%} - -{% block pagination_note%} -Special notice 30/01/2017: due to the constraints of the underlying 3rd party -library, it will read the whole file before returning the paginated data. So -at the end of day, the only benefit is less data returned from the reading -function. No major performance improvement will be seen. - -With that said, please install `pyexcel-odsr `_ -and it gives better performance in pagination. -{%endblock%} - -{%block extras %} -Credits -================================================================================ - -ODSReader is originally written by `Marco Conti `_ -{%endblock%} diff --git a/.moban.d/setup.py b/.moban.d/setup.py deleted file mode 100644 index b276d5a..0000000 --- a/.moban.d/setup.py +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'setup.py.jj2' %} - -{%block platform_block%} -{%endblock%} - -{%block compat_block%} -{%endblock%} diff --git a/.moban.yml b/.moban.yml index 3f061c1..dc2c267 100644 --- a/.moban.yml +++ b/.moban.yml @@ -1,33 +1,16 @@ -requires: - - type: git - url: https://github.com/moremoban/pypi-mobans - submodule: true - - https://github.com/pyexcel/pyexcel-mobans +overrides: "git://github.com/pyexcel/pyexcel-mobans!/mobanfile.yaml" configuration: - configuration_dir: "pyexcel-mobans:config" - template_dir: - - "pyexcel-mobans:templates" - - "pypi-mobans:templates" - - ".moban.d" configuration: pyexcel-ods.yml targets: - - README.rst: README.rst - - setup.py: setup.py + - README.rst: custom_README.rst.jj2 + - setup.py: custom_setup.py.jj2 - "docs/source/conf.py": "docs/source/conf.py.jj2" - .travis.yml: travis.yml - .gitignore: gitignore.jj2 - - requirements.txt: requirements.txt - - LICENSE: NEW_BSD_LICENSE.jj2 - MANIFEST.in: MANIFEST.in.jj2 - "tests/requirements.txt": "tests/requirements.txt" - - test.sh: test.script.jj2 - - test.bat: test.script.jj2 - "tests/test_filter.py": "tests/test_filter.py.jj2" - "tests/test_formatters.py": "tests/test_formatters.py" - "tests/test_stringio.py": "tests/test_stringio.py.jj2" - "tests/test_writer.py": "tests/test_writer.py.jj2" - "tests/base.py": "tests/base.py.jj2" - - output: CHANGELOG.rst - configuration: changelog.yml - template: CHANGELOG.rst.jj2 - - lint.sh: lint.script.jj2 diff --git a/.travis.yml b/.travis.yml index 324d79f..a94a221 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,49 +1,11 @@ -sudo: false -dist: xenial -language: python -notifications: - email: false +{% extends "travis.yml.jj2" %} + +{%block custom_python_versions%} python: - 3.8-dev - 3.7 - 3.6 - 3.5 - 2.7 +{%endblock%} -stages: - - test - - lint - -.disable_global: &disable_global - before_install: false - install: true - before_script: false - after_success: false - after_failure: false - -.lint: &lint - <<: *disable_global - python: 3.6 - stage: lint - install: pip install flake8 - script: make lint - -jobs: - include: - - *lint - -stage: test - -script: make test - -before_install: - - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then - mv min_requirements.txt requirements.txt ; - fi - - test ! -f rnd_requirements.txt || pip install --no-deps -r rnd_requirements.txt - - test ! -f rnd_requirements.txt || pip install -r rnd_requirements.txt ; - - pip install -r tests/requirements.txt -script: - - make test -after_success: - codecov diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7fb00f1..9ef21e4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,8 +4,7 @@ Change log 0.5.6 - 19.03.2019 -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `#32 `_, fix odfpy pinning #. `#33 `_, fix @@ -14,16 +13,14 @@ added 0.5.5 - 16.03.2019 -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `#32 `_, fix odfpy pinning 0.5.4 - 27.11.2018 -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `#30 `_, long type will not be written in ods. please use string type. And if the integer is equal or @@ -33,8 +30,7 @@ added 0.5.3 - unreleased -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `#24 `_, ignore comments() in cell @@ -45,8 +41,7 @@ added 0.5.2 - 23.10.2017 -------------------------------------------------------------------------------- -updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**updated** #. pyexcel `pyexcel#105 `_, remove gease from setup_requires, introduced by 0.5.1. @@ -55,8 +50,7 @@ updated 0.5.1 - 20.10.2017 -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `pyexcel#103 `_, include LICENSE file in MANIFEST.in, meaning LICENSE file will appear in the released @@ -65,22 +59,19 @@ added 0.5.0 - 30.08.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. put dependency on pyexcel-io 0.5.0, which uses cStringIO instead of StringIO. Hence, there will be performance boost in handling files in memory. -Relocated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Relocated** #. All ods type conversion code lives in pyexcel_io.service module 0.4.1 - 25.08.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `pyexcel#23 `_, handle unseekable stream given by http response @@ -90,8 +81,7 @@ Updated 0.4.0 - 19.06.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `pyexcel#14 `_, close file handle @@ -101,8 +91,7 @@ Updated 0.3.3 - 07.05.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. issue `pyexcel#19 `_, not all texts in a multi-node cell were extracted. @@ -110,8 +99,7 @@ Updated 0.3.2 - 13.04.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. issue `pyexcel#17 `_, empty new line is ignored @@ -121,24 +109,21 @@ Updated 0.3.1 - 02.02.2017 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. Recognize currency type 0.3.0 - 22.12.2016 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Code refactoring with pyexcel-io v 0.3.0 0.2.2 - 24.10.2016 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. issue `pyexcel#14 `_, index error when reading a ods file that has non-uniform columns repeated property. @@ -146,8 +131,7 @@ Updated 0.2.1 - 31.08.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. support pagination. two pairs: start_row, row_limit and start_column, column_limit help you deal with large files. @@ -156,24 +140,21 @@ Added 0.2.0 - 01.06.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. By default, `float` will be converted to `int` where fits. `auto_detect_int`, a flag to switch off the autoatic conversion from `float` to `int`. #. 'library=pyexcel-ods' was added so as to inform pyexcel to use it instead of other libraries, in the situation where multiple plugins were installed. -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. support the auto-import feature of pyexcel-io 0.2.0 0.1.1 - 30.01.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. 'streaming' is an extra option given to get_data. Only when 'streaming' is explicitly set to True, the data will be consisted of generators, hence will @@ -182,64 +163,56 @@ Added #. support multi-line text cell #5 #. feature migration from pyexcel-ods3 pyexcel/pyexcel-ods3#5 -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. compatibility with pyexcel-io 0.1.1 0.0.12 - 10.10.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Bug fix: excessive trailing columns with empty values 0.0.11 - 26.09.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Complete fix for libreoffice datetime field 0.0.10 - 15.09.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Bug fix: date field could have datetime from libreoffice 0.0.9 - 21.08.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Bug fix: utf-8 string throw unicode exceptions 0.0.8 - 28.06.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Pin dependency odfpy 0.9.6 to avoid buggy odfpy 1.3.0 0.0.7 - 28.05.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Bug fix: "number-columns-repeated" is now respected 0.0.6 - 21.05.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. get_data and save_data are seen across pyexcel-* extensions. remember them once and use them across all extensions. @@ -247,8 +220,7 @@ Updated 0.0.5 - 22.02.2015 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. Loads only one sheet from a multiple sheet book #. Use New BSD License @@ -256,8 +228,7 @@ Added 0.0.4 - 14.12.2014 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. IO interface update as pyexcel-io introduced keywords. #. initial release @@ -265,8 +236,7 @@ Updated 0.0.3 - 08.12.2014 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. IO interface update as pyexcel-io introduced keywords. #. initial release diff --git a/README.rst b/README.rst index 5c9bfc8..24e006e 100644 --- a/README.rst +++ b/README.rst @@ -3,10 +3,7 @@ pyexcel-ods - Let you focus on data, instead of ods format ================================================================================ .. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png - :target: https://www.patreon.com/pyexcel - -.. image:: https://api.bountysource.com/badge/team?team_id=288537 - :target: https://salt.bountysource.com/teams/chfw-pyexcel + :target: https://www.patreon.com/chfw .. image:: https://travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-ods @@ -14,6 +11,14 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://codecov.io/gh/pyexcel/pyexcel-ods/branch/master/graph/badge.svg :target: https://codecov.io/gh/pyexcel/pyexcel-ods +.. image:: https://badge.fury.io/py/pyexcel-ods.svg + :target: https://pypi.org/project/pyexcel-ods + + +.. image:: https://pepy.tech/badge/pyexcel-ods/month + :target: https://pepy.tech/project/pyexcel-ods/month + + .. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg :target: https://gitter.im/pyexcel/Lobby @@ -53,7 +58,7 @@ Support the project ================================================================================ If your company has embedded pyexcel and its components into a revenue generating -product, please support me on `patreon `_ +product, please support me on `github `_, `patreon `_ or `bounty source `_ to maintain the project and develop it further. @@ -354,8 +359,6 @@ How to update test environment and update documentation Additional steps are required: #. pip install moban -#. git clone https://github.com/moremoban/setupmobans.git # generic setup -#. git clone https://github.com/pyexcel/pyexcel-commons.git commons #. make your changes in `.moban.d` directory, then issue command `moban` What is pyexcel-commons @@ -368,18 +371,6 @@ What is .moban.d `.moban.d` stores the specific meta data for the library. -Acceptance criteria -------------------- - -#. Has Test cases written -#. Has all code lines tested -#. Passes all Travis CI builds -#. Has fair amount of documentation if your change is complex -#. run 'make format' so as to confirm the pyexcel organisation's coding style -#. Please update CHANGELOG.rst -#. Please add yourself to CONTRIBUTORS.rst -#. Agree on NEW BSD License for your contribution - Credits ================================================================================ diff --git a/docs/source/conf.py b/docs/source/conf.py index 9603cb6..4f79234 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -7,7 +7,7 @@ DESCRIPTION = ( # # This file only contains a selection of the most common options. For a full # list see the documentation: -# http://www.sphinx-doc.org/en/master/config +# https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- @@ -21,9 +21,9 @@ DESCRIPTION = ( # -- Project information ----------------------------------------------------- -project = 'pyexcel' -copyright = 'copyright 2015-2019 Onni Software Ltd.' -author = 'Onni Software Ltd.' +project = 'pyexcel-ods' +copyright = '2015-2019 Onni Software Ltd.' +author = 'C.W.' # The short X.Y version version = '0.5.6' # The full version, including alpha/beta/rc tags @@ -68,7 +68,7 @@ html_static_path = ['_static'] # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {'https://docs.python.org/3/': None} # TODO: html_theme not configurable upstream html_theme = 'default' @@ -83,3 +83,4 @@ texinfo_documents = [ intersphinx_mapping.update({ 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), }) +master_doc = "index" diff --git a/lint.sh b/lint.sh index 12183c3..976f745 100644 --- a/lint.sh +++ b/lint.sh @@ -1 +1,2 @@ -flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long \ No newline at end of file +pip install flake8 +flake8 . --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long \ No newline at end of file diff --git a/setup.py b/setup.py index 42a26c3..db405d1 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 +import os +import sys +# Template by pypi-mobans import codecs import locale -# Template by pypi-mobans -import os import platform -import sys from shutil import rmtree -from setuptools import Command, find_packages, setup +from setuptools import Command, setup, find_packages # Work around mbcs bug in distutils. # http://bugs.python.org/issue10945 @@ -18,55 +18,59 @@ from setuptools import Command, find_packages, setup try: lc = locale.getlocale() pf = platform.system() - if pf != 'Windows' and lc == (None, None): - locale.setlocale(locale.LC_ALL, 'C.UTF-8') + if pf != "Windows" and lc == (None, None): + locale.setlocale(locale.LC_ALL, "C.UTF-8") except (ValueError, UnicodeError, locale.Error): - locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') + locale.setlocale(locale.LC_ALL, "en_US.UTF-8") -NAME = 'pyexcel-ods' -AUTHOR = 'C.W.' -VERSION = '0.5.6' -EMAIL = 'wangc_2011@hotmail.com' -LICENSE = 'New BSD' +NAME = "pyexcel-ods" +AUTHOR = "C.W." +VERSION = "0.5.6" +EMAIL = "info@pyexcel.org" +LICENSE = "New BSD" DESCRIPTION = ( - 'A wrapper library to read, manipulate and write data in ods format' + "A wrapper library to read, manipulate and write data in ods format" ) -URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.5.6.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +URL = "https://github.com/pyexcel/pyexcel-ods" +DOWNLOAD_URL = "%s/archive/0.5.6.tar.gz" % URL +FILES = ["README.rst", "CHANGELOG.rst"] KEYWORDS = [ - 'python', + "python", ] CLASSIFIERS = [ - 'Topic :: Software Development :: Libraries', - 'Programming Language :: Python', - 'Intended Audience :: Developers', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', + "Topic :: Software Development :: Libraries", + "Programming Language :: Python", + "Intended Audience :: Developers", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + + "Programming Language :: Python :: 3.7", + + "Programming Language :: Python :: 3.8", + ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.5.16', - 'odfpy>=1.3.5', + "pyexcel-io>=0.5.16", + "odfpy>=1.3.5", ] SETUP_COMMANDS = {} -PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) +PACKAGES = find_packages(exclude=["ez_setup", "examples", "tests"]) EXTRAS_REQUIRE = { } # You do not need to read beyond this line -PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( - sys.executable) -GS_COMMAND = ('gs pyexcel-ods v0.5.6 ' + +PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) +GS_COMMAND = ("gs pyexcel-ods v0.5.6 " + "Find 0.5.6 in changelog for more details") -NO_GS_MESSAGE = ('Automatic github release is disabled. ' + - 'Please install gease to enable it.') +NO_GS_MESSAGE = ("Automatic github release is disabled. " + + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( 'Upload failed. please run "%s" yourself.' % PUBLISH_COMMAND) HERE = os.path.abspath(os.path.dirname(__file__)) @@ -75,13 +79,13 @@ HERE = os.path.abspath(os.path.dirname(__file__)) class PublishCommand(Command): """Support setup.py upload.""" - description = 'Build and publish the package on github and pypi' + description = "Build and publish the package on github and pypi" user_options = [] @staticmethod def status(s): """Prints things in bold.""" - print('\033[1m{0}\033[0m'.format(s)) + print("\033[1m{0}\033[0m".format(s)) def initialize_options(self): pass @@ -91,14 +95,14 @@ class PublishCommand(Command): def run(self): try: - self.status('Removing previous builds...') - rmtree(os.path.join(HERE, 'dist')) - rmtree(os.path.join(HERE, 'build')) - rmtree(os.path.join(HERE, 'pyexcel_ods.egg-info')) + self.status("Removing previous builds...") + rmtree(os.path.join(HERE, "dist")) + rmtree(os.path.join(HERE, "build")) + rmtree(os.path.join(HERE, "pyexcel_ods.egg-info")) except OSError: pass - self.status('Building Source and Wheel (universal) distribution...') + self.status("Building Source and Wheel (universal) distribution...") run_status = True if has_gease(): run_status = os.system(GS_COMMAND) == 0 @@ -106,13 +110,13 @@ class PublishCommand(Command): self.status(NO_GS_MESSAGE) if run_status: if os.system(PUBLISH_COMMAND) != 0: - self.status(UPLOAD_FAILED_MSG % PUBLISH_COMMAND) + self.status(UPLOAD_FAILED_MSG) sys.exit() SETUP_COMMANDS.update({ - 'publish': PublishCommand + "publish": PublishCommand }) @@ -141,7 +145,7 @@ def read_files(*files): def read(afile): """Read a file into setup""" the_relative_file = os.path.join(HERE, afile) - with codecs.open(the_relative_file, 'r', 'utf-8') as opened_file: + with codecs.open(the_relative_file, "r", "utf-8") as opened_file: content = filter_out_test_code(opened_file) content = "".join(list(content)) return content @@ -150,11 +154,11 @@ def read(afile): def filter_out_test_code(file_handle): found_test_code = False for line in file_handle.readlines(): - if line.startswith('.. testcode:'): + if line.startswith(".. testcode:"): found_test_code = True continue if found_test_code is True: - if line.startswith(' '): + if line.startswith(" "): continue else: empty_line = line.strip() @@ -164,14 +168,14 @@ def filter_out_test_code(file_handle): found_test_code = False yield line else: - for keyword in ['|version|', '|today|']: + for keyword in ["|version|", "|today|"]: if keyword in line: break else: yield line -if __name__ == '__main__': +if __name__ == "__main__": setup( test_suite="tests", name=NAME, @@ -185,7 +189,7 @@ if __name__ == '__main__': license=LICENSE, keywords=KEYWORDS, extras_require=EXTRAS_REQUIRE, - tests_require=['nose'], + tests_require=["nose"], install_requires=INSTALL_REQUIRES, packages=PACKAGES, include_package_data=True, diff --git a/test.sh b/test.sh index ecba1ba..dacfc93 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,3 @@ +#/bin/bash pip freeze nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_ods diff --git a/tests/test_formatters.py b/tests/test_formatters.py index ba78ec2..ae1e6e8 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -2,6 +2,7 @@ import os from textwrap import dedent import pyexcel as pe + from nose.tools import eq_ From a0076fdcbe17b32c052e8957f9f173417c61e8bf Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 12 Nov 2019 19:46:57 +0000 Subject: [PATCH 097/111] :shirt: update travis yaml file --- .../{travis.yml => custom_travis.yml.jj2} | 0 .moban.yml | 2 +- .travis.yml | 64 +++++++++++++++++-- 3 files changed, 61 insertions(+), 5 deletions(-) rename .moban.d/{travis.yml => custom_travis.yml.jj2} (100%) diff --git a/.moban.d/travis.yml b/.moban.d/custom_travis.yml.jj2 similarity index 100% rename from .moban.d/travis.yml rename to .moban.d/custom_travis.yml.jj2 diff --git a/.moban.yml b/.moban.yml index dc2c267..5a23821 100644 --- a/.moban.yml +++ b/.moban.yml @@ -5,7 +5,7 @@ targets: - README.rst: custom_README.rst.jj2 - setup.py: custom_setup.py.jj2 - "docs/source/conf.py": "docs/source/conf.py.jj2" - - .travis.yml: travis.yml + - .travis.yml: custom_travis.yml.jj2 - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 - "tests/requirements.txt": "tests/requirements.txt" diff --git a/.travis.yml b/.travis.yml index a94a221..1881eac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,67 @@ -{% extends "travis.yml.jj2" %} - -{%block custom_python_versions%} +sudo: false +dist: xenial +language: python +notifications: + email: false python: - 3.8-dev - 3.7 - 3.6 - 3.5 - 2.7 -{%endblock%} +stages: + - lint + - moban + - test + +.disable_global: &disable_global + addons: false + cache: false + env: {} + python: false + before_install: false + install: false + before_script: false + script: false + after_success: false + after_failure: false + before_deploy: false + deploy: false + +.lint: &lint + <<: *disable_global + git: + submodules: false + python: 3.6 + stage: lint + script: make lint + +.moban: &moban + <<: *disable_global + python: 3.6 + stage: moban + install: pip install moban>=0.0.4 + script: + - moban + - git diff --exit-code + +jobs: + include: + - *moban + - *lint + +stage: test + +before_install: + - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then + mv min_requirements.txt requirements.txt ; + fi + - test ! -f rnd_requirements.txt || + pip install --no-deps -r rnd_requirements.txt + - test ! -f rnd_requirements.txt || pip install -r rnd_requirements.txt ; + - pip install -r tests/requirements.txt +script: + - make test +after_success: + codecov From 711dc8d1b528a432100f66daccfcd5ff25ef067d Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 12 Nov 2019 19:49:20 +0000 Subject: [PATCH 098/111] :fire: remove test file generation --- .moban.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.moban.yml b/.moban.yml index 5a23821..7ee24e3 100644 --- a/.moban.yml +++ b/.moban.yml @@ -9,8 +9,3 @@ targets: - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 - "tests/requirements.txt": "tests/requirements.txt" - - "tests/test_filter.py": "tests/test_filter.py.jj2" - - "tests/test_formatters.py": "tests/test_formatters.py" - - "tests/test_stringio.py": "tests/test_stringio.py.jj2" - - "tests/test_writer.py": "tests/test_writer.py.jj2" - - "tests/base.py": "tests/base.py.jj2" From 8e39448d98f1f963c844ac9e1bab7a4afb6fb333 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 8 Jun 2020 22:46:03 +0100 Subject: [PATCH 099/111] :handshake: synchronize the organisational meta data --- .github/PULL_REQUEST_TEMPLATE.md | 2 ++ .gitignore | 46 ++++++++++++++++++++++--- .travis.yml | 21 +++--------- LICENSE | 2 +- README.rst | 58 +++++++++++++++++++------------- docs/source/conf.py | 2 +- pyexcel-ods.yml | 4 ++- setup.py | 24 +++++++------ 8 files changed, 102 insertions(+), 57 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7b632ce..d5a2c03 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,6 +2,8 @@ With your PR, here is a check list: - [ ] Has Test cases written - [ ] Has all code lines tested +- [ ] Has `make format` been run? +- [ ] Has `moban` been run? - [ ] Passes all Travis CI builds - [ ] Has fair amount of documentation if your change is complex - [ ] run 'make format' so as to confirm the pyexcel organisation's coding style diff --git a/.gitignore b/.gitignore index 88bc3f6..a9ca840 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,6 @@ parts/ sdist/ var/ wheels/ -pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg @@ -52,8 +51,10 @@ htmlcov/ nosetests.xml coverage.xml *.cover +*.py,cover .hypothesis/ .pytest_cache/ +cover/ # Translations *.mo @@ -63,6 +64,7 @@ coverage.xml *.log local_settings.py db.sqlite3 +db.sqlite3-journal # Flask stuff: instance/ @@ -75,6 +77,7 @@ instance/ docs/_build/ # PyBuilder +.pybuilder/ target/ # Jupyter Notebook @@ -85,17 +88,23 @@ profile_default/ ipython_config.py # pyenv -.python-version +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don’t work, or not +# having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock -# celery beat schedule file +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff celerybeat-schedule +celerybeat.pid # SageMath parsed files *.sage.py @@ -127,6 +136,12 @@ dmypy.json # Pyre type checker .pyre/ +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + # VirtualEnv rules # Virtualenv # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ @@ -159,6 +174,7 @@ pip-selfcheck.json # Windows rules # Windows thumbnail cache files Thumbs.db +Thumbs.db:encryptable ehthumbs.db ehthumbs_vista.db @@ -264,6 +280,7 @@ flycheck_*.el # Vim rules # Swap [._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files [._]*.sw[a-p] [._]s[a-rt-v][a-z] [._]ss[a-gi-z] @@ -271,6 +288,7 @@ flycheck_*.el # Session Session.vim +Sessionx.vim # Temporary .netrwhist @@ -281,7 +299,7 @@ tags [._]*.un~ # JetBrains rules -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff @@ -311,9 +329,14 @@ tags # When using Gradle or Maven with auto-import, you should exclude module files, # since they will be recreated, and may cause churn. Uncomment if using # auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml # .idea/modules.xml # .idea/*.iml # .idea/modules +# *.iml +# *.ipr # CMake cmake-build-*/ @@ -363,6 +386,7 @@ fabric.properties # SFTP configuration file sftp-config.json +sftp-config-alt*.json # Package control specific files Package Control.last-run @@ -400,6 +424,10 @@ tmtags !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ # Xcode rules # Xcode @@ -426,6 +454,9 @@ DerivedData/ *.perspectivev3 !default.perspectivev3 +## Gcc Patch +/*.gcno + # Eclipse rules .metadata bin/ @@ -477,12 +508,17 @@ local.properties # Annotation Processing .apt_generated/ +.apt_generated_test/ # Scala IDE specific (Scala & Java development for Eclipse) .cache-main .scala_dependencies .worksheet +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + # TortoiseGit rules # Project-level settings /.tgitconfig diff --git a/.travis.yml b/.travis.yml index 1881eac..94e3c9a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,33 +15,22 @@ stages: - moban - test -.disable_global: &disable_global - addons: false - cache: false - env: {} - python: false - before_install: false - install: false - before_script: false - script: false - after_success: false - after_failure: false - before_deploy: false - deploy: false .lint: &lint - <<: *disable_global git: submodules: false python: 3.6 + env: + - MINREQ=0 stage: lint script: make lint .moban: &moban - <<: *disable_global python: 3.6 + env: + - MINREQ=0 stage: moban - install: pip install moban>=0.0.4 + install: pip install moban>=0.0.4 gitfs2 pypifs script: - moban - git diff --exit-code diff --git a/LICENSE b/LICENSE index 0f53832..dd9cb68 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2019 by Onni Software Ltd. and its contributors +Copyright (c) 2015-2020 by Onni Software Ltd. and its contributors All rights reserved. Redistribution and use in source and binary forms of the software as well diff --git a/README.rst b/README.rst index 24e006e..ba331b0 100644 --- a/README.rst +++ b/README.rst @@ -5,6 +5,9 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png :target: https://www.patreon.com/chfw +.. image:: https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg + :target: https://awesome-python.com/#specific-formats-processing + .. image:: https://travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-ods @@ -30,6 +33,24 @@ ods format using python 2.6 and python 2.7. You are likely to use it with depends on ezodf and lxml. `pyexcel-odsr `_ is the other sister library that has no external dependency but do ods reading only +Support the project +================================================================================ + +If your company has embedded pyexcel and its components into a revenue generating +product, please support me on github, `patreon `_ +or `bounty source `_ to maintain +the project and develop it further. + +If you are an individual, you are welcome to support me too and for however long +you feel like. As my backer, you will receive +`early access to pyexcel related contents `_. + +And your issues will get prioritized if you would like to become my patreon as `pyexcel pro user`. + +With your financial support, I will be able to invest +a little bit more time in coding, documentation and writing interesting posts. + + Known constraints ================== @@ -54,24 +75,6 @@ or clone it and install it: $ cd pyexcel-ods $ python setup.py install -Support the project -================================================================================ - -If your company has embedded pyexcel and its components into a revenue generating -product, please support me on `github `_, `patreon `_ -or `bounty source `_ to maintain -the project and develop it further. - -If you are an individual, you are welcome to support me too and for however long -you feel like. As my backer, you will receive -`early access to pyexcel related contents `_. - -And your issues will get prioritized if you would like to become my patreon as `pyexcel pro user`. - -With your financial support, I will be able to invest -a little bit more time in coding, documentation and writing interesting posts. - - Usage ================================================================================ @@ -353,18 +356,27 @@ On Windows systems, please issue this command:: > test.bat -How to update test environment and update documentation + +Before you commit +------------------------------ + +Please run:: + + $ make format + +so as to beautify your code otherwise travis-ci may fail your unit test. + + +And make sure you would have run moban command --------------------------------------------------------- Additional steps are required: #. pip install moban #. make your changes in `.moban.d` directory, then issue command `moban` +#. moban -What is pyexcel-commons ---------------------------------- - -Many information that are shared across pyexcel projects, such as: this developer guide, license info, etc. are stored in `pyexcel-commons` project. +otherwise travis-ci may also fail your unit test. What is .moban.d --------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index 4f79234..f1c2f23 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ DESCRIPTION = ( # -- Project information ----------------------------------------------------- project = 'pyexcel-ods' -copyright = '2015-2019 Onni Software Ltd.' +copyright = '2015-2020 Onni Software Ltd.' author = 'C.W.' # The short X.Y version version = '0.5.6' diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index 1201ffe..d041c31 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -4,9 +4,11 @@ nick_name: ods version: 0.5.6 current_version: 0.5.6 release: 0.5.6 -copyright_year: 2015-2019 +copyright_year: 2015-2020 file_type: ods dependencies: - pyexcel-io>=0.5.16 - odfpy>=1.3.5 description: A wrapper library to read, manipulate and write data in ods format +python_requires: ">=3.6" +min_python_version: "3.6" diff --git a/setup.py b/setup.py index db405d1..239d156 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,11 @@ #!/usr/bin/env python3 +""" +Template by pypi-mobans +""" + import os import sys -# Template by pypi-mobans import codecs import locale import platform @@ -10,6 +13,7 @@ from shutil import rmtree from setuptools import Command, setup, find_packages + # Work around mbcs bug in distutils. # http://bugs.python.org/issue10945 # This work around is only if a project supports Python < 3.4 @@ -42,27 +46,26 @@ CLASSIFIERS = [ "Topic :: Software Development :: Libraries", "Programming Language :: Python", "Intended Audience :: Developers", - "Programming Language :: Python :: 2.6", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3.3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", + + "Programming Language :: Python :: 3 :: Only", + + + "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", ] +PYTHON_REQUIRES = ">=3.6" + INSTALL_REQUIRES = [ "pyexcel-io>=0.5.16", "odfpy>=1.3.5", ] SETUP_COMMANDS = {} - -PACKAGES = find_packages(exclude=["ez_setup", "examples", "tests"]) +PACKAGES = find_packages(exclude=["ez_setup", "examples", "tests", "tests.*"]) EXTRAS_REQUIRE = { } # You do not need to read beyond this line @@ -188,6 +191,7 @@ if __name__ == "__main__": long_description=read_files(*FILES), license=LICENSE, keywords=KEYWORDS, + python_requires=PYTHON_REQUIRES, extras_require=EXTRAS_REQUIRE, tests_require=["nose"], install_requires=INSTALL_REQUIRES, From 7b52ebc0ef04688572607eb632a052340a8aad68 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 12 Jun 2020 22:14:20 +0100 Subject: [PATCH 100/111] :green_heart: test rnd pyexcel-io --- .moban.d/custom_travis.yml.jj2 | 14 +++++++++----- .travis.yml | 8 +++++--- rnd_requirements.txt | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 rnd_requirements.txt diff --git a/.moban.d/custom_travis.yml.jj2 b/.moban.d/custom_travis.yml.jj2 index a94a221..73b434a 100644 --- a/.moban.d/custom_travis.yml.jj2 +++ b/.moban.d/custom_travis.yml.jj2 @@ -1,11 +1,15 @@ {% extends "travis.yml.jj2" %} - +{%block extra_matrix %} +matrix: + include: + - python: 3.6 + env: MINREQ=1 +{%endblock%} {%block custom_python_versions%} python: - - 3.8-dev + - 3.8 - 3.7 - 3.6 - - 3.5 - - 2.7 {%endblock%} - +{%block pypi_deployment%} +{%endblock %} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 94e3c9a..3901204 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,11 +4,13 @@ language: python notifications: email: false python: - - 3.8-dev + - 3.8 - 3.7 - 3.6 - - 3.5 - - 2.7 +matrix: + include: + - python: 3.6 + env: MINREQ=1 stages: - lint diff --git a/rnd_requirements.txt b/rnd_requirements.txt new file mode 100644 index 0000000..a4748b0 --- /dev/null +++ b/rnd_requirements.txt @@ -0,0 +1 @@ +https://github.com/pyexcel/pyexcel-io/archive/dev.zip From d739ae7886bc36f0eee849051e99005a01c7f9a5 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 12 Jun 2020 23:28:29 +0100 Subject: [PATCH 101/111] :handshake: synch with pyexcel-mobans --- .moban.d/custom_travis.yml.jj2 | 8 +++----- .moban.yml | 1 - .travis.yml | 6 ++---- lint.sh | 3 ++- pyexcel-ods.yml | 4 ++++ tests/requirements.txt | 8 +++++--- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.moban.d/custom_travis.yml.jj2 b/.moban.d/custom_travis.yml.jj2 index 73b434a..d330a08 100644 --- a/.moban.d/custom_travis.yml.jj2 +++ b/.moban.d/custom_travis.yml.jj2 @@ -1,9 +1,7 @@ {% extends "travis.yml.jj2" %} {%block extra_matrix %} -matrix: - include: - - python: 3.6 - env: MINREQ=1 +env: + - MINREQ=1 {%endblock%} {%block custom_python_versions%} python: @@ -12,4 +10,4 @@ python: - 3.6 {%endblock%} {%block pypi_deployment%} -{%endblock %} \ No newline at end of file +{%endblock %} diff --git a/.moban.yml b/.moban.yml index 7ee24e3..4f49247 100644 --- a/.moban.yml +++ b/.moban.yml @@ -8,4 +8,3 @@ targets: - .travis.yml: custom_travis.yml.jj2 - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 - - "tests/requirements.txt": "tests/requirements.txt" diff --git a/.travis.yml b/.travis.yml index 3901204..6f4639e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,8 @@ python: - 3.8 - 3.7 - 3.6 -matrix: - include: - - python: 3.6 - env: MINREQ=1 +env: + - MINREQ=1 stages: - lint diff --git a/lint.sh b/lint.sh index 976f745..6907d07 100644 --- a/lint.sh +++ b/lint.sh @@ -1,2 +1,3 @@ pip install flake8 -flake8 . --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long \ No newline at end of file +flake8 . --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long +python setup.py checkdocs diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index d041c31..e8235c8 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -9,6 +9,10 @@ file_type: ods dependencies: - pyexcel-io>=0.5.16 - odfpy>=1.3.5 +test_dependencies: + - pyexcel + - psutil + - pyexcel-xls description: A wrapper library to read, manipulate and write data in ods format python_requires: ">=3.6" min_python_version: "3.6" diff --git a/tests/requirements.txt b/tests/requirements.txt index 7a755ef..17bc903 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,9 +3,11 @@ mock;python_version<"3" codecov coverage flake8 +black +isort +collective.checkdocs +pygments moban -black;python_version>="3.6" -isort;python_version>="3.6" -psutil pyexcel +psutil pyexcel-xls From 9260b3e9d690b85acba3057959bcebce620f91e2 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 23 Aug 2020 01:23:51 +0100 Subject: [PATCH 102/111] :rocket: github actions for moban, pypi release and automatically extract contributors --- .github/PULL_REQUEST_TEMPLATE.md | 5 ++--- .github/workflows/moban-update.yml | 27 +++++++++++++++++++++++++++ .github/workflows/pythonpublish.yml | 26 ++++++++++++++++++++++++++ CONTRIBUTORS.rst | 9 +++++++++ Makefile | 17 ++++++++++++----- README.rst | 16 ---------------- docs/source/conf.py | 2 +- setup.py | 2 +- 8 files changed, 78 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/moban-update.yml create mode 100644 .github/workflows/pythonpublish.yml create mode 100644 CONTRIBUTORS.rst diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d5a2c03..fa2fa6a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,10 +3,9 @@ With your PR, here is a check list: - [ ] Has Test cases written - [ ] Has all code lines tested - [ ] Has `make format` been run? -- [ ] Has `moban` been run? +- [ ] Please update CHANGELOG.yml(not CHANGELOG.rst) - [ ] Passes all Travis CI builds - [ ] Has fair amount of documentation if your change is complex - [ ] run 'make format' so as to confirm the pyexcel organisation's coding style -- [ ] Please update CHANGELOG.rst -- [ ] Please add yourself to CONTRIBUTORS.rst +- [ ] Please add yourself to 'contributors' section of pyexcel-ods.yml (if not found, please use CONTRIBUTORS.rst) - [ ] Agree on NEW BSD License for your contribution diff --git a/.github/workflows/moban-update.yml b/.github/workflows/moban-update.yml new file mode 100644 index 0000000..db4f13a --- /dev/null +++ b/.github/workflows/moban-update.yml @@ -0,0 +1,27 @@ +on: [push] + +jobs: + run_moban: + runs-on: ubuntu-latest + name: synchronize templates via moban + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: '3.7' + - name: check changes + run: | + pip install moban gitfs2 pypifs + moban + git status + git diff --exit-code + - name: Auto-commit + if: failure() + uses: docker://cdssnc/auto-commit-github-action + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml new file mode 100644 index 0000000..9e7ec42 --- /dev/null +++ b/.github/workflows/pythonpublish.yml @@ -0,0 +1,26 @@ +name: Upload Python Package + +on: + release: + types: [created] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + - name: Build and publish + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + python setup.py sdist bdist_wheel + twine upload dist/* diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst new file mode 100644 index 0000000..0445133 --- /dev/null +++ b/CONTRIBUTORS.rst @@ -0,0 +1,9 @@ + +3 contributors +================================================================================ + +In alphabetical order: + +* `Azamat H. Hackimov `_ +* `John Vandenberg `_ +* `Mateusz Konieczny `_ diff --git a/Makefile b/Makefile index d3587b4..d7e640e 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,19 @@ all: test -test: +test: lint bash test.sh -format: - isort -y $(find pyexcel_ods -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) - black -l 79 pyexcel_ods - black -l 79 tests +install_test: + pip install -r tests/requirements.txt + +git-diff-check: + git diff --exit-code lint: bash lint.sh + +format: + bash format.sh + +git-diff-check: + git diff --exit-code diff --git a/README.rst b/README.rst index ba331b0..d7cb182 100644 --- a/README.rst +++ b/README.rst @@ -367,22 +367,6 @@ Please run:: so as to beautify your code otherwise travis-ci may fail your unit test. -And make sure you would have run moban command ---------------------------------------------------------- - -Additional steps are required: - -#. pip install moban -#. make your changes in `.moban.d` directory, then issue command `moban` -#. moban - -otherwise travis-ci may also fail your unit test. - -What is .moban.d ---------------------------------- - -`.moban.d` stores the specific meta data for the library. - Credits ================================================================================ diff --git a/docs/source/conf.py b/docs/source/conf.py index f1c2f23..67e8ad3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,7 @@ DESCRIPTION = ( project = 'pyexcel-ods' copyright = '2015-2020 Onni Software Ltd.' -author = 'C.W.' +author = 'chfw' # The short X.Y version version = '0.5.6' # The full version, including alpha/beta/rc tags diff --git a/setup.py b/setup.py index 239d156..4a2482c 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ except (ValueError, UnicodeError, locale.Error): locale.setlocale(locale.LC_ALL, "en_US.UTF-8") NAME = "pyexcel-ods" -AUTHOR = "C.W." +AUTHOR = "chfw" VERSION = "0.5.6" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" From 344e6f0a958c63ce2de854123830050f00959d7f Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 23 Aug 2020 00:24:29 +0000 Subject: [PATCH 103/111] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- MANIFEST.in | 1 + format.sh | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 format.sh diff --git a/MANIFEST.in b/MANIFEST.in index b1bf562..e86ae54 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,6 @@ include README.rst include LICENSE include CHANGELOG.rst +include CONTRIBUTORS.rst recursive-include tests * recursive-include docs * diff --git a/format.sh b/format.sh new file mode 100644 index 0000000..3a0ecb9 --- /dev/null +++ b/format.sh @@ -0,0 +1,3 @@ +isort $(find pyexcel_ods -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) +black -l 79 pyexcel_ods +black -l 79 tests From 2e23f33bea94f21df31da5d30f9ebbd5d7c44253 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 19 Sep 2020 19:32:30 +0100 Subject: [PATCH 104/111] :handshake: update meta data --- .travis.yml | 2 +- MANIFEST.in | 1 + tests/requirements.txt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6f4639e..8718cdd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ stages: env: - MINREQ=0 stage: moban - install: pip install moban>=0.0.4 gitfs2 pypifs + install: pip install moban gitfs2 pypifs moban-jinja2-github moban-ansible script: - moban - git diff --exit-code diff --git a/MANIFEST.in b/MANIFEST.in index b1bf562..e86ae54 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,6 @@ include README.rst include LICENSE include CHANGELOG.rst +include CONTRIBUTORS.rst recursive-include tests * recursive-include docs * diff --git a/tests/requirements.txt b/tests/requirements.txt index 17bc903..ae03e89 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -8,6 +8,7 @@ isort collective.checkdocs pygments moban +moban_jinja2_github pyexcel psutil pyexcel-xls From 07ee703b59e3c4424ed165c2a8dff5fab63479be Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 3 Oct 2020 10:22:16 +0100 Subject: [PATCH 106/111] :handshake: update project meta data and :lipstick: update coding style --- .github/PULL_REQUEST_TEMPLATE.md | 6 ++--- .github/workflows/moban-update.yml | 42 ++++++++++++++++-------------- .gitignore | 4 +++ CONTRIBUTORS.rst | 7 ++--- Makefile | 3 --- lint.sh | 3 +-- pyexcel_ods/odsr.py | 5 ++-- pyexcel_ods/odsw.py | 5 ++-- tests/test_bug_fixes.py | 4 +-- tests/test_filter.py | 3 ++- 10 files changed, 41 insertions(+), 41 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fa2fa6a..6017f21 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,11 +1,9 @@ With your PR, here is a check list: -- [ ] Has Test cases written -- [ ] Has all code lines tested +- [ ] Has test cases written? +- [ ] Has all code lines tested? - [ ] Has `make format` been run? - [ ] Please update CHANGELOG.yml(not CHANGELOG.rst) - [ ] Passes all Travis CI builds - [ ] Has fair amount of documentation if your change is complex -- [ ] run 'make format' so as to confirm the pyexcel organisation's coding style -- [ ] Please add yourself to 'contributors' section of pyexcel-ods.yml (if not found, please use CONTRIBUTORS.rst) - [ ] Agree on NEW BSD License for your contribution diff --git a/.github/workflows/moban-update.yml b/.github/workflows/moban-update.yml index db4f13a..706fd82 100644 --- a/.github/workflows/moban-update.yml +++ b/.github/workflows/moban-update.yml @@ -5,23 +5,25 @@ jobs: runs-on: ubuntu-latest name: synchronize templates via moban steps: - - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - name: Set up Python - uses: actions/setup-python@v1 - with: - python-version: '3.7' - - name: check changes - run: | - pip install moban gitfs2 pypifs - moban - git status - git diff --exit-code - - name: Auto-commit - if: failure() - uses: docker://cdssnc/auto-commit-github-action - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - args: This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst + - uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: '3.7' + - name: check changes + run: | + pip install moban gitfs2 pypifs moban-jinja2-github moban-ansible + moban + git status + git diff --exit-code + - name: Auto-commit + if: failure() + uses: docker://cdssnc/auto-commit-github-action + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: >- + This is an auto-commit, updating project meta data, + such as changelog.rst, contributors.rst diff --git a/.gitignore b/.gitignore index a9ca840..e8b12f9 100644 --- a/.gitignore +++ b/.gitignore @@ -540,3 +540,7 @@ cscope.files cscope.out cscope.in.out cscope.po.out + + +# remove moban hash dictionary +.moban.hashes diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 0445133..ccdfc96 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -1,9 +1,10 @@ + 3 contributors ================================================================================ In alphabetical order: -* `Azamat H. Hackimov `_ -* `John Vandenberg `_ -* `Mateusz Konieczny `_ +* `Azamat H. Hackimov `_ +* `John Vandenberg `_ +* `Mateusz Konieczny `_ diff --git a/Makefile b/Makefile index d7e640e..3e0ee51 100644 --- a/Makefile +++ b/Makefile @@ -6,9 +6,6 @@ test: lint install_test: pip install -r tests/requirements.txt -git-diff-check: - git diff --exit-code - lint: bash lint.sh diff --git a/lint.sh b/lint.sh index 6907d07..891aa63 100644 --- a/lint.sh +++ b/lint.sh @@ -1,3 +1,2 @@ pip install flake8 -flake8 . --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long -python setup.py checkdocs +flake8 --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long . && python setup.py checkdocs diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 9aa3cee..5cd5113 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -21,16 +21,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import pyexcel_io.service as service from odf.text import P from odf.table import Table, TableRow, TableCell # Thanks to grt for the fixes from odf.teletype import extractText from odf.namespaces import OFFICENS -from odf.opendocument import load - -import pyexcel_io.service as service from pyexcel_io.book import BookReader +from odf.opendocument import load from pyexcel_io.sheet import SheetReader from pyexcel_io._compact import OrderedDict diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index 2cbe118..429bd42 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -9,13 +9,12 @@ """ import sys +import pyexcel_io.service as converter from odf.text import P from odf.table import Table, TableRow, TableCell from odf.namespaces import OFFICENS -from odf.opendocument import OpenDocumentSpreadsheet - -import pyexcel_io.service as converter from pyexcel_io.book import BookWriter +from odf.opendocument import OpenDocumentSpreadsheet from pyexcel_io.sheet import SheetWriter PY2 = sys.version_info[0] == 2 diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index de4d13b..c644529 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -2,13 +2,13 @@ # -*- encoding: utf-8 -*- import os +import psutil import pyexcel as pe from pyexcel_ods import get_data, save_data +from pyexcel_io.exceptions import IntegerAccuracyLossError -import psutil from nose import SkipTest from nose.tools import eq_, raises -from pyexcel_io.exceptions import IntegerAccuracyLossError IN_TRAVIS = "TRAVIS" in os.environ diff --git a/tests/test_filter.py b/tests/test_filter.py index 67d8876..029e04b 100644 --- a/tests/test_filter.py +++ b/tests/test_filter.py @@ -1,8 +1,9 @@ import os -from nose.tools import eq_ from pyexcel_io import get_data, save_data +from nose.tools import eq_ + class TestFilter: def setUp(self): From 24813b2d34c6ca8ce27cb7d2ef72c58eb66d68e2 Mon Sep 17 00:00:00 2001 From: jaska Date: Sat, 3 Oct 2020 14:27:56 +0100 Subject: [PATCH 107/111] New style reader writer (#39) * :tada: new style ods reader written * This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst * :sparkles: new style ods writer Co-authored-by: chfw --- .isort.cfg | 2 +- CHANGELOG.rst | 7 ++++ changelog.yml | 6 +++ docs/source/conf.py | 2 +- pyexcel-ods.yml | 4 +- pyexcel_ods/__init__.py | 14 +++++-- pyexcel_ods/odsr.py | 87 +++++++++++++++------------------------- pyexcel_ods/odsw.py | 24 +++++------ setup.py | 2 +- tests/test_ods_reader.py | 16 ++++---- tests/test_writer.py | 6 +-- 11 files changed, 81 insertions(+), 89 deletions(-) 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]) From fb82cf285f800515a28c7e283eecfc02fc7ee62f Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 6 Oct 2020 23:23:30 +0100 Subject: [PATCH 108/111] :hammer: code refactoring --- pyexcel_ods/odsr.py | 14 ++++---------- pyexcel_ods/odsw.py | 20 +++++++------------- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index ecc4aa7..444c3eb 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -30,8 +30,8 @@ from odf.table import Table, TableRow, TableCell from odf.teletype import extractText from odf.namespaces import OFFICENS from odf.opendocument import load -from pyexcel_io.plugin_api.abstract_sheet import ISheet -from pyexcel_io.plugin_api.abstract_reader import IReader +from pyexcel_io.plugin_api import ISheet +from pyexcel_io.plugin_api import IReader, NamedContent class ODSSheet(ISheet): @@ -107,13 +107,13 @@ class ODSBook(IReader): self._native_book = load(file_alike_object) self._keywords = keywords self.content_array = [ - NameObject(table.getAttribute("name"), table) + NamedContent(table.getAttribute("name"), table) for table in self._native_book.spreadsheet.getElementsByType(Table) ] def read_sheet(self, sheet_index): """read a sheet at a specified index""" - table = self.content_array[sheet_index].sheet + table = self.content_array[sheet_index].payload sheet = ODSSheet(table, **self._keywords) return sheet @@ -129,9 +129,3 @@ class ODSBookInContent(ODSBook): 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 b13e3f6..e851429 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -7,19 +7,13 @@ :copyright: (c) 2014-2020 by Onni Software Ltd. :license: New BSD License, see LICENSE for more details """ -import sys - import pyexcel_io.service as converter from odf.text import P from odf.table import Table, TableRow, TableCell from odf.namespaces import OFFICENS from odf.opendocument import OpenDocumentSpreadsheet -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 +from pyexcel_io.plugin_api import ISheetWriter +from pyexcel_io.plugin_api import IWriter class ODSSheetWriter(ISheetWriter): @@ -27,7 +21,7 @@ class ODSSheetWriter(ISheetWriter): ODS sheet writer """ - def __init__(self, ods_book, ods_sheet, sheet_name, **keywords): + def __init__(self, ods_book, sheet_name): self._native_book = ods_book self._native_sheet = Table(name=sheet_name) @@ -79,20 +73,20 @@ class ODSWriter(IWriter): """ - def __init__(self, file_alike_object, file_type, **keywords): - self._file_alike_object = file_alike_object + def __init__(self, file_alike_object, file_type, **_): + self.file_alike_object = file_alike_object self._native_book = OpenDocumentSpreadsheet() def create_sheet(self, name): """ write a row into the file """ - return ODSSheetWriter(self._native_book, None, name) + return ODSSheetWriter(self._native_book, name) def close(self): """ This call writes file """ - self._native_book.write(self._file_alike_object) + self._native_book.write(self.file_alike_object) self._native_book = None From ca67cc960929edf60e4f75875fcecae71333e298 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 7 Oct 2020 22:19:58 +0100 Subject: [PATCH 109/111] :green_heart: update unit tests --- pyexcel_ods/odsr.py | 3 +-- pyexcel_ods/odsw.py | 3 +-- tests/test_ods_reader.py | 18 ++++++++++-------- tests/test_writer.py | 8 ++------ 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 444c3eb..178fd4d 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -30,8 +30,7 @@ from odf.table import Table, TableRow, TableCell from odf.teletype import extractText from odf.namespaces import OFFICENS from odf.opendocument import load -from pyexcel_io.plugin_api import ISheet -from pyexcel_io.plugin_api import IReader, NamedContent +from pyexcel_io.plugin_api import ISheet, IReader, NamedContent class ODSSheet(ISheet): diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index e851429..1cb9762 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -12,8 +12,7 @@ from odf.text import P from odf.table import Table, TableRow, TableCell from odf.namespaces import OFFICENS from odf.opendocument import OpenDocumentSpreadsheet -from pyexcel_io.plugin_api import ISheetWriter -from pyexcel_io.plugin_api import IWriter +from pyexcel_io.plugin_api import IWriter, ISheetWriter class ODSSheetWriter(ISheetWriter): diff --git a/tests/test_ods_reader.py b/tests/test_ods_reader.py index 384da20..f236bf5 100644 --- a/tests/test_ods_reader.py +++ b/tests/test_ods_reader.py @@ -3,13 +3,14 @@ import os from base import ODSCellTypes from pyexcel_ods.odsr import ODSBook from pyexcel_ods.odsw import ODSWriter +from pyexcel_io.reader import Reader class TestODSReader(ODSCellTypes): def setUp(self): - r = ODSBook( - os.path.join("tests", "fixtures", "ods_formats.ods"), "ods" - ) + r = Reader("ods") + r.reader_class = ODSBook + r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) self.data = r.read_all() for key in self.data.keys(): self.data[key] = list(self.data[key]) @@ -18,16 +19,17 @@ class TestODSReader(ODSCellTypes): class TestODSWriter(ODSCellTypes): def setUp(self): - r = ODSBook( - os.path.join("tests", "fixtures", "ods_formats.ods"), "ods" - ) + r = Reader("ods") + r.reader_class = ODSBook + r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) + r.close() self.data1 = r.read_all() self.testfile = "odswriter.ods" w = ODSWriter(self.testfile, "ods") w.write(self.data1) w.close() - r2 = ODSBook(self.testfile, "ods") - self.data = r2.read_all() + r.open(self.testfile) + self.data = r.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 73c32aa..1402ce5 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,7 +1,7 @@ import os from base import PyexcelWriterBase, PyexcelHatWriterBase -from pyexcel_ods.odsr import ODSBook as Reader +from pyexcel_io import get_data from pyexcel_ods.odsw import ODSWriter as Writer @@ -16,12 +16,8 @@ class TestNativeODSWriter: writer = Writer(self.testfile, "ods") writer.write(self.content) writer.close() - reader = Reader(self.testfile, "ods") - content = reader.read_all() - for key in content.keys(): - content[key] = list(content[key]) + content = get_data(self.testfile, library="pyexcel-ods") assert content == self.content - reader.close() def tearDown(self): if os.path.exists(self.testfile): From ebb9c2f8f286a4e1d55ae60ed84d097ba0346f5d Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 8 Oct 2020 22:46:46 +0100 Subject: [PATCH 110/111] :egg: :ferris_wheel: release 0.6.0 --- CHANGELOG.rst | 4 ++-- LICENSE | 2 +- README.rst | 5 +++++ changelog.yml | 4 ++-- docs/source/conf.py | 2 +- pyexcel-ods.yml | 4 ++-- requirements.txt | 2 +- setup.py | 8 ++++---- 8 files changed, 18 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fc86868..c2249ed 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,12 +1,12 @@ Change log ================================================================================ -0.6.0 - 2020 +0.6.0 - 9.10.2020 -------------------------------------------------------------------------------- **added** -#. new style reader and writer plugins. works with pyexcel-io v0.6.0 +#. new style reader and writer plugins. works with pyexcel-io v0.6.2 0.5.6 - 19.03.2019 -------------------------------------------------------------------------------- diff --git a/LICENSE b/LICENSE index dd9cb68..a0a4488 100644 --- a/LICENSE +++ b/LICENSE @@ -13,7 +13,7 @@ that the following conditions are met: and/or other materials provided with the distribution. * Neither the name of 'pyexcel-ods' nor the names of the contributors - may be used to endorse or promote products derived from this software + may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND diff --git a/README.rst b/README.rst index d7cb182..abbced9 100644 --- a/README.rst +++ b/README.rst @@ -25,6 +25,11 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg :target: https://gitter.im/pyexcel/Lobby +.. image:: https://img.shields.io/static/v1?label=continuous%20templating&message=%E6%A8%A1%E7%89%88%E6%9B%B4%E6%96%B0&color=blue&style=flat-square + :target: https://moban.readthedocs.io/en/latest/#at-scale-continous-templating-for-open-source-projects + +.. image:: https://img.shields.io/static/v1?label=coding%20style&message=black&color=black&style=flat-square + :target: https://github.com/psf/black **pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in ods format using python 2.6 and python 2.7. You are likely to use it with diff --git a/changelog.yml b/changelog.yml index 8bb7c9d..1692c01 100644 --- a/changelog.yml +++ b/changelog.yml @@ -4,8 +4,8 @@ releases: - changes: - action: added details: - - 'new style reader and writer plugins. works with pyexcel-io v0.6.0' - date: 2020 + - 'new style reader and writer plugins. works with pyexcel-io v0.6.2' + date: 9.10.2020 version: 0.6.0 - changes: - action: added diff --git a/docs/source/conf.py b/docs/source/conf.py index 664ab82..5a459b0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -27,7 +27,7 @@ author = 'chfw' # The short X.Y version version = '0.6.0' # The full version, including alpha/beta/rc tags -release = '0.5.6' +release = '0.6.0' # -- General configuration --------------------------------------------------- diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index 94a0235..5eefaa6 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -3,11 +3,11 @@ name: "pyexcel-ods" nick_name: ods version: 0.6.0 current_version: 0.6.0 -release: 0.5.6 +release: 0.6.0 copyright_year: 2015-2020 file_type: ods dependencies: - - pyexcel-io>=0.5.16 + - pyexcel-io>=0.6.2 - odfpy>=1.3.5 test_dependencies: - pyexcel diff --git a/requirements.txt b/requirements.txt index a6599ba..10c1e1d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.5.16 +pyexcel-io>=0.6.2 odfpy>=1.3.5 diff --git a/setup.py b/setup.py index d2f1740..e4a3e42 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ DESCRIPTION = ( "A wrapper library to read, manipulate and write data in ods format" ) URL = "https://github.com/pyexcel/pyexcel-ods" -DOWNLOAD_URL = "%s/archive/0.5.6.tar.gz" % URL +DOWNLOAD_URL = "%s/archive/0.6.0.tar.gz" % URL FILES = ["README.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", @@ -60,7 +60,7 @@ CLASSIFIERS = [ PYTHON_REQUIRES = ">=3.6" INSTALL_REQUIRES = [ - "pyexcel-io>=0.5.16", + "pyexcel-io>=0.6.2", "odfpy>=1.3.5", ] SETUP_COMMANDS = {} @@ -70,8 +70,8 @@ EXTRAS_REQUIRE = { } # You do not need to read beyond this line PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) -GS_COMMAND = ("gs pyexcel-ods v0.5.6 " + - "Find 0.5.6 in changelog for more details") +GS_COMMAND = ("gs pyexcel-ods v0.6.0 " + + "Find 0.6.0 in changelog for more details") NO_GS_MESSAGE = ("Automatic github release is disabled. " + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( From 661d4f0b484ed281128c72e1a2701e2d33fc1879 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 28 Nov 2020 22:33:41 +0000 Subject: [PATCH 111/111] :fire: remove travis build from ci. credit goes to #234 --- .github/PULL_REQUEST_TEMPLATE.md | 1 - .github/workflows/lint.yml | 20 ++++++++++++ .github/workflows/tests.yml | 32 ++++++++++++++++++ .moban.d/custom_travis.yml.jj2 | 13 -------- .moban.yml | 1 - .travis.yml | 56 -------------------------------- README.rst | 10 +++--- docs/source/conf.py | 2 +- lint.sh | 2 +- setup.py | 8 ++--- 10 files changed, 64 insertions(+), 81 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/tests.yml delete mode 100644 .moban.d/custom_travis.yml.jj2 delete mode 100644 .travis.yml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6017f21..8996445 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,6 +4,5 @@ With your PR, here is a check list: - [ ] Has all code lines tested? - [ ] Has `make format` been run? - [ ] Please update CHANGELOG.yml(not CHANGELOG.rst) -- [ ] Passes all Travis CI builds - [ ] Has fair amount of documentation if your change is complex - [ ] Agree on NEW BSD License for your contribution diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..03122a1 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,20 @@ +name: lint + +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + name: lint code + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - name: lint + run: | + pip install flake8 + pip install -r tests/requirements.txt + flake8 --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long . + python setup.py checkdocs diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..5d03855 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,32 @@ +name: run_tests + +on: [push, pull_request] + +jobs: + test: + strategy: + fail-fast: false + matrix: + python-version: [3.6, 3.7, 3.8, 3.9] + os: [macOs-latest, ubuntu-latest, windows-latest] + + runs-on: ${{ matrix.os }} + name: run tests + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: install + run: | + pip install -r requirements.txt + pip install -r tests/requirements.txt + - name: test + run: | + pip freeze + nosetests --verbosity=3 --with-coverage --cover-package pyexcel_ods --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_ods + - name: Upload coverage + uses: codecov/codecov-action@v1 + with: + name: ${{ matrix.os }} Python ${{ matrix.python-version }} \ No newline at end of file diff --git a/.moban.d/custom_travis.yml.jj2 b/.moban.d/custom_travis.yml.jj2 deleted file mode 100644 index d330a08..0000000 --- a/.moban.d/custom_travis.yml.jj2 +++ /dev/null @@ -1,13 +0,0 @@ -{% extends "travis.yml.jj2" %} -{%block extra_matrix %} -env: - - MINREQ=1 -{%endblock%} -{%block custom_python_versions%} -python: - - 3.8 - - 3.7 - - 3.6 -{%endblock%} -{%block pypi_deployment%} -{%endblock %} diff --git a/.moban.yml b/.moban.yml index 4f49247..46b2d76 100644 --- a/.moban.yml +++ b/.moban.yml @@ -5,6 +5,5 @@ targets: - README.rst: custom_README.rst.jj2 - setup.py: custom_setup.py.jj2 - "docs/source/conf.py": "docs/source/conf.py.jj2" - - .travis.yml: custom_travis.yml.jj2 - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8718cdd..0000000 --- a/.travis.yml +++ /dev/null @@ -1,56 +0,0 @@ -sudo: false -dist: xenial -language: python -notifications: - email: false -python: - - 3.8 - - 3.7 - - 3.6 -env: - - MINREQ=1 - -stages: - - lint - - moban - - test - - -.lint: &lint - git: - submodules: false - python: 3.6 - env: - - MINREQ=0 - stage: lint - script: make lint - -.moban: &moban - python: 3.6 - env: - - MINREQ=0 - stage: moban - install: pip install moban gitfs2 pypifs moban-jinja2-github moban-ansible - script: - - moban - - git diff --exit-code - -jobs: - include: - - *moban - - *lint - -stage: test - -before_install: - - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then - mv min_requirements.txt requirements.txt ; - fi - - test ! -f rnd_requirements.txt || - pip install --no-deps -r rnd_requirements.txt - - test ! -f rnd_requirements.txt || pip install -r rnd_requirements.txt ; - - pip install -r tests/requirements.txt -script: - - make test -after_success: - codecov diff --git a/README.rst b/README.rst index abbced9..b74e157 100644 --- a/README.rst +++ b/README.rst @@ -5,11 +5,11 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png :target: https://www.patreon.com/chfw -.. image:: https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg +.. image:: https://raw.githubusercontent.com/pyexcel/pyexcel-mobans/master/images/awesome-badge.svg :target: https://awesome-python.com/#specific-formats-processing -.. image:: https://travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master - :target: http://travis-ci.org/pyexcel/pyexcel-ods +.. image:: https://github.com/pyexcel/pyexcel-ods/workflows/run_tests/badge.svg + :target: http://github.com/pyexcel/pyexcel-ods/actions .. image:: https://codecov.io/gh/pyexcel/pyexcel-ods/branch/master/graph/badge.svg :target: https://codecov.io/gh/pyexcel/pyexcel-ods @@ -19,7 +19,7 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://pepy.tech/badge/pyexcel-ods/month - :target: https://pepy.tech/project/pyexcel-ods/month + :target: https://pepy.tech/project/pyexcel-ods .. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg @@ -61,6 +61,8 @@ Known constraints Fonts, colors and charts are not supported. +Nor to read password protected xls, xlsx and ods files. + Installation ================================================================================ diff --git a/docs/source/conf.py b/docs/source/conf.py index 5a459b0..46df225 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,7 @@ DESCRIPTION = ( project = 'pyexcel-ods' copyright = '2015-2020 Onni Software Ltd.' -author = 'chfw' +author = 'C.W.' # The short X.Y version version = '0.6.0' # The full version, including alpha/beta/rc tags diff --git a/lint.sh b/lint.sh index 891aa63..d31eeaa 100644 --- a/lint.sh +++ b/lint.sh @@ -1,2 +1,2 @@ pip install flake8 -flake8 --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long . && python setup.py checkdocs +flake8 --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long . && python setup.py checkdocs \ No newline at end of file diff --git a/setup.py b/setup.py index e4a3e42..b9f9462 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ except (ValueError, UnicodeError, locale.Error): locale.setlocale(locale.LC_ALL, "en_US.UTF-8") NAME = "pyexcel-ods" -AUTHOR = "chfw" +AUTHOR = "C.W." VERSION = "0.6.0" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" @@ -70,13 +70,14 @@ EXTRAS_REQUIRE = { } # You do not need to read beyond this line PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) -GS_COMMAND = ("gs pyexcel-ods v0.6.0 " + +HERE = os.path.abspath(os.path.dirname(__file__)) + +GS_COMMAND = ("gease pyexcel-ods v0.6.0 " + "Find 0.6.0 in changelog for more details") NO_GS_MESSAGE = ("Automatic github release is disabled. " + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( 'Upload failed. please run "%s" yourself.' % PUBLISH_COMMAND) -HERE = os.path.abspath(os.path.dirname(__file__)) class PublishCommand(Command): @@ -122,7 +123,6 @@ SETUP_COMMANDS.update({ "publish": PublishCommand }) - def has_gease(): """ test if github release command is installed