From 974f66eecde732504a898caa97c9c733f95124b7 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 20 Sep 2016 18:38:22 +0100 Subject: [PATCH 001/163] fix #10 support two dimensional generators: a generator list of a generator list --- CHANGELOG.rst | 9 ++++++ README.rst | 2 +- docs/source/conf.py | 4 +-- pyexcel_xls.yaml | 4 +-- pyexcel_xls/xls.py | 3 +- setup.py | 65 ++++++++++++++++++++++++++++------------- test.bat | 3 +- test.sh | 3 +- tests/test_bug_fixes.py | 9 ++++++ 9 files changed, 72 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b8ddd29..872148f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.2.3 - unreleased +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#10 `_, To support + generator as member of the incoming two dimensional data + 0.2.2 - 31.08.2016 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index 48efabb..18bafa7 100644 --- a/README.rst +++ b/README.rst @@ -280,7 +280,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 6b93174..cd49c48 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,8 +16,8 @@ master_doc = 'index' project = u'pyexcel-xls' 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_xls.yaml b/pyexcel_xls.yaml index 8b53f43..f9b9b3a 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.2.2 -release: 0.2.1 +version: 0.2.3 +release: 0.2.2 file_type: xls dependencies: - pyexcel-io>=0.2.2 diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 3cbebfc..d40b5e0 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -190,8 +190,7 @@ class XLSheetWriter(SheetWriter): """ write a row into the file """ - for i in range(len(array)): - value = array[i] + for i, value in enumerate(array): style = None tmp_array = [] if isinstance(value, datetime.datetime): diff --git a/setup.py b/setup.py index 4a8f428..fa0ca9f 100644 --- a/setup.py +++ b/setup.py @@ -10,10 +10,9 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.2.2' +VERSION = '0.2.3' 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 xls format. It' + ' reads xlsx and xlsm format' + @@ -28,19 +27,6 @@ KEYWORDS = [ 'xlsm' ] -INSTALL_REQUIRES = [ - 'pyexcel-io>=0.2.2', - 'xlrd', -] - -if PY2: - INSTALL_REQUIRES.append('xlwt') -if not PY2: - INSTALL_REQUIRES.append('xlwt-future') - -EXTRAS_REQUIRE = { -} - CLASSIFIERS = [ 'Topic :: Office/Business', 'Topic :: Utilities', @@ -57,19 +43,56 @@ CLASSIFIERS = [ 'Programming Language :: Python :: Implementation :: PyPy' ] +INSTALL_REQUIRES = [ + 'pyexcel-io>=0.2.2', + 'xlrd', +] + +if PY2: + INSTALL_REQUIRES.append('xlwt') +if not PY2: + INSTALL_REQUIRES.append('xlwt-future') + +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__': @@ -79,14 +102,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 00c3550..45ba0f8 100644 --- a/test.bat +++ b/test.bat @@ -1,3 +1,4 @@ + pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index 00c3550..45ba0f8 100644 --- a/test.sh +++ b/test.sh @@ -1,3 +1,4 @@ + pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index cca61f2..2268ee8 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -45,3 +45,12 @@ class TestBugFix: assert "hidden" in book_dict eq_(book_dict['shown'], [['A', 'B']]) eq_(book_dict['hidden'], [['a', 'b']]) + + def test_issue_10_generator_as_content(self): + def data_gen(): + def custom_row_renderer(row): + for e in row: + yield e + for i in range(2): + yield custom_row_renderer([1,2]) + save_data("test.xls", {"sheet": data_gen()}) From ba7cfbdd5a1fc9d45120eefe7830e7ea2d4e1c17 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 20 Sep 2016 18:43:59 +0100 Subject: [PATCH 002/163] code reordering --- pyexcel_xls/xls.py | 66 ++++++++++++++++++++--------------------- tests/base.py | 2 +- tests/test_bug_fixes.py | 2 +- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index d40b5e0..845e8dc 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -28,39 +28,6 @@ DEFAULT_TIME_FORMAT = "HH:MM:SS" DEFAULT_DATETIME_FORMAT = "%s %s" % (DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT) -def is_integer_ok_for_xl_float(value): - """check if a float value had zero value in digits""" - return value == math.floor(value) - - -def xldate_to_python_date(value): - """ - convert xl date to python date - """ - date_tuple = xlrd.xldate_as_tuple(value, 0) - ret = None - if date_tuple == (0, 0, 0, 0, 0, 0): - ret = datetime.datetime(1900, 1, 1, 0, 0, 0) - elif date_tuple[0:3] == (0, 0, 0): - ret = datetime.time(date_tuple[3], - date_tuple[4], - date_tuple[5]) - elif date_tuple[3:6] == (0, 0, 0): - ret = datetime.date(date_tuple[0], - date_tuple[1], - date_tuple[2]) - else: - ret = datetime.datetime( - date_tuple[0], - date_tuple[1], - date_tuple[2], - date_tuple[3], - date_tuple[4], - date_tuple[5] - ) - return ret - - class XLSheet(SheetReader): """ xls, xlsx, xlsm sheet reader @@ -242,6 +209,39 @@ class XLSWriter(BookWriter): self.work_book.save(self.file_alike_object) +def is_integer_ok_for_xl_float(value): + """check if a float value had zero value in digits""" + return value == math.floor(value) + + +def xldate_to_python_date(value): + """ + convert xl date to python date + """ + date_tuple = xlrd.xldate_as_tuple(value, 0) + ret = None + if date_tuple == (0, 0, 0, 0, 0, 0): + ret = datetime.datetime(1900, 1, 1, 0, 0, 0) + elif date_tuple[0:3] == (0, 0, 0): + ret = datetime.time(date_tuple[3], + date_tuple[4], + date_tuple[5]) + elif date_tuple[3:6] == (0, 0, 0): + ret = datetime.date(date_tuple[0], + date_tuple[1], + date_tuple[2]) + else: + ret = datetime.datetime( + date_tuple[0], + date_tuple[1], + date_tuple[2], + date_tuple[3], + date_tuple[4], + date_tuple[5] + ) + return ret + + _xls_reader_registry = { "file_type": "xls", "reader": XLSBook, diff --git a/tests/base.py b/tests/base.py index b12e825..855ec96 100644 --- a/tests/base.py +++ b/tests/base.py @@ -107,7 +107,7 @@ class PyexcelMultipleSheetBase: for s in b: data = pyexcel.utils.to_array(s) assert self.content[s.name] == data - si = pyexcel.iterators.SheetIterator(b) + si = pyexcel.sheets.iterators.SheetIterator(b) for s in si: data = pyexcel.utils.to_array(s) assert self.content[s.name] == data diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 2268ee8..3b8752a 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -52,5 +52,5 @@ class TestBugFix: for e in row: yield e for i in range(2): - yield custom_row_renderer([1,2]) + yield custom_row_renderer([1, 2]) save_data("test.xls", {"sheet": data_gen()}) From ae18771b036f9077e514b97003ec0536994ae17a Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 20 Sep 2016 20:25:22 +0100 Subject: [PATCH 003/163] update test case --- tests/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/base.py b/tests/base.py index 855ec96..b12e825 100644 --- a/tests/base.py +++ b/tests/base.py @@ -107,7 +107,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 8eda6c227feb893b5f059ee8f883b7419e45689a Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 20 Sep 2016 20:35:40 +0100 Subject: [PATCH 004/163] release 0.2.3 --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 872148f..11abc01 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.2.3 - unreleased +0.2.3 - 20.09.2016 -------------------------------------------------------------------------------- Updated From d897adab0513a97d970a9c17521a4dda19c3b508 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 24 Oct 2016 21:58:37 +0100 Subject: [PATCH 005/163] test against pyexcel v0.3.0 --- docs/source/conf.py | 4 +- pyexcel_xls.yaml | 4 +- setup.py | 2 +- test.bat | 2 +- test.sh | 2 +- tests/base.py | 51 +++---------------- ...iple_sheets.py => test_multiple_sheets.py} | 26 +++++----- tests/test_stringio.py | 4 +- 8 files changed, 30 insertions(+), 65 deletions(-) rename tests/{test_mutliple_sheets.py => test_multiple_sheets.py} (92%) diff --git a/docs/source/conf.py b/docs/source/conf.py index cd49c48..032eb2d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,8 +16,8 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2016 Onni Software Ltd.' -version = '0.2.2' -release = '0.2.3' +version = '0.2.3' +release = '0.2.4' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index f9b9b3a..d3aec39 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.2.3 -release: 0.2.2 +version: 0.2.4 +release: 0.2.3 file_type: xls dependencies: - pyexcel-io>=0.2.2 diff --git a/setup.py b/setup.py index fa0ca9f..f8d82da 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.2.3' +VERSION = '0.2.4' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( diff --git a/test.bat b/test.bat index 45ba0f8..4f7c289 100644 --- a/test.bat +++ b/test.bat @@ -1,4 +1,4 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index 45ba0f8..4f7c289 100644 --- a/test.sh +++ b/test.sh @@ -1,4 +1,4 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/tests/base.py b/tests/base.py index b12e825..6d0879f 100644 --- a/tests/base.py +++ b/tests/base.py @@ -8,7 +8,7 @@ def create_sample_file1(file): table.append(data[:4]) table.append(data[4:8]) table.append(data[8:12]) - pyexcel.save_as(dest_file_name=file, array=table) + pyexcel.save_as(array=table, dest_file_name=file) class PyexcelHatWriterBase: @@ -24,8 +24,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: @@ -48,29 +47,14 @@ 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()) - assert actual == self.content - - def test_write_reader(self): - """ - Use reader as data container - - this test case shows the file written by pyexcel - can be read back by itself - """ - self._create_a_file(self.testfile) - r = pyexcel.Reader(self.testfile) - r.save_as(self.testfile2) - r2 = pyexcel.Reader(self.testfile2) - r2.format(int) - actual = pyexcel.utils.to_array(r2.rows()) + actual = list(r.rows()) assert actual == self.content class PyexcelMultipleSheetBase: def _write_test_file(self, filename): - pyexcel.save_book_as(dest_file_name=filename, bookdict=self.content) + pyexcel.save_book_as(bookdict=self.content, dest_file_name=filename) def _clean_up(self): if os.path.exists(self.testfile2): @@ -87,36 +71,17 @@ 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 diff --git a/tests/test_mutliple_sheets.py b/tests/test_multiple_sheets.py similarity index 92% rename from tests/test_mutliple_sheets.py rename to tests/test_multiple_sheets.py index 7a5abce..d20dc61 100644 --- a/tests/test_mutliple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -92,10 +92,10 @@ class TestAddBooks: """ test this scenario: book3 = book1 + book2 """ - b1 = pyexcel.BookReader(self.testfile) - b2 = pyexcel.BookReader(self.testfile2) + 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: @@ -108,12 +108,12 @@ class TestAddBooks: def test_add_book1_in_place(self): """ - test this scenario book1 += book2 + test this scenario: book1 += book2 """ 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: @@ -126,12 +126,12 @@ class TestAddBooks: def test_add_book2(self): """ - test this scenario book3 = book1 + sheet3 + test this scenario: book3 = book1 + sheet3 """ 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: @@ -144,12 +144,12 @@ class TestAddBooks: def test_add_book2_in_place(self): """ - test this scenario book3 = book1 + sheet3 + test this scenario: book3 = book1 + sheet3 """ 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: @@ -162,12 +162,12 @@ class TestAddBooks: def test_add_book3(self): """ - test this scenario book3 = sheet1 + sheet2 + test this scenario: book3 = sheet1 + sheet2 """ 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"] @@ -175,12 +175,12 @@ class TestAddBooks: def test_add_book4(self): """ - test this scenario book3 = sheet1 + book + test this scenario: book3 = sheet1 + book """ 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 0d8c4fe..3cba260 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -12,7 +12,7 @@ class TestStringIO: content = f.read() r = pyexcel.get_sheet(file_type="xls", 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()) assert result == actual if os.path.exists(xlsfile): os.unlink(xlsfile) @@ -26,5 +26,5 @@ class TestStringIO: array=data) r = pyexcel.get_sheet(file_type="xls", file_content=io.getvalue()) result = [1, 2, 3, 4, 5, 6] - actual = pyexcel.utils.to_array(r.enumerate()) + actual = list(r.enumerate()) assert result == actual From 53b58e329ee485d193722c27d3450ed911a06ea8 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 24 Oct 2016 22:09:42 +0100 Subject: [PATCH 006/163] use pyexcel v0.3.0 --- rnd_requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 30a50e9..2ce1c92 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1 +1,2 @@ -https://github.com/pyexcel/pyexcel-io/archive/master.zip +https://github.com/pyexcel/pyexcel/archive/master.zip + From 9427b2ab3b21e2341a1ef5a5b7fdf7af1226253c Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Nov 2016 00:21:06 +0000 Subject: [PATCH 007/163] code refactoring: label private, protected or public for class attributes --- docs/source/conf.py | 2 +- pyexcel_xls.yaml | 2 +- pyexcel_xls/xls.py | 56 ++++++++++++++++++++++----------------------- setup.py | 2 +- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 032eb2d..21e45cb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -17,7 +17,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2016 Onni Software Ltd.' version = '0.2.3' -release = '0.2.4' +release = '0.3.0' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index d3aec39..0c5c89b 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,7 +1,7 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.2.4 +version: 0.3.0 release: 0.2.3 file_type: xls dependencies: diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 845e8dc..6289842 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -40,26 +40,26 @@ class XLSheet(SheetReader): @property def name(self): - return self.native_sheet.name + return self._native_sheet.name def number_of_rows(self): """ Number of rows in the xls sheet """ - return self.native_sheet.nrows + return self._native_sheet.nrows def number_of_columns(self): """ Number of columns in the xls sheet """ - return self.native_sheet.ncols + return self._native_sheet.ncols def _cell_value(self, row, column): """ Random access to the xls cells """ - cell_type = self.native_sheet.cell_type(row, column) - value = self.native_sheet.cell_value(row, column) + cell_type = self._native_sheet.cell_type(row, column) + value = self._native_sheet.cell_value(row, column) if cell_type == xlrd.XL_CELL_DATE: value = xldate_to_python_date(value) elif cell_type == xlrd.XL_CELL_NUMBER and self.auto_detect_int: @@ -76,7 +76,7 @@ class XLSBook(BookReader): """ def __init__(self): BookReader.__init__(self) - self.file_content = None + self._file_content = None def open(self, file_name, **keywords): BookReader.open(self, file_name, **keywords) @@ -87,31 +87,31 @@ class XLSBook(BookReader): self._get_params() def open_content(self, file_content, **keywords): - self.keywords = keywords - self.file_content = file_content + self._keywords = keywords + self._file_content = file_content self._get_params() def close(self): - if self.native_book: - self.native_book.release_resources() + if self._native_book: + self._native_book.release_resources() def read_sheet_by_index(self, sheet_index): - self.native_book = self._get_book(on_demand=True) - sheet = self.native_book.sheet_by_index(sheet_index) + self._native_book = self._get_book(on_demand=True) + sheet = self._native_book.sheet_by_index(sheet_index) return self.read_sheet(sheet) def read_sheet_by_name(self, sheet_name): - self.native_book = self._get_book(on_demand=True) + self._native_book = self._get_book(on_demand=True) try: - sheet = self.native_book.sheet_by_name(sheet_name) + sheet = self._native_book.sheet_by_name(sheet_name) except xlrd.XLRDError: raise ValueError("%s cannot be found" % sheet_name) return self.read_sheet(sheet) def read_all(self): result = OrderedDict() - self.native_book = self._get_book() - for sheet in self.native_book.sheets(): + self._native_book = self._get_book() + for sheet in self._native_book.sheets(): if self.skip_hidden_sheets and sheet.visibility != 0: continue data_dict = self.read_sheet(sheet) @@ -119,28 +119,28 @@ class XLSBook(BookReader): return result def read_sheet(self, native_sheet): - sheet = XLSheet(native_sheet, **self.keywords) + sheet = XLSheet(native_sheet, **self._keywords) return {sheet.name: sheet.to_array()} def _get_book(self, on_demand=False): - if self.file_name: - xls_book = xlrd.open_workbook(self.file_name, on_demand=on_demand) - elif self.file_stream: + if self._file_name: + xls_book = xlrd.open_workbook(self._file_name, on_demand=on_demand) + elif self._file_stream: xls_book = xlrd.open_workbook( None, - file_contents=self.file_stream.getvalue(), + file_contents=self._file_stream.getvalue(), on_demand=on_demand ) - elif self.file_content: + elif self._file_content: xls_book = xlrd.open_workbook( None, - file_contents=self.file_content, + file_contents=self._file_content, on_demand=on_demand ) return xls_book def _get_params(self): - self.skip_hidden_sheets = self.keywords.get('skip_hidden_sheets', True) + self.skip_hidden_sheets = self._keywords.get('skip_hidden_sheets', True) class XLSheetWriter(SheetWriter): @@ -150,7 +150,7 @@ class XLSheetWriter(SheetWriter): def set_sheet_name(self, name): """Create a sheet """ - self.native_sheet = self.native_book.add_sheet(name) + self._native_sheet = self._native_book.add_sheet(name) self.current_row = 0 def write_row(self, array): @@ -179,9 +179,9 @@ class XLSheetWriter(SheetWriter): style = XFStyle() style.num_format_str = DEFAULT_TIME_FORMAT if style: - self.native_sheet.write(self.current_row, i, value, style) + self._native_sheet.write(self.current_row, i, value, style) else: - self.native_sheet.write(self.current_row, i, value) + self._native_sheet.write(self.current_row, i, value) self.current_row += 1 @@ -206,7 +206,7 @@ class XLSWriter(BookWriter): """ This call actually save the file """ - self.work_book.save(self.file_alike_object) + self.work_book.save(self._file_alike_object) def is_integer_ok_for_xl_float(value): diff --git a/setup.py b/setup.py index f8d82da..fa8bccc 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.2.4' +VERSION = '0.3.0' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( From 2bcf8c260b4f0ee7b890eb11ec510368a4af9dcc Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Nov 2016 09:01:19 +0000 Subject: [PATCH 008/163] use io3 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 2ce1c92..9457a41 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/archive/io3.zip From a8348b4a68c80bc5d3fa3218a5580b73efaa8641 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Nov 2016 09:18:06 +0000 Subject: [PATCH 009/163] use rnd pyexcel-io too --- rnd_requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 9457a41..7a4c8f0 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,2 +1,3 @@ https://github.com/pyexcel/pyexcel/archive/io3.zip +https://github.com/pyexcel/pyexcel-io/archive/master.zip From 2f876aa91cae58be289e6efe667d81e1777fa730 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Nov 2016 09:31:26 +0000 Subject: [PATCH 010/163] fix a long line --- pyexcel_xls/xls.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 6289842..9bfbb93 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -140,7 +140,8 @@ class XLSBook(BookReader): return xls_book def _get_params(self): - self.skip_hidden_sheets = self._keywords.get('skip_hidden_sheets', True) + self.skip_hidden_sheets = self._keywords.get( + 'skip_hidden_sheets', True) class XLSheetWriter(SheetWriter): From 6c1a62725bebd92e91c312963c5bd62e32513feb Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 1 Dec 2016 23:48:29 +0000 Subject: [PATCH 011/163] remove pypy3 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e2a876e..8ec4420 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ python: - pypy - 2.6 - 2.7 - - pypy3 - 3.3 - 3.4 - 3.5 From 93d6b7016a5ed3fd0f7e6c44babba77dca310320 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 6 Dec 2016 09:28:17 +0000 Subject: [PATCH 012/163] describe the library using meta for lazy loading --- pyexcel_xls/__init__.py | 12 ++++++++---- pyexcel_xls/xls.py | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index 75d7a76..e89770f 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -10,8 +10,12 @@ # flake8: noqa # this line has to be place above all else # because of dynamic import -_FILE_TYPE = 'xls' -__pyexcel_io_plugins__ = [_FILE_TYPE] +__FILE_TYPE__ = 'xls' +__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 @@ -20,12 +24,12 @@ from pyexcel_io.io import get_data as read_data, isstream, store_data as write_d 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) 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) diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 9bfbb93..c5e761a 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -36,7 +36,7 @@ class XLSheet(SheetReader): """ def __init__(self, sheet, auto_detect_int=True, **keywords): SheetReader.__init__(self, sheet, **keywords) - self.auto_detect_int = auto_detect_int + self.__auto_detect_int = auto_detect_int @property def name(self): @@ -62,7 +62,7 @@ class XLSheet(SheetReader): value = self._native_sheet.cell_value(row, column) if cell_type == xlrd.XL_CELL_DATE: value = xldate_to_python_date(value) - elif cell_type == xlrd.XL_CELL_NUMBER and self.auto_detect_int: + elif cell_type == xlrd.XL_CELL_NUMBER and self.__auto_detect_int: if is_integer_ok_for_xl_float(value): value = int(value) return value From 6730166fddda97eb133771b09748fa53a89609e0 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 6 Dec 2016 14:08:38 +0000 Subject: [PATCH 013/163] 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 7a4c8f0..3fcc9af 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 From 3836c432a71dfaa53520899c849abd958035f461 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 12 Dec 2016 17:45:03 +0000 Subject: [PATCH 014/163] fix #13: raise exception when no file name or content found --- CHANGELOG.rst | 9 +++++++++ pyexcel_xls/xls.py | 4 +++- tests/test_bug_fixes.py | 6 +++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 11abc01..437310a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.3.0 - unreleased +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#13 `_, alert on empyty + file content + 0.2.3 - 20.09.2016 -------------------------------------------------------------------------------- diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index c5e761a..0625eef 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -131,12 +131,14 @@ class XLSBook(BookReader): file_contents=self._file_stream.getvalue(), on_demand=on_demand ) - elif self._file_content: + elif self._file_content is not None: xls_book = xlrd.open_workbook( None, file_contents=self._file_content, on_demand=on_demand ) + else: + raise IOError("No valid file name or file content found.") return xls_book def _get_params(self): diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 3b8752a..f4f79ab 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -8,7 +8,7 @@ import os import pyexcel as pe from pyexcel_xls import save_data from _compact import OrderedDict -from nose.tools import eq_ +from nose.tools import eq_, raises import datetime @@ -54,3 +54,7 @@ class TestBugFix: for i in range(2): yield custom_row_renderer([1, 2]) save_data("test.xls", {"sheet": data_gen()}) + + @raises(IOError) + def test_issue_13_empty_file_content(self): + pe.get_sheet(file_content='', file_type='xls') From 562691db039faeadcec99159e7782aad937559c5 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 13 Dec 2016 23:09:49 +0000 Subject: [PATCH 015/163] soft-register xlsx and xlsm --- pyexcel_xls/__init__.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index e89770f..eb97b98 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -11,11 +11,23 @@ # this line has to be place above all else # because of dynamic import __FILE_TYPE__ = 'xls' -__META__ = { +__XLS_META__ = { 'file_type': __FILE_TYPE__, 'stream_type': 'binary' } -__pyexcel_io_plugins__ = [__META__] +__XLSX_META__ = { + 'file_type': 'xlsx', + 'stream_type': 'binary' +} +__XLSM_META__ = { + 'file_type': 'xlsm', + 'stream_type': 'binary' +} +__pyexcel_io_plugins__ = [ + __XLS_META__, + __XLSX_META__, + __XLSM_META__ +] from pyexcel_io.io import get_data as read_data, isstream, store_data as write_data From 81bfe0724f9262c15d8b4582bc6e9c8399e4eec6 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 14 Dec 2016 16:44:35 +0000 Subject: [PATCH 016/163] support sheltered file types, such as xlsx under pyexcel-xls --- pyexcel_xls/__init__.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index eb97b98..23fa653 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -11,23 +11,12 @@ # this line has to be place above all else # because of dynamic import __FILE_TYPE__ = 'xls' -__XLS_META__ = { +__META__ = { 'file_type': __FILE_TYPE__, + 'other_types': ['xlsx', 'xlsm'], 'stream_type': 'binary' } -__XLSX_META__ = { - 'file_type': 'xlsx', - 'stream_type': 'binary' -} -__XLSM_META__ = { - 'file_type': 'xlsm', - 'stream_type': 'binary' -} -__pyexcel_io_plugins__ = [ - __XLS_META__, - __XLSX_META__, - __XLSM_META__ -] +__pyexcel_io_plugins__ = [__META__] from pyexcel_io.io import get_data as read_data, isstream, store_data as write_data From 73e6979f04783c6607af97519398576825aabce4 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 14 Dec 2016 22:11:45 +0000 Subject: [PATCH 017/163] adjust lazy loading behavior --- pyexcel_xls/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index 23fa653..d235645 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -12,8 +12,8 @@ # because of dynamic import __FILE_TYPE__ = 'xls' __META__ = { - 'file_type': __FILE_TYPE__, - 'other_types': ['xlsx', 'xlsm'], + 'submodule': __FILE_TYPE__, + 'file_types': [__FILE_TYPE__, 'xlsx', 'xlsm'], 'stream_type': 'binary' } __pyexcel_io_plugins__ = [__META__] From 75cbd2e11e87a301f2bebed0a1744da4f71ef0e6 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 21 Dec 2016 23:58:09 +0000 Subject: [PATCH 018/163] update function name --- pyexcel_xls/xls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 0625eef..98f2b6f 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -54,7 +54,7 @@ class XLSheet(SheetReader): """ return self._native_sheet.ncols - def _cell_value(self, row, column): + def cell_value(self, row, column): """ Random access to the xls cells """ From 0970757403f20030a94c7a6d8298f787246998db Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 22 Dec 2016 10:27:12 +0000 Subject: [PATCH 019/163] update changelog --- CHANGELOG.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 437310a..a538a7e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.3.0 - unreleased +0.3.0 - 22.12.2016 -------------------------------------------------------------------------------- Updated @@ -9,6 +9,7 @@ Updated #. `#13 `_, alert on empyty file content +#. Support pyexcel-io v0.3.0 0.2.3 - 20.09.2016 -------------------------------------------------------------------------------- From 771969ec849447440c96b81761c77d47bcd406cb Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 16 Jan 2017 13:08:34 +0000 Subject: [PATCH 020/163] update dependencies --- docs/source/conf.py | 4 ++-- pyexcel_xls.yaml | 9 ++++----- pyexcel_xls/__init__.py | 2 +- pyexcel_xls/xls.py | 2 +- requirements.txt | 5 ++--- setup.py | 9 +++------ 6 files changed, 13 insertions(+), 18 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 21e45cb..6caa748 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,8 +16,8 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2016 Onni Software Ltd.' -version = '0.2.3' -release = '0.3.0' +version = '0.3.0' +release = '0.3.1' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index 0c5c89b..ce37cb2 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,12 +1,11 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.3.0 -release: 0.2.3 +version: 0.3.1 +release: 0.3.0 file_type: xls dependencies: - - pyexcel-io>=0.2.2 + - pyexcel-io>=0.3.0 - xlrd - - xlwt;python_version<"3" - - xlwt-future;python_version>="3" + - xlwt description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index d235645..ad9eb7c 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -4,7 +4,7 @@ The lower level xls/xlsx/xlsm file format handler using xlrd/xlwt - :copyright: (c) 2015-2016 by Onni Software Ltd + :copyright: (c) 2016-2017 by Onni Software Ltd :license: New BSD License """ # flake8: noqa diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 98f2b6f..6b8e926 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -4,7 +4,7 @@ The lower level xls/xlsm file format handler using xlrd/xlwt - :copyright: (c) 2015-2016 by Onni Software Ltd + :copyright: (c) 2016-2017 by Onni Software Ltd :license: New BSD License """ import sys diff --git a/requirements.txt b/requirements.txt index efb555b..2f413dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -pyexcel-io>=0.2.2 +pyexcel-io>=0.3.0 xlrd -xlwt;python_version<"3" -xlwt-future;python_version>="3" +xlwt diff --git a/setup.py b/setup.py index fa8bccc..14db673 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.3.0' +VERSION = '0.3.1' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -44,14 +44,11 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.2.2', + 'pyexcel-io>=0.3.0', 'xlrd', + 'xlwt', ] -if PY2: - INSTALL_REQUIRES.append('xlwt') -if not PY2: - INSTALL_REQUIRES.append('xlwt-future') PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) EXTRAS_REQUIRE = { From 0dae19aa1fccd6402cfd5f5283d6c2c699b569e7 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 16 Jan 2017 13:14:34 +0000 Subject: [PATCH 021/163] test again python 3.6 --- .moban.d/travis.yml | 1 + .travis.yml | 1 + LICENSE | 2 +- docs/source/conf.py | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.moban.d/travis.yml b/.moban.d/travis.yml index 9839e3c..e6ce23b 100644 --- a/.moban.d/travis.yml +++ b/.moban.d/travis.yml @@ -4,6 +4,7 @@ - 3.4 - 3.5 - pypy + - 3.6 {%endblock%} {%block extra_matrix%} diff --git a/.travis.yml b/.travis.yml index 8ec4420..b6f6aff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ python: - 3.3 - 3.4 - 3.5 + - 3.6 matrix: include: - python: 2.7 diff --git a/LICENSE b/LICENSE index f5d9673..4066e82 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/docs/source/conf.py b/docs/source/conf.py index 6caa748..1f9f590 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -15,7 +15,7 @@ source_suffix = '.rst' master_doc = 'index' project = u'pyexcel-xls' -copyright = u'2015-2016 Onni Software Ltd.' +copyright = u'2015-2017 Onni Software Ltd.' version = '0.3.0' release = '0.3.1' exclude_patterns = [] From 73051b6a450cfc528b624e0af629d40c79080a20 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 16 Jan 2017 22:28:32 +0000 Subject: [PATCH 022/163] fix #14 in v0.3.1 --- CHANGELOG.rst | 10 ++++++++++ README.rst | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a538a7e..f58b956 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,16 @@ Change log ================================================================================ +0.3.1 - 16.01.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#14 `_, Python 3.6 - + cannot use LOCALE flag with a str pattern +#. fix its dependency on pyexcel-io 0.3.0 + 0.3.0 - 22.12.2016 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index 18bafa7..5706a1e 100644 --- a/README.rst +++ b/README.rst @@ -293,7 +293,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 From 0dfe727630f7b6aef5aaf4314c26ef61a6324d7b Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Feb 2017 23:38:52 +0000 Subject: [PATCH 023/163] common tests are mobanized --- .moban.d/setup.py | 6 ------ .moban.d/tests/base.py | 4 ++++ .moban.yml | 5 +++++ .travis.yml | 12 ++++++------ README.rst | 24 ++++++++++-------------- setup.py | 2 +- tests/base.py | 6 ++++-- tests/test_formatters.py | 3 ++- tests/test_stringio.py | 15 ++++++++------- tests/test_writer.py | 14 +++++++------- 10 files changed, 47 insertions(+), 44 deletions(-) create mode 100644 .moban.d/tests/base.py diff --git a/.moban.d/setup.py b/.moban.d/setup.py index fce0619..8fc8de0 100644 --- a/.moban.d/setup.py +++ b/.moban.d/setup.py @@ -10,11 +10,5 @@ {%endblock%} {%block additional_classifiers%} - 'Development Status :: 3 - Alpha', - '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 :: Implementation :: PyPy' {%endblock%} diff --git a/.moban.d/tests/base.py b/.moban.d/tests/base.py new file mode 100644 index 0000000..b7510db --- /dev/null +++ b/.moban.d/tests/base.py @@ -0,0 +1,4 @@ +{% extends 'tests/base.py.jj2' %} + +{%block ods_types%} +{%endblock%} \ No newline at end of file diff --git a/.moban.yml b/.moban.yml index a88db65..5855bb6 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.jj2" + - "tests/test_stringio.py": "tests/test_stringio.py.jj2" + - "tests/test_writer.py": "tests/test_writer.py.jj2" + - "tests/base.py": "tests/base.py" diff --git a/.travis.yml b/.travis.yml index b6f6aff..825e7d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,13 +3,13 @@ language: python notifications: email: false python: - - pypy - - 2.6 - - 2.7 - - 3.3 - - 3.4 - - 3.5 - 3.6 + - 3.5 + - 3.4 + - 3.3 + - 2.7 + - 2.6 + - pypy matrix: include: - python: 2.7 diff --git a/README.rst b/README.rst index 5706a1e..bc7cc00 100644 --- a/README.rst +++ b/README.rst @@ -39,9 +39,6 @@ Usage As a standalone library -------------------------------------------------------------------------------- -Write to an xls file -******************************************************************************** - .. testcode:: :hide: @@ -58,6 +55,11 @@ Write to an xls file ... from collections import OrderedDict +Write to an xls file +******************************************************************************** + + + Here's the sample code to write a dictionary to an xls file: .. code-block:: python @@ -68,6 +70,7 @@ Here's the sample code to write a dictionary to an xls file: >>> data.update({"Sheet 2": [["row 1", "row 2", "row 3"]]}) >>> save_data("your_file.xls", data) + Read from an xls file ******************************************************************************** @@ -101,6 +104,7 @@ Here's the sample code to write a dictionary to an xls file: + Read from an xls from memory ******************************************************************************** @@ -119,6 +123,8 @@ Continue from previous example: Pagination feature ******************************************************************************** + + Let's assume the following file is a huge xls file: .. code-block:: python @@ -175,16 +181,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 xls 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 xls - -Please note only pyexcel version 0.0.4+ support this. - Reading from an xls file ******************************************************************************** @@ -194,7 +190,6 @@ Here is the sample code: .. code-block:: python >>> import pyexcel as pe - >>> # from pyexcel.ext import xls >>> sheet = pe.get_book(file_name="your_file.xls") >>> sheet Sheet 1: @@ -265,6 +260,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 14db673..9cc7468 100644 --- a/setup.py +++ b/setup.py @@ -34,12 +34,12 @@ CLASSIFIERS = [ 'Programming Language :: Python', 'License :: OSI Approved :: BSD License', 'Intended Audience :: Developers', - 'Development Status :: 3 - Alpha', '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 :: Implementation :: PyPy' ] diff --git a/tests/base.py b/tests/base.py index 6d0879f..625eb00 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,5 +1,7 @@ -import os +import os # noqa import pyexcel +import datetime # noqa +from nose.tools import raises, eq_ # noqa def create_sample_file1(file): @@ -24,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_formatters.py b/tests/test_formatters.py index f18fd3a..29389cb 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -1,5 +1,4 @@ import os -import datetime from unittest import TestCase from textwrap import dedent @@ -15,6 +14,7 @@ class TestDateFormat: 01/01/15 13:13:13 0.0 0.0 """ + import datetime r = pe.get_sheet(file_name=os.path.join("tests", "fixtures", "date_field.xls")) assert isinstance(r[1, 0], datetime.date) is True @@ -25,6 +25,7 @@ class TestDateFormat: assert r[4, 1].strftime("%H:%M:%S") == "00:00:00" def test_writing_date_format(self): + import datetime excel_filename = "testdateformat.xls" data = [[datetime.date(2014, 12, 25), datetime.time(11, 11, 11), diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 3cba260..11d532a 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -1,21 +1,22 @@ import os import pyexcel +from nose.tools import eq_ from base import create_sample_file1 class TestStringIO: def test_xls_stringio(self): - xlsfile = "cute.xls" - create_sample_file1(xlsfile) - with open(xlsfile, "rb") as f: + testfile = "cute.xls" + create_sample_file1(testfile) + with open(testfile, "rb") as f: content = f.read() r = pyexcel.get_sheet(file_type="xls", file_content=content) result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] actual = list(r.enumerate()) - assert result == actual - if os.path.exists(xlsfile): - os.unlink(xlsfile) + eq_(result, actual) + if os.path.exists(testfile): + os.unlink(testfile) def test_xls_output_stringio(self): data = [ @@ -27,4 +28,4 @@ class TestStringIO: r = pyexcel.get_sheet(file_type="xls", file_content=io.getvalue()) result = [1, 2, 3, 4, 5, 6] actual = list(r.enumerate()) - assert result == actual + eq_(result, actual) diff --git a/tests/test_writer.py b/tests/test_writer.py index 561d420..80d34f1 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,21 +1,21 @@ import os -from pyexcel_xls.xls import XLSWriter, XLSBook +from pyexcel_xls.xls import XLSWriter as Writer, XLSBook as Reader from base import PyexcelWriterBase, PyexcelHatWriterBase -class TestNativeXLWriter: +class TestNativeXLSWriter: def test_write_book(self): 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]] } - self.testfile = "xlwriter.xls" - writer = XLSWriter() + self.testfile = "writer.xls" + writer = Writer() writer.open(self.testfile) writer.write(self.content) writer.close() - reader = XLSBook() + reader = Reader() reader.open(self.testfile) content = reader.read_all() reader.close() @@ -28,7 +28,7 @@ class TestNativeXLWriter: os.unlink(self.testfile) -class TestXLSnCSVWriter(PyexcelWriterBase): +class TestxlsnCSVWriter(PyexcelWriterBase): def setUp(self): self.testfile = "test.xls" self.testfile2 = "test.csv" @@ -40,7 +40,7 @@ class TestXLSnCSVWriter(PyexcelWriterBase): os.unlink(self.testfile2) -class TestXLSHatWriter(PyexcelHatWriterBase): +class TestxlsHatWriter(PyexcelHatWriterBase): def setUp(self): self.testfile = "test.xls" From b04c4c434b4571f0db0bf682361e4853475e98e7 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 31 Mar 2017 16:08:22 +0100 Subject: [PATCH 024/163] sync with commons --- README.rst | 6 +++--- docs/source/conf.py | 17 +++++++++++++---- test.bat | 4 +--- test.sh | 4 +--- tests/base.py | 6 +++--- tests/test_formatters.py | 5 +++-- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/README.rst b/README.rst index bc7cc00..1ee7c96 100644 --- a/README.rst +++ b/README.rst @@ -276,7 +276,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: @@ -285,7 +285,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 @@ -314,7 +314,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 1f9f590..a4d7158 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,4 +1,9 @@ # -*- coding: utf-8 -*- +DESCRIPTION = ( + 'A wrapper library to read, manipulate and write data in xls format. It' + + ' reads xlsx and xlsm format' + + '' +) extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', @@ -25,15 +30,19 @@ html_static_path = ['_static'] htmlhelp_basename = 'pyexcel-xlsdoc' latex_elements = {} latex_documents = [ - ('index', 'pyexcel-xls.tex', u'pyexcel-xls Documentation', + ('index', 'pyexcel-xls.tex', + 'pyexcel-xls Documentation', 'Onni Software Ltd.', 'manual'), ] man_pages = [ - ('index', 'pyexcel-xls', u'pyexcel-xls Documentation', + ('index', 'pyexcel-xls', + 'pyexcel-xls Documentation', [u'Onni Software Ltd.'], 1) ] texinfo_documents = [ - ('index', 'pyexcel-xls', u'pyexcel-xls Documentation', - 'Onni Software Ltd.', 'pyexcel-xls', 'One line description of project.', + ('index', 'pyexcel-xls', + 'pyexcel-xls Documentation', + 'Onni Software Ltd.', 'pyexcel-xls', + DESCRIPTION, 'Miscellaneous'), ] diff --git a/test.bat b/test.bat index 4f7c289..fd8fdd3 100644 --- a/test.bat +++ b/test.bat @@ -1,4 +1,2 @@ - - pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index 4f7c289..fd8fdd3 100644 --- a/test.sh +++ b/test.sh @@ -1,4 +1,2 @@ - - pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst tests README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/tests/base.py b/tests/base.py index 625eb00..4339f70 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,7 +1,7 @@ -import os # noqa +import os # noqa import pyexcel -import datetime # noqa -from nose.tools import raises, eq_ # noqa +import datetime # noqa +from nose.tools import raises, eq_ # noqa def create_sample_file1(file): diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 29389cb..109c2f8 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -16,7 +16,8 @@ class TestDateFormat: """ import datetime r = pe.get_sheet(file_name=os.path.join("tests", "fixtures", - "date_field.xls")) + "date_field.xls"), + library='pyexcel-xls') assert isinstance(r[1, 0], datetime.date) is True assert r[1, 0].strftime("%d/%m/%y") == "25/12/14" assert isinstance(r[1, 1], datetime.time) is True @@ -31,7 +32,7 @@ class TestDateFormat: datetime.time(11, 11, 11), datetime.datetime(2014, 12, 25, 11, 11, 11)]] pe.save_as(dest_file_name=excel_filename, array=data) - r = pe.get_sheet(file_name=excel_filename) + r = pe.get_sheet(file_name=excel_filename, library='pyexcel-xls') assert isinstance(r[0, 0], datetime.date) is True assert r[0, 0].strftime("%d/%m/%y") == "25/12/14" assert isinstance(r[0, 1], datetime.time) is True From 47c65e5cb34f60054681e08c2cf713f056a4d909 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 6 Apr 2017 23:02:35 +0100 Subject: [PATCH 025/163] update plugin protocol --- pyexcel_xls/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index ad9eb7c..8f09d8b 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -12,6 +12,7 @@ # because of dynamic import __FILE_TYPE__ = 'xls' __META__ = { + 'plugin_type': 'pyexcel io plugin', 'submodule': __FILE_TYPE__, 'file_types': [__FILE_TYPE__, 'xlsx', 'xlsm'], 'stream_type': 'binary' From c6cce59f1026fbd160a78fbc63e66a97bc4cb036 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 6 Apr 2017 23:16:48 +0100 Subject: [PATCH 026/163] use rnd branch for testing --- rnd_requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 3fcc9af..971c3d8 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-io/archive/v0.4.x.zip From ce89ef555370a18f45435a316c8f882e932bfc32 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 11 Apr 2017 07:05:51 +0100 Subject: [PATCH 027/163] simplify plugin interace. aligned it with pyexcel. both uses meta_class pump up version minor --- docs/source/conf.py | 4 ++-- pyexcel_xls.yaml | 4 ++-- pyexcel_xls/xls.py | 42 ++++++++---------------------------------- setup.py | 2 +- 4 files changed, 13 insertions(+), 39 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index a4d7158..1a9c890 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,8 +21,8 @@ master_doc = 'index' project = u'pyexcel-xls' 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' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index ce37cb2..8107046 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.3.1 -release: 0.3.0 +version: 0.4.0 +release: 0.3.1 file_type: xls dependencies: - pyexcel-io>=0.3.0 diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 6b8e926..ffe6e0d 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -74,6 +74,10 @@ class XLSBook(BookReader): It reads xls, xlsm, xlsx work book """ + file_types = ['xls', 'xlsm', 'xlsx'] + stream_type = 'binary' + library = 'pyexcel-xls' + def __init__(self): BookReader.__init__(self) self._file_content = None @@ -192,6 +196,10 @@ class XLSWriter(BookWriter): """ xls writer """ + file_types = ['xls'] + stream_type = 'binary' + library = 'pyexcel-xls' + def __init__(self): BookWriter.__init__(self) self.work_book = None @@ -243,37 +251,3 @@ def xldate_to_python_date(value): date_tuple[5] ) return ret - - -_xls_reader_registry = { - "file_type": "xls", - "reader": XLSBook, - "writer": XLSWriter, - "stream_type": "binary", - "mime_type": "application/vnd.ms-excel", - "library": "pyexcel-xls" -} - -_XLSM_MIME = ( - "application/" + - "vnd.openxmlformats-officedocument.spreadsheetml.sheet") - -_xlsm_registry = { - "file_type": "xlsm", - "reader": XLSBook, - "stream_type": "binary", - "mime_type": _XLSM_MIME, - "library": "pyexcel-xls" -} - -_xlsx_registry = { - "file_type": "xlsx", - "reader": XLSBook, - "stream_type": "binary", - "mime_type": "application/vnd.ms-excel.sheet.macroenabled.12", - "library": "pyexcel-xls" -} - -exports = (_xls_reader_registry, - _xlsm_registry, - _xlsx_registry) diff --git a/setup.py b/setup.py index 9cc7468..e4a9fa0 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.3.1' +VERSION = '0.4.0' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( From ca8db4a748dedcaf98d3b783807fccb58de378bb Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 13 Apr 2017 22:09:56 +0100 Subject: [PATCH 028/163] launch patreon support channel --- README.rst | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 1ee7c96..6e30f35 100644 --- a/README.rst +++ b/README.rst @@ -2,11 +2,17 @@ pyexcel-xls - Let you focus on data, instead of xls format ================================================================================ -.. image:: https://api.travis-ci.org/pyexcel/pyexcel-xls.png - :target: http://travis-ci.org/pyexcel/pyexcel-xls +.. 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-xls.svg?branch=master + :target: http://travis-ci.org/pyexcel/pyexcel-xls .. image:: https://codecov.io/github/pyexcel/pyexcel-xls/coverage.png - :target: https://codecov.io/github/pyexcel/pyexcel-xls + :target: https://codecov.io/github/pyexcel/pyexcel-xls + +.. image:: https://readthedocs.org/projects/pyexcel-xls/badge/?version=latest + :target: http://pyexcel-xls.readthedocs.org/en/latest/ **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. @@ -332,3 +338,9 @@ Known Issues >>> import os >>> os.unlink("your_file.xls") >>> os.unlink("another_file.xls") + +Support the project +================================================================================ + +If your company has embedded pyexcel and its components into a revenue generating +product, please `support me on patreon `_. From 9dc6d884b4749e48588667d8174375bef90a64b0 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 13 Apr 2017 22:46:06 +0100 Subject: [PATCH 029/163] test against released libraries --- README.rst | 3 ++- rnd_requirements.txt | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 6e30f35..bc9cd8c 100644 --- a/README.rst +++ b/README.rst @@ -343,4 +343,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/rnd_requirements.txt b/rnd_requirements.txt index 3fcc9af..8b13789 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,3 +1 @@ -https://github.com/pyexcel/pyexcel/archive/master.zip -https://github.com/pyexcel/pyexcel-io/archive/master.zip From e045f97b66596fc74abceaf87fddc6a0e9682ac5 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 18 Apr 2017 22:16:25 +0100 Subject: [PATCH 030/163] separation of reader and writer --- pyexcel_xls/__init__.py | 21 +++++--- pyexcel_xls/{xls.py => xlsr.py} | 81 +----------------------------- pyexcel_xls/xlsw.py | 89 +++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 86 deletions(-) rename pyexcel_xls/{xls.py => xlsr.py} (65%) create mode 100644 pyexcel_xls/xlsw.py diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index 8f09d8b..726f5d8 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -11,13 +11,20 @@ # this line has to be place above all else # because of dynamic import __FILE_TYPE__ = 'xls' -__META__ = { - 'plugin_type': 'pyexcel io plugin', - 'submodule': __FILE_TYPE__, - 'file_types': [__FILE_TYPE__, 'xlsx', 'xlsm'], - 'stream_type': 'binary' -} -__pyexcel_io_plugins__ = [__META__] +__pyexcel_io_plugins__ = [ + { + 'plugin_type': 'pyexcel-io reader', + 'submodule': 'xlsr', + 'file_types': [__FILE_TYPE__, 'xlsx', 'xlsm'], + 'stream_type': 'binary' + }, + { + 'plugin_type': 'pyexcel-io writer', + 'submodule': 'xlsw', + 'file_types': [__FILE_TYPE__], + 'stream_type': 'binary' + }, +] from pyexcel_io.io import get_data as read_data, isstream, store_data as write_data diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xlsr.py similarity index 65% rename from pyexcel_xls/xls.py rename to pyexcel_xls/xlsr.py index ffe6e0d..941a0fb 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xlsr.py @@ -11,10 +11,9 @@ import sys import math import datetime import xlrd -from xlwt import Workbook, XFStyle -from pyexcel_io.book import BookReader, BookWriter -from pyexcel_io.sheet import SheetReader, SheetWriter +from pyexcel_io.book import BookReader +from pyexcel_io.sheet import SheetReader PY2 = sys.version_info[0] == 2 if PY2 and sys.version_info[1] < 7: @@ -23,11 +22,6 @@ else: from collections import OrderedDict -DEFAULT_DATE_FORMAT = "DD/MM/YY" -DEFAULT_TIME_FORMAT = "HH:MM:SS" -DEFAULT_DATETIME_FORMAT = "%s %s" % (DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT) - - class XLSheet(SheetReader): """ xls, xlsx, xlsm sheet reader @@ -76,7 +70,6 @@ class XLSBook(BookReader): """ file_types = ['xls', 'xlsm', 'xlsx'] stream_type = 'binary' - library = 'pyexcel-xls' def __init__(self): BookReader.__init__(self) @@ -150,76 +143,6 @@ class XLSBook(BookReader): 'skip_hidden_sheets', True) -class XLSheetWriter(SheetWriter): - """ - xls sheet writer - """ - def set_sheet_name(self, name): - """Create a sheet - """ - self._native_sheet = self._native_book.add_sheet(name) - self.current_row = 0 - - def write_row(self, array): - """ - write a row into the file - """ - for i, value in enumerate(array): - style = None - tmp_array = [] - if isinstance(value, datetime.datetime): - tmp_array = [ - value.year, value.month, value.day, - value.hour, value.minute, value.second - ] - value = xlrd.xldate.xldate_from_datetime_tuple(tmp_array, 0) - style = XFStyle() - style.num_format_str = DEFAULT_DATETIME_FORMAT - elif isinstance(value, datetime.date): - tmp_array = [value.year, value.month, value.day] - value = xlrd.xldate.xldate_from_date_tuple(tmp_array, 0) - style = XFStyle() - style.num_format_str = DEFAULT_DATE_FORMAT - elif isinstance(value, datetime.time): - tmp_array = [value.hour, value.minute, value.second] - value = xlrd.xldate.xldate_from_time_tuple(tmp_array) - style = XFStyle() - style.num_format_str = DEFAULT_TIME_FORMAT - if style: - self._native_sheet.write(self.current_row, i, value, style) - else: - self._native_sheet.write(self.current_row, i, value) - self.current_row += 1 - - -class XLSWriter(BookWriter): - """ - xls writer - """ - file_types = ['xls'] - stream_type = 'binary' - library = 'pyexcel-xls' - - def __init__(self): - BookWriter.__init__(self) - self.work_book = None - - def open(self, file_name, - encoding='ascii', style_compression=2, **keywords): - BookWriter.open(self, file_name, **keywords) - self.work_book = Workbook(style_compression=style_compression, - encoding=encoding) - - def create_sheet(self, name): - return XLSheetWriter(self.work_book, None, name) - - def close(self): - """ - This call actually save the file - """ - self.work_book.save(self._file_alike_object) - - def is_integer_ok_for_xl_float(value): """check if a float value had zero value in digits""" return value == math.floor(value) diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py new file mode 100644 index 0000000..0a48fc6 --- /dev/null +++ b/pyexcel_xls/xlsw.py @@ -0,0 +1,89 @@ +""" + pyexcel_xls + ~~~~~~~~~~~~~~~~~~~ + + The lower level xls/xlsm file format handler using xlrd/xlwt + + :copyright: (c) 2016-2017 by Onni Software Ltd + :license: New BSD License +""" +import datetime +import xlrd +from xlwt import Workbook, XFStyle + +from pyexcel_io.book import BookWriter +from pyexcel_io.sheet import SheetWriter + + +DEFAULT_DATE_FORMAT = "DD/MM/YY" +DEFAULT_TIME_FORMAT = "HH:MM:SS" +DEFAULT_DATETIME_FORMAT = "%s %s" % (DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT) + + +class XLSheetWriter(SheetWriter): + """ + xls sheet writer + """ + def set_sheet_name(self, name): + """Create a sheet + """ + self._native_sheet = self._native_book.add_sheet(name) + self.current_row = 0 + + def write_row(self, array): + """ + write a row into the file + """ + for i, value in enumerate(array): + style = None + tmp_array = [] + if isinstance(value, datetime.datetime): + tmp_array = [ + value.year, value.month, value.day, + value.hour, value.minute, value.second + ] + value = xlrd.xldate.xldate_from_datetime_tuple(tmp_array, 0) + style = XFStyle() + style.num_format_str = DEFAULT_DATETIME_FORMAT + elif isinstance(value, datetime.date): + tmp_array = [value.year, value.month, value.day] + value = xlrd.xldate.xldate_from_date_tuple(tmp_array, 0) + style = XFStyle() + style.num_format_str = DEFAULT_DATE_FORMAT + elif isinstance(value, datetime.time): + tmp_array = [value.hour, value.minute, value.second] + value = xlrd.xldate.xldate_from_time_tuple(tmp_array) + style = XFStyle() + style.num_format_str = DEFAULT_TIME_FORMAT + if style: + self._native_sheet.write(self.current_row, i, value, style) + else: + self._native_sheet.write(self.current_row, i, value) + self.current_row += 1 + + +class XLSWriter(BookWriter): + """ + xls writer + """ + file_types = ['xls'] + stream_type = 'binary' + + def __init__(self): + BookWriter.__init__(self) + self.work_book = None + + def open(self, file_name, + encoding='ascii', style_compression=2, **keywords): + BookWriter.open(self, file_name, **keywords) + self.work_book = Workbook(style_compression=style_compression, + encoding=encoding) + + def create_sheet(self, name): + return XLSheetWriter(self.work_book, None, name) + + def close(self): + """ + This call actually save the file + """ + self.work_book.save(self._file_alike_object) From 0648fdc4d636b1a128934fa567b6c2e0a82b0787 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 18 Apr 2017 23:49:36 +0100 Subject: [PATCH 031/163] fix unit test failure --- tests/test_writer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_writer.py b/tests/test_writer.py index 80d34f1..7ec75ba 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,5 +1,6 @@ import os -from pyexcel_xls.xls import XLSWriter as Writer, XLSBook as Reader +from pyexcel_xls.xlsw import XLSWriter as Writer +from pyexcel_xls.xlsr import XLSBook as Reader from base import PyexcelWriterBase, PyexcelHatWriterBase From 5eba2be0de9288652f8fb4b06d885f09f23f109f Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 19 Apr 2017 18:16:47 +0100 Subject: [PATCH 032/163] Simplify plugin info declaration --- pyexcel_xls/__init__.py | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index 726f5d8..2afaa69 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -10,25 +10,16 @@ # flake8: noqa # this line has to be place above all else # because of dynamic import -__FILE_TYPE__ = 'xls' -__pyexcel_io_plugins__ = [ - { - 'plugin_type': 'pyexcel-io reader', - 'submodule': 'xlsr', - 'file_types': [__FILE_TYPE__, 'xlsx', 'xlsm'], - 'stream_type': 'binary' - }, - { - 'plugin_type': 'pyexcel-io writer', - 'submodule': 'xlsw', - 'file_types': [__FILE_TYPE__], - 'stream_type': 'binary' - }, -] - - +from pyexcel_io.plugins import IORegistry from pyexcel_io.io import get_data as read_data, isstream, store_data as write_data +__FILE_TYPE__ = 'xls' +__pyexcel_io_plugins__ = IORegistry(__name__).add_a_reader( + submodule='xlsr', + file_types=[__FILE_TYPE__, 'xlsx', 'xlsm'], + stream_type='binary' +).add_a_writer(submodule='xlsw', file_types=[__FILE_TYPE__], stream_type='binary') + def get_data(afile, file_type=None, **keywords): """standalone module function for reading module supported file type""" From 436015ebdd6cd4d8786110a6417fa31600827eaf Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 26 Apr 2017 22:43:17 +0100 Subject: [PATCH 033/163] update io plugin interface --- pyexcel_xls/__init__.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index 2afaa69..3882722 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -14,11 +14,15 @@ from pyexcel_io.plugins import IORegistry from pyexcel_io.io import get_data as read_data, isstream, store_data as write_data __FILE_TYPE__ = 'xls' -__pyexcel_io_plugins__ = IORegistry(__name__).add_a_reader( - submodule='xlsr', +IORegistry(__name__).add_a_reader( + submodule='xlsr.XLSBook', file_types=[__FILE_TYPE__, 'xlsx', 'xlsm'], stream_type='binary' -).add_a_writer(submodule='xlsw', file_types=[__FILE_TYPE__], stream_type='binary') +).add_a_writer( + submodule='xlsw.XLSWriter', + file_types=[__FILE_TYPE__], + stream_type='binary' +) def get_data(afile, file_type=None, **keywords): From 69be5d56173058a82fbeb037dcb124212e36cfd3 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 6 May 2017 09:32:11 +0100 Subject: [PATCH 034/163] fix #15: assign native_book to None on closing --- pyexcel_xls/xlsr.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 941a0fb..5ad1c04 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -1,8 +1,8 @@ """ - pyexcel_xls + pyexcel_xlsr ~~~~~~~~~~~~~~~~~~~ - The lower level xls/xlsm file format handler using xlrd/xlwt + The lower level xls/xlsm file format handler using xlrd :copyright: (c) 2016-2017 by Onni Software Ltd :license: New BSD License @@ -91,6 +91,7 @@ class XLSBook(BookReader): def close(self): if self._native_book: self._native_book.release_resources() + self._native_book = None def read_sheet_by_index(self, sheet_index): self._native_book = self._get_book(on_demand=True) From 4da841fa845987756271be34d1c2db020ade9c10 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 6 May 2017 09:32:22 +0100 Subject: [PATCH 035/163] update documentation --- README.rst | 21 +++++++++++++++++---- pyexcel_xls/xlsw.py | 4 ++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 1ee7c96..b1c028b 100644 --- a/README.rst +++ b/README.rst @@ -2,11 +2,17 @@ pyexcel-xls - Let you focus on data, instead of xls format ================================================================================ -.. image:: https://api.travis-ci.org/pyexcel/pyexcel-xls.png - :target: http://travis-ci.org/pyexcel/pyexcel-xls +.. 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-xls.svg?branch=master + :target: http://travis-ci.org/pyexcel/pyexcel-xls .. image:: https://codecov.io/github/pyexcel/pyexcel-xls/coverage.png - :target: https://codecov.io/github/pyexcel/pyexcel-xls + :target: https://codecov.io/github/pyexcel/pyexcel-xls + +.. image:: https://readthedocs.org/projects/pyexcel-xls/badge/?version=latest + :target: http://pyexcel-xls.readthedocs.org/en/latest/ **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. @@ -29,7 +35,7 @@ or clone it and install it: .. code-block:: bash - $ git clone http://github.com/pyexcel/pyexcel-xls.git + $ git clone https://github.com/pyexcel/pyexcel-xls.git $ cd pyexcel-xls $ python setup.py install @@ -332,3 +338,10 @@ Known Issues >>> import os >>> os.unlink("your_file.xls") >>> os.unlink("another_file.xls") + +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/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 0a48fc6..38167f2 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -1,8 +1,8 @@ """ - pyexcel_xls + pyexcel_xlsw ~~~~~~~~~~~~~~~~~~~ - The lower level xls/xlsm file format handler using xlrd/xlwt + The lower level xls file format handler using xlwt :copyright: (c) 2016-2017 by Onni Software Ltd :license: New BSD License From 2b6f906a8efb19f346fcd36fcf53b5b0e02fe295 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 6 May 2017 09:33:23 +0100 Subject: [PATCH 036/163] add the cfg file --- setup.cfg | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 setup.cfg 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 From 8f17b27a2f72861957be03aafef60b976b6062a7 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 12 May 2017 13:27:34 +0100 Subject: [PATCH 037/163] update change log --- CHANGELOG.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f58b956..433e58a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,17 @@ Change log ================================================================================ +0.4.0 - unreleased +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#15 `_, close file + handle +#. pyexcel-io plugin interface now updated to use + `lml `_. + 0.3.1 - 16.01.2017 -------------------------------------------------------------------------------- From 0474acf6ded9399eb774585bd53c6f50d608aef4 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 12 May 2017 13:33:56 +0100 Subject: [PATCH 038/163] refactoring the test code --- .../test-date-format.xls | Bin tests/test_bug_fixes.py | 86 ++++++++++-------- 2 files changed, 46 insertions(+), 40 deletions(-) rename tests/{test-fixtures => fixtures}/test-date-format.xls (100%) diff --git a/tests/test-fixtures/test-date-format.xls b/tests/fixtures/test-date-format.xls similarity index 100% rename from tests/test-fixtures/test-date-format.xls rename to tests/fixtures/test-date-format.xls diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index f4f79ab..ef1c705 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -12,49 +12,55 @@ from nose.tools import eq_, raises import datetime -class TestBugFix: - def test_pyexcel_issue_5(self): - """pyexcel issue #5 +def test_pyexcel_issue_5(): + """pyexcel issue #5 - datetime is not properly parsed - """ - s = pe.load(os.path.join("tests", - "test-fixtures", - "test-date-format.xls")) - assert s[0, 0] == datetime.datetime(2015, 11, 11, 11, 12, 0) + datetime is not properly parsed + """ + s = pe.load(get_fixture("test-date-format.xls")) + assert s[0, 0] == datetime.datetime(2015, 11, 11, 11, 12, 0) - def test_pyexcel_xls_issue_2(self): - data = OrderedDict() - array = [] - for i in range(4100): - array.append([datetime.datetime.now()]) - data.update({"test": array}) - save_data("test.xls", data) - os.unlink("test.xls") - def test_issue_9_hidden_sheet(self): - test_file = os.path.join("tests", "fixtures", "hidden_sheets.xls") - book_dict = pe.get_book_dict(file_name=test_file) - assert "hidden" not in book_dict - eq_(book_dict['shown'], [['A', 'B']]) +def test_pyexcel_xls_issue_2(): + data = OrderedDict() + array = [] + for i in range(4100): + array.append([datetime.datetime.now()]) + data.update({"test": array}) + save_data("test.xls", data) + os.unlink("test.xls") - def test_issue_9_hidden_sheet_2(self): - test_file = os.path.join("tests", "fixtures", "hidden_sheets.xls") - book_dict = pe.get_book_dict(file_name=test_file, - skip_hidden_sheets=False) - assert "hidden" in book_dict - eq_(book_dict['shown'], [['A', 'B']]) - eq_(book_dict['hidden'], [['a', 'b']]) - def test_issue_10_generator_as_content(self): - def data_gen(): - def custom_row_renderer(row): - for e in row: - yield e - for i in range(2): - yield custom_row_renderer([1, 2]) - save_data("test.xls", {"sheet": data_gen()}) +def test_issue_9_hidden_sheet(): + test_file = get_fixture("hidden_sheets.xls") + book_dict = pe.get_book_dict(file_name=test_file) + assert "hidden" not in book_dict + eq_(book_dict['shown'], [['A', 'B']]) - @raises(IOError) - def test_issue_13_empty_file_content(self): - pe.get_sheet(file_content='', file_type='xls') + +def test_issue_9_hidden_sheet_2(): + test_file = get_fixture("hidden_sheets.xls") + book_dict = pe.get_book_dict(file_name=test_file, + skip_hidden_sheets=False) + assert "hidden" in book_dict + eq_(book_dict['shown'], [['A', 'B']]) + eq_(book_dict['hidden'], [['a', 'b']]) + + +def test_issue_10_generator_as_content(): + def data_gen(): + def custom_row_renderer(row): + for e in row: + yield e + for i in range(2): + yield custom_row_renderer([1, 2]) + save_data("test.xls", {"sheet": data_gen()}) + + +@raises(IOError) +def test_issue_13_empty_file_content(): + pe.get_sheet(file_content='', file_type='xls') + + +def get_fixture(file_name): + return os.path.join("tests", "fixtures", file_name) From f8d76ba0ad7905b89aec1cc4e5c91db0c9ced4c3 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 12 May 2017 13:41:59 +0100 Subject: [PATCH 039/163] fix #16: where only stream instance could be passed to file_stream whereas using read() applies to both stream and file handle --- pyexcel_xls/xls.py | 4 +++- tests/test_bug_fixes.py | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 6b8e926..116e7da 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -126,9 +126,11 @@ class XLSBook(BookReader): if self._file_name: xls_book = xlrd.open_workbook(self._file_name, on_demand=on_demand) elif self._file_stream: + self._file_stream.seek(0) + file_content = self._file_stream.read() xls_book = xlrd.open_workbook( None, - file_contents=self._file_stream.getvalue(), + file_contents=file_content, on_demand=on_demand ) elif self._file_content is not None: diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index ef1c705..01ec758 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -62,5 +62,11 @@ def test_issue_13_empty_file_content(): pe.get_sheet(file_content='', file_type='xls') +def test_issue_16_file_stream_has_no_getvalue(): + test_file = get_fixture("hidden_sheets.xls") + with open(test_file, 'rb') as f: + pe.get_sheet(file_stream=f, file_type='xls') + + def get_fixture(file_name): return os.path.join("tests", "fixtures", file_name) From 6e1c324009bb36eed697ad332f2199df23a30f26 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 17 May 2017 08:41:59 +0100 Subject: [PATCH 040/163] pump up version --- CHANGELOG.rst | 9 +++++++++ docs/source/conf.py | 4 ++-- pyexcel_xls.yaml | 4 ++-- setup.py | 2 +- tests/test_writer.py | 5 +++-- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f58b956..b5cbda6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.3.2 - unreleased +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#16 `_, allow mmap to + be passed as file content + 0.3.1 - 16.01.2017 -------------------------------------------------------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index a4d7158..e3804b5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,8 +21,8 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.3.0' -release = '0.3.1' +version = '0.3.1' +release = '0.3.2' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index ce37cb2..ae7fd61 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.3.1 -release: 0.3.0 +version: 0.3.2 +release: 0.3.1 file_type: xls dependencies: - pyexcel-io>=0.3.0 diff --git a/setup.py b/setup.py index 9cc7468..6a35a3c 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.3.1' +VERSION = '0.3.2' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( diff --git a/tests/test_writer.py b/tests/test_writer.py index 80d34f1..a045814 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,5 +1,6 @@ import os -from pyexcel_xls.xls import XLSWriter as Writer, XLSBook as Reader +from pyexcel_xls.xlsw import XLSWriter as Writer +from pyexcel_xls.xlsr import XLSBook as Reader from base import PyexcelWriterBase, PyexcelHatWriterBase @@ -18,10 +19,10 @@ class TestNativeXLSWriter: 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 abb9b56b62c684b49a494540a8bc170657336b6b Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 18 May 2017 20:28:51 +0100 Subject: [PATCH 041/163] test against pyexcel-io 0.3.4 --- rnd_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 8b13789..30a50e9 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1 +1 @@ - +https://github.com/pyexcel/pyexcel-io/archive/master.zip From c9d92235540dd72d859a8ad9e6a67e1ff48dbfb8 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 18 May 2017 20:34:14 +0100 Subject: [PATCH 042/163] update test case --- tests/test_writer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_writer.py b/tests/test_writer.py index a045814..332dd70 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,6 +1,6 @@ import os -from pyexcel_xls.xlsw import XLSWriter as Writer -from pyexcel_xls.xlsr import XLSBook as Reader +from pyexcel_xls.xls import XLSWriter as Writer +from pyexcel_xls.xls import XLSBook as Reader from base import PyexcelWriterBase, PyexcelHatWriterBase From 4de3894e75a92d38161834150da7e47d2c7532d2 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 18 May 2017 20:35:56 +0100 Subject: [PATCH 043/163] release 0.3.2 --- CHANGELOG.rst | 2 +- docs/source/conf.py | 2 +- pyexcel_xls.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b5cbda6..7ea8e5b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.3.2 - unreleased +0.3.2 - 18.05.2017 -------------------------------------------------------------------------------- Updated diff --git a/docs/source/conf.py b/docs/source/conf.py index e3804b5..8bda021 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,7 +21,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.3.1' +version = '0.3.2' release = '0.3.2' exclude_patterns = [] pygments_style = 'sphinx' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index ae7fd61..c0b8ac2 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -2,7 +2,7 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls version: 0.3.2 -release: 0.3.1 +release: 0.3.2 file_type: xls dependencies: - pyexcel-io>=0.3.0 From 291fbb8e87ad551e87267919b0ab83ade6dc947e Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 21 May 2017 22:34:43 +0100 Subject: [PATCH 044/163] remove now useless class fields --- pyexcel_xls/xlsr.py | 3 --- pyexcel_xls/xlsw.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 687e767..2b18aab 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -68,9 +68,6 @@ class XLSBook(BookReader): It reads xls, xlsm, xlsx work book """ - file_types = ['xls', 'xlsm', 'xlsx'] - stream_type = 'binary' - def __init__(self): BookReader.__init__(self) self._file_content = None diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 38167f2..7af5cb5 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -66,9 +66,6 @@ class XLSWriter(BookWriter): """ xls writer """ - file_types = ['xls'] - stream_type = 'binary' - def __init__(self): BookWriter.__init__(self) self.work_book = None From 9e9ed77c8c747c932977ae65d51ca93cc24aa91b Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 22 May 2017 08:42:08 +0100 Subject: [PATCH 045/163] propagate the lml interface changes --- README.rst | 2 +- pyexcel_xls/__init__.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index b1c028b..263be65 100644 --- a/README.rst +++ b/README.rst @@ -343,5 +343,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_xls/__init__.py b/pyexcel_xls/__init__.py index 3882722..839f600 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -10,16 +10,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__ = 'xls' -IORegistry(__name__).add_a_reader( - submodule='xlsr.XLSBook', +IOPluginInfoChain(__name__).add_a_reader( + relative_plugin_class_path='xlsr.XLSBook', file_types=[__FILE_TYPE__, 'xlsx', 'xlsm'], stream_type='binary' ).add_a_writer( - submodule='xlsw.XLSWriter', + relative_plugin_class_path='xlsw.XLSWriter', file_types=[__FILE_TYPE__], stream_type='binary' ) From 80396cc0c081acafe21b887f172a7e47385f5cda Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 26 May 2017 18:51:38 +0100 Subject: [PATCH 046/163] fix #18: pass on encoding_override and others to xlrd --- pyexcel_xls/xls.py | 31 ++++++++++++++++++++----------- tests/test_bug_fixes.py | 13 +++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/pyexcel_xls/xls.py b/pyexcel_xls/xls.py index 116e7da..c8dbc2a 100644 --- a/pyexcel_xls/xls.py +++ b/pyexcel_xls/xls.py @@ -26,6 +26,11 @@ else: DEFAULT_DATE_FORMAT = "DD/MM/YY" DEFAULT_TIME_FORMAT = "HH:MM:SS" DEFAULT_DATETIME_FORMAT = "%s %s" % (DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT) +XLS_KEYWORDS = [ + 'filename', 'logfile', 'verbosity', 'use_mmap', + 'file_contents', 'encoding_override', 'formatting_info', + 'on_demand', 'ragged_rows' +] class XLSheet(SheetReader): @@ -123,30 +128,34 @@ class XLSBook(BookReader): return {sheet.name: sheet.to_array()} def _get_book(self, on_demand=False): + xlrd_params = self._extract_xlrd_params() + xlrd_params['on_demand'] = on_demand + if self._file_name: - xls_book = xlrd.open_workbook(self._file_name, on_demand=on_demand) + xlrd_params['filename'] = self._file_name elif self._file_stream: self._file_stream.seek(0) file_content = self._file_stream.read() - xls_book = xlrd.open_workbook( - None, - file_contents=file_content, - on_demand=on_demand - ) + xlrd_params['file_contents'] = file_content elif self._file_content is not None: - xls_book = xlrd.open_workbook( - None, - file_contents=self._file_content, - on_demand=on_demand - ) + xlrd_params['file_contents'] = self._file_content else: raise IOError("No valid file name or file content found.") + xls_book = xlrd.open_workbook(**xlrd_params) return xls_book def _get_params(self): self.skip_hidden_sheets = self._keywords.get( 'skip_hidden_sheets', True) + def _extract_xlrd_params(self): + params = {} + if self._keywords is not None: + for key in list(self._keywords.keys()): + if key in XLS_KEYWORDS: + params[key] = self._keywords.pop(key) + return params + class XLSheetWriter(SheetWriter): """ diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 01ec758..8f3fede 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -10,6 +10,7 @@ from pyexcel_xls import save_data from _compact import OrderedDict from nose.tools import eq_, raises import datetime +from mock import patch def test_pyexcel_issue_5(): @@ -68,5 +69,17 @@ def test_issue_16_file_stream_has_no_getvalue(): pe.get_sheet(file_stream=f, file_type='xls') +@patch('xlrd.open_workbook') +def test_issue_18_encoding_override_isnt_passed(fake_open): + fake_open.return_value = None + test_encoding = 'utf-32' + from pyexcel_xls.xls import XLSBook + book = XLSBook() + book.open('fake_file.xls', encoding_override=test_encoding) + book._get_book() + keywords = fake_open.call_args[1] + assert keywords['encoding_override'] == test_encoding + + def get_fixture(file_name): return os.path.join("tests", "fixtures", file_name) From 00ac5041306244d4721be9b64c929347f0123c1b Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 26 May 2017 18:53:23 +0100 Subject: [PATCH 047/163] pump up the version 0.3.3 --- CHANGELOG.rst | 9 +++++++++ docs/source/conf.py | 2 +- pyexcel_xls.yaml | 2 +- setup.py | 2 +- tests/requirements.txt | 1 + 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7ea8e5b..5a67a64 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.3.3 - unreleased +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#18 `_, pass on + encoding_override and others to xlrd. + 0.3.2 - 18.05.2017 -------------------------------------------------------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index 8bda021..35747bf 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' version = '0.3.2' -release = '0.3.2' +release = '0.3.3' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index c0b8ac2..d360fe3 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,7 +1,7 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.3.2 +version: 0.3.3 release: 0.3.2 file_type: xls dependencies: diff --git a/setup.py b/setup.py index 6a35a3c..a517af6 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.3.2' +VERSION = '0.3.3' EMAIL = 'wangc_2011 (at) hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( diff --git a/tests/requirements.txt b/tests/requirements.txt index 74a0108..e9aa366 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,5 @@ nose +mock codecov coverage flake8 From a2c0e5dc20b719cb8267d754801225af4932d997 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 30 May 2017 22:38:22 +0100 Subject: [PATCH 048/163] release v0.3.3 --- .travis.yml | 2 +- CHANGELOG.rst | 2 +- docs/source/conf.py | 4 ++-- pyexcel_xls.yaml | 2 +- tests/requirements.txt | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 825e7d2..9d8db60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,13 +3,13 @@ language: python notifications: email: false python: + - pypy - 3.6 - 3.5 - 3.4 - 3.3 - 2.7 - 2.6 - - pypy matrix: include: - python: 2.7 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5a67a64..8ac27a1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.3.3 - unreleased +0.3.3 - 30/05/2017 -------------------------------------------------------------------------------- Updated diff --git a/docs/source/conf.py b/docs/source/conf.py index 35747bf..9f9bf70 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -12,7 +12,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'] @@ -21,7 +21,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.3.2' +version = '0.3.3' release = '0.3.3' exclude_patterns = [] pygments_style = 'sphinx' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index d360fe3..639ec4d 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -2,7 +2,7 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls version: 0.3.3 -release: 0.3.2 +release: 0.3.3 file_type: xls dependencies: - pyexcel-io>=0.3.0 diff --git a/tests/requirements.txt b/tests/requirements.txt index e9aa366..a29762c 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,5 +1,5 @@ nose -mock +mock;python_version<"3" codecov coverage flake8 From 47ab50819d4b60879c5bc18d9bc504e25d3f7fcc Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 30 May 2017 22:41:32 +0100 Subject: [PATCH 049/163] adding setup config --- setup.cfg | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 setup.cfg 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 From 94226c06693c49a1d790f9b4aff558fc8e09bc83 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 4 Jun 2017 17:39:40 +0100 Subject: [PATCH 050/163] code refactoring --- pyexcel_xls/xlsr.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index ec53052..56b9234 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -79,18 +79,18 @@ class XLSBook(BookReader): BookReader.__init__(self) self._file_content = None - def open(self, file_name, **keywords): + def open(self, file_name, skip_hidden_sheets=True, **keywords): BookReader.open(self, file_name, **keywords) - self._get_params() + self.__skip_hidden_sheets = skip_hidden_sheets - def open_stream(self, file_stream, **keywords): + def open_stream(self, file_stream, skip_hidden_sheets=True, **keywords): BookReader.open_stream(self, file_stream, **keywords) - self._get_params() + self.__skip_hidden_sheets = skip_hidden_sheets - def open_content(self, file_content, **keywords): + def open_content(self, file_content, skip_hidden_sheets=True, **keywords): self._keywords = keywords self._file_content = file_content - self._get_params() + self.__skip_hidden_sheets = skip_hidden_sheets def close(self): if self._native_book: @@ -114,7 +114,7 @@ class XLSBook(BookReader): result = OrderedDict() self._native_book = self._get_book() for sheet in self._native_book.sheets(): - if self.skip_hidden_sheets and sheet.visibility != 0: + if self.__skip_hidden_sheets and sheet.visibility != 0: continue data_dict = self.read_sheet(sheet) result.update(data_dict) @@ -141,10 +141,6 @@ class XLSBook(BookReader): xls_book = xlrd.open_workbook(**xlrd_params) return xls_book - def _get_params(self): - self.skip_hidden_sheets = self._keywords.get( - 'skip_hidden_sheets', True) - def _extract_xlrd_params(self): params = {} if self._keywords is not None: From 59bdcff4248d51a0914a01262ac9206de7d10bda Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 4 Jun 2017 17:41:14 +0100 Subject: [PATCH 051/163] update patreon text --- .travis.yml | 1 - README.rst | 22 +++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9d8db60..fabc323 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,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/README.rst b/README.rst index 263be65..cdb9433 100644 --- a/README.rst +++ b/README.rst @@ -39,6 +39,21 @@ or clone it and install it: $ cd pyexcel-xls $ 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 ================================================================================ @@ -338,10 +353,3 @@ Known Issues >>> import os >>> os.unlink("your_file.xls") >>> os.unlink("another_file.xls") - -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. From fd29e7e7aa69a8b282cd3ed612138ea1bf8cb52e Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 13 Jun 2017 18:45:07 +0100 Subject: [PATCH 052/163] update dependencies --- .travis.yml | 3 +++ docs/source/conf.py | 2 +- pyexcel_xls.yaml | 4 ++-- requirements.txt | 2 +- setup.py | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index fabc323..16c6255 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,9 @@ matrix: - python-nose - python-mock 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 ordereddict; fi - 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/docs/source/conf.py b/docs/source/conf.py index 99b233d..77a0426 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,7 +21,7 @@ master_doc = 'index' project = u'pyexcel-xls' 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_xls.yaml b/pyexcel_xls.yaml index 271c40f..dbbb51e 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -2,10 +2,10 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls version: 0.4.0 -release: 0.3.3 +release: 0.4.0 file_type: xls dependencies: - - pyexcel-io>=0.3.0 + - pyexcel-io>=0.4.0 - xlrd - xlwt description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format diff --git a/requirements.txt b/requirements.txt index 2f413dc..38b71d8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -pyexcel-io>=0.3.0 +pyexcel-io>=0.4.0 xlrd xlwt diff --git a/setup.py b/setup.py index e4a9fa0..eadaf67 100644 --- a/setup.py +++ b/setup.py @@ -44,7 +44,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.3.0', + 'pyexcel-io>=0.4.0', 'xlrd', 'xlwt', ] From 3a7179843336a0d90fbdfb2e234f87ec3f73c561 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 13 Jun 2017 22:09:29 +0100 Subject: [PATCH 053/163] code optimization --- pyexcel_xls/xlsr.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 56b9234..e7574b0 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -7,19 +7,13 @@ :copyright: (c) 2016-2017 by Onni Software Ltd :license: New BSD License """ -import sys import math import datetime import xlrd from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader - -PY2 = sys.version_info[0] == 2 -if PY2 and sys.version_info[1] < 7: - from ordereddict import OrderedDict -else: - from collections import OrderedDict +from pyexcel_io._compact import OrderedDict XLS_KEYWORDS = [ From 5cd98619df26f5a768a48ac90827f2284b9dd39e Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 19 Jun 2017 10:43:48 +0100 Subject: [PATCH 054/163] release v0.4.0 --- CHANGELOG.rst | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fcfb5ce..32f0417 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.4.0 - unreleased +0.4.0 - 19.06.2017 -------------------------------------------------------------------------------- Updated diff --git a/setup.py b/setup.py index eadaf67..7f0707e 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' 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 xls format. It' + From 21fb7e2638f832b3c19556dfc4f446d7fab5db7e Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 20 Aug 2017 01:07:43 +0100 Subject: [PATCH 055/163] :books: update documentations --- .moban.yml | 6 ++--- .travis.yml | 5 +--- README.rst | 64 ++++++++++++++++++++++++++++++--------------- docs/source/conf.py | 2 +- setup.py | 20 +++++++++----- 5 files changed, 61 insertions(+), 36 deletions(-) diff --git a/.moban.yml b/.moban.yml index 5855bb6..c5b932b 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_xls.yaml targets: @@ -10,11 +11,10 @@ targets: - "docs/source/conf.py": "docs/source/conf.py.jj2" - .travis.yml: travis.yml - requirements.txt: requirements.txt - - LICENSE: 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.jj2" - "tests/test_stringio.py": "tests/test_stringio.py.jj2" diff --git a/.travis.yml b/.travis.yml index 16c6255..7a38bf0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: python notifications: email: false python: - - pypy + - pypy-5.3.1 - 3.6 - 3.5 - 3.4 @@ -26,9 +26,6 @@ matrix: - python-nose - python-mock 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 ordereddict; fi - 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/README.rst b/README.rst index cdb9433..33fafee 100644 --- a/README.rst +++ b/README.rst @@ -8,8 +8,11 @@ pyexcel-xls - Let you focus on data, instead of xls format .. image:: https://api.travis-ci.org/pyexcel/pyexcel-xls.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-xls -.. image:: https://codecov.io/github/pyexcel/pyexcel-xls/coverage.png - :target: https://codecov.io/github/pyexcel/pyexcel-xls +.. image:: https://codecov.io/gh/pyexcel/pyexcel-xls/branch/master/graph/badge.svg + :target: https://codecov.io/gh/pyexcel/pyexcel-xls + +.. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg + :target: https://gitter.im/pyexcel/Lobby .. image:: https://readthedocs.org/projects/pyexcel-xls/badge/?version=latest :target: http://pyexcel-xls.readthedocs.org/en/latest/ @@ -305,28 +308,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 ------------------------------ @@ -341,6 +332,37 @@ 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/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 +--------------------------------- + +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 +#. Please update CHANGELOG.rst +#. Please add yourself to CONTRIBUTORS.rst +#. Agree on NEW BSD License for your contribution + Known Issues ============= diff --git a/docs/source/conf.py b/docs/source/conf.py index 77a0426..1795e57 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -12,7 +12,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.py b/setup.py index 7f0707e..76b3c23 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.4.0' +VERSION = '' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -18,13 +18,14 @@ DESCRIPTION = ( ' reads xlsx and xlsm format' + '' ) +URL = 'https://github.com/pyexcel/pyexcel-xls' +DOWNLOAD_URL = '%s/archive/0.4.0.tar.gz' % URL +FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ - 'excel', - 'python', - 'pyexcel', 'xls', 'xlsx', 'xlsm' + 'python' ] CLASSIFIERS = [ @@ -32,7 +33,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', @@ -89,7 +89,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__': @@ -99,7 +103,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 0d4370f88e9c138ed7f9d55ef8474f10204fbec6 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 20 Aug 2017 01:10:36 +0100 Subject: [PATCH 056/163] :books: update gitignore --- .gitignore | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++-- .moban.yml | 1 + 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index c2ece11..f32c742 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +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 +.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 c5b932b..e837507 100644 --- a/.moban.yml +++ b/.moban.yml @@ -11,6 +11,7 @@ targets: - "docs/source/conf.py": "docs/source/conf.py.jj2" - .travis.yml: travis.yml - requirements.txt: requirements.txt + - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 - "tests/requirements.txt": "tests/requirements.txt" - test.sh: test.script.jj2 From 1084452855b56bf3ab6c88909dbcdabdc960068d Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 Aug 2017 23:06:32 +0100 Subject: [PATCH 057/163] :umbrella: reproduce issue #20 --- tests/test_bug_fixes.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index e065f73..9b0d4df 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -9,9 +9,12 @@ import pyexcel as pe from pyexcel_xls import save_data from _compact import OrderedDict from nose.tools import eq_, raises +from nose import SkipTest import datetime from mock import patch +IS_TRAVIS = 'TRAVIS' in os.environ + def test_pyexcel_issue_5(): """pyexcel issue #5 @@ -81,5 +84,12 @@ def test_issue_18_encoding_override_isnt_passed(fake_open): assert keywords['encoding_override'] == test_encoding +def test_issue_20(): + import pdb; pdb.set_trace() + if not IS_TRAVIS: + raise SkipTest() + pe.get_book(url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls"); # flake8: noqa + + def get_fixture(file_name): return os.path.join("tests", "fixtures", file_name) From 119f0c9eef68b4aaaeded6337b68ebe62579b7b3 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 Aug 2017 23:13:47 +0100 Subject: [PATCH 058/163] :bug: fix #20, no seeking for url stream --- pyexcel_xls/xlsr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index e7574b0..308f309 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -125,7 +125,8 @@ class XLSBook(BookReader): if self._file_name: xlrd_params['filename'] = self._file_name elif self._file_stream: - self._file_stream.seek(0) + if hasattr(self._file_stream, 'seek'): + self._file_stream.seek(0) file_content = self._file_stream.read() xlrd_params['file_contents'] = file_content elif self._file_content is not None: From e6907015f99508c93a722d27fc79c35ebcb5b79c Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 Aug 2017 23:14:00 +0100 Subject: [PATCH 059/163] :books: new version string --- .moban.d/README.rst | 3 +++ README.rst | 2 -- docs/source/conf.py | 2 +- pyexcel_xls.yaml | 3 ++- setup.py | 2 +- tests/test_bug_fixes.py | 4 ++-- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.moban.d/README.rst b/.moban.d/README.rst index 5dee5c3..1829748 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-{{file_type}}** is a tiny wrapper library to read, manipulate and write data in {{file_type}} format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. {%endblock%} diff --git a/README.rst b/README.rst index 33fafee..debaced 100644 --- a/README.rst +++ b/README.rst @@ -14,8 +14,6 @@ pyexcel-xls - Let you focus on data, instead of xls format .. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg :target: https://gitter.im/pyexcel/Lobby -.. image:: https://readthedocs.org/projects/pyexcel-xls/badge/?version=latest - :target: http://pyexcel-xls.readthedocs.org/en/latest/ **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. diff --git a/docs/source/conf.py b/docs/source/conf.py index 1795e57..3d61b9f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ master_doc = 'index' project = u'pyexcel-xls' 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_xls.yaml b/pyexcel_xls.yaml index dbbb51e..3eaf6be 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,7 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.4.0 +version: 0.4.1 +current_version: 0.4.1 release: 0.4.0 file_type: xls dependencies: diff --git a/setup.py b/setup.py index 76b3c23..63d6604 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '' +VERSION = '0.4.1' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 9b0d4df..413ab39 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -13,7 +13,7 @@ from nose import SkipTest import datetime from mock import patch -IS_TRAVIS = 'TRAVIS' in os.environ +IN_TRAVIS = 'TRAVIS' in os.environ def test_pyexcel_issue_5(): @@ -86,7 +86,7 @@ def test_issue_18_encoding_override_isnt_passed(fake_open): def test_issue_20(): import pdb; pdb.set_trace() - if not IS_TRAVIS: + if not IN_TRAVIS: raise SkipTest() pe.get_book(url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls"); # flake8: noqa From 789d410aa50410b2b90825c891a5aee7a0d1da57 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 Aug 2017 23:18:23 +0100 Subject: [PATCH 060/163] :bug: fix flake8 warnings --- tests/test_bug_fixes.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 413ab39..6d43b46 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -85,11 +85,10 @@ def test_issue_18_encoding_override_isnt_passed(fake_open): def test_issue_20(): - import pdb; pdb.set_trace() if not IN_TRAVIS: raise SkipTest() pe.get_book(url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls"); # flake8: noqa - + def get_fixture(file_name): return os.path.join("tests", "fixtures", file_name) From ec325aadcd83f064d74da7fbd047ac5f397eb048 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 23 Aug 2017 23:46:32 +0100 Subject: [PATCH 061/163] :green_heart: fix broken test --- pyexcel_xls/xlsr.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 308f309..e109069 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -10,10 +10,11 @@ import math import datetime import xlrd +from io import UnsupportedOperation from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader -from pyexcel_io._compact import OrderedDict +from pyexcel_io._compact import OrderedDict, PY2 XLS_KEYWORDS = [ @@ -125,8 +126,14 @@ class XLSBook(BookReader): if self._file_name: xlrd_params['filename'] = self._file_name elif self._file_stream: - if hasattr(self._file_stream, 'seek'): - self._file_stream.seek(0) + if PY2: + if hasattr(self._file_stream, 'seek'): + self._file_stream.seek(0) + else: + try: + self._file_stream.seek(0) + except UnsupportedOperation: + pass file_content = self._file_stream.read() xlrd_params['file_contents'] = file_content elif self._file_content is not None: From 2000b49c28e4bc8ba71edd4c62c5517a48747da7 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Aug 2017 07:00:36 +0100 Subject: [PATCH 062/163] :egg: :ferris_wheel: release 0.4.1 --- CHANGELOG.rst | 9 +++++++++ docs/source/conf.py | 2 +- pyexcel_xls.yaml | 2 +- setup.py | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 32f0417..09f31b5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.4.1 - 25.08.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#20 `_, 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 3d61b9f..b910ec1 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,7 +21,7 @@ master_doc = 'index' project = u'pyexcel-xls' 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_xls.yaml b/pyexcel_xls.yaml index 3eaf6be..2de220b 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -3,7 +3,7 @@ name: "pyexcel-xls" nick_name: xls version: 0.4.1 current_version: 0.4.1 -release: 0.4.0 +release: 0.4.1 file_type: xls dependencies: - pyexcel-io>=0.4.0 diff --git a/setup.py b/setup.py index 63d6604..9f0cd4c 100644 --- a/setup.py +++ b/setup.py @@ -19,8 +19,8 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -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 = [ 'xls', 'xlsx', From ba2610b5f7d233a3057c8defbb175ef6997b2916 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Aug 2017 07:54:14 +0100 Subject: [PATCH 063/163] :fire: remove useless code as it is now handled in pyexcel-io --- pyexcel_xls/xlsr.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index e109069..e7574b0 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -10,11 +10,10 @@ import math import datetime import xlrd -from io import UnsupportedOperation 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 XLS_KEYWORDS = [ @@ -126,14 +125,7 @@ class XLSBook(BookReader): if self._file_name: xlrd_params['filename'] = self._file_name elif self._file_stream: - if PY2: - if hasattr(self._file_stream, 'seek'): - self._file_stream.seek(0) - else: - try: - self._file_stream.seek(0) - except UnsupportedOperation: - pass + self._file_stream.seek(0) file_content = self._file_stream.read() xlrd_params['file_contents'] = file_content elif self._file_content is not None: From 06c51137ec5815272928f26baf201e1fe9ebb175 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Aug 2017 07:57:27 +0100 Subject: [PATCH 064/163] :art: use dev branch of pyexcel-io --- rnd_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 971c3d8..f7d7dd2 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/archive/master.zip -https://github.com/pyexcel/pyexcel-io/archive/v0.4.x.zip +https://github.com/pyexcel/pyexcel-io/archive/dev.zip From b91fba369671f04dafbb1868a91773846c44b503 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Aug 2017 19:05:14 +0100 Subject: [PATCH 065/163] :newspaper: kick start 0.5.0 --- docs/source/conf.py | 2 +- pyexcel_xls.yaml | 6 +++--- pyexcel_xls/xlsr.py | 9 ++------- requirements.txt | 2 +- rnd_requirements.txt | 2 -- setup.py | 4 ++-- 6 files changed, 9 insertions(+), 16 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b910ec1..89ff810 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' version = '0.4.1' -release = '0.4.1' +release = '0.5.0' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index 2de220b..cb1afa8 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,12 +1,12 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.4.1 -current_version: 0.4.1 +version: 0.5.0 +current_version: 0.5.0 release: 0.4.1 file_type: xls dependencies: - - pyexcel-io>=0.4.0 + - pyexcel-io>=0.5.0 - xlrd - xlwt description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index e7574b0..5b5f19d 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -7,13 +7,13 @@ :copyright: (c) 2016-2017 by Onni Software Ltd :license: New BSD License """ -import math import datetime import xlrd from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader from pyexcel_io._compact import OrderedDict +from pyexcel_io.service import has_no_digits_in_float XLS_KEYWORDS = [ @@ -58,7 +58,7 @@ class XLSheet(SheetReader): if cell_type == xlrd.XL_CELL_DATE: value = xldate_to_python_date(value) elif cell_type == xlrd.XL_CELL_NUMBER and self.__auto_detect_int: - if is_integer_ok_for_xl_float(value): + if has_no_digits_in_float(value): value = int(value) return value @@ -144,11 +144,6 @@ class XLSBook(BookReader): return params -def is_integer_ok_for_xl_float(value): - """check if a float value had zero value in digits""" - return value == math.floor(value) - - def xldate_to_python_date(value): """ convert xl date to python date diff --git a/requirements.txt b/requirements.txt index 38b71d8..3f33157 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -pyexcel-io>=0.4.0 +pyexcel-io>=0.5.0 xlrd xlwt diff --git a/rnd_requirements.txt b/rnd_requirements.txt index f7d7dd2..dffaa2d 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/archive/master.zip https://github.com/pyexcel/pyexcel-io/archive/dev.zip diff --git a/setup.py b/setup.py index 9f0cd4c..5bb53b5 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.4.1' +VERSION = '0.5.0' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -44,7 +44,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.4.0', + 'pyexcel-io>=0.5.0', 'xlrd', 'xlwt', ] From 052d5f32bdebab260182d177725be93455811128 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 25 Aug 2017 19:16:17 +0100 Subject: [PATCH 066/163] :bug: do not ever seek, pyexcel-io will make sure it has reset the file handle to 0 --- pyexcel_xls/xlsr.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 5b5f19d..ee09ff4 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -125,7 +125,6 @@ class XLSBook(BookReader): if self._file_name: xlrd_params['filename'] = self._file_name elif self._file_stream: - self._file_stream.seek(0) file_content = self._file_stream.read() xlrd_params['file_contents'] = file_content elif self._file_content is not None: From 6e831d5676ffe284f6ccb5e28dda6af1c54cb53e Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 30 Aug 2017 22:59:12 +0100 Subject: [PATCH 067/163] :pencil: use master for testing --- rnd_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rnd_requirements.txt b/rnd_requirements.txt index dffaa2d..6d9386d 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,2 +1,2 @@ -https://github.com/pyexcel/pyexcel-io/archive/dev.zip +https://github.com/pyexcel/pyexcel-io/archive/master.zip From ae1657036b37ae41a1dc470a8112594a21c42844 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 30 Aug 2017 23:15:10 +0100 Subject: [PATCH 068/163] release 0.5.0 :egg: :ferris_wheel: --- CHANGELOG.rst | 11 +++++++++++ docs/source/conf.py | 2 +- pyexcel_xls.yaml | 2 +- setup.py | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 09f31b5..27a0ef3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,17 @@ Change log ================================================================================ +0.5.0 - 30.08.2017 +-------------------------------------------------------------------------------- + +Updated +******************************************************************************** + +#. `#20 `_, is handled in + pyexcel-io +#. 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. + 0.4.1 - 25.08.2017 -------------------------------------------------------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index 89ff810..7ecd0e1 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,7 +21,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.4.1' +version = '0.5.0' release = '0.5.0' exclude_patterns = [] pygments_style = 'sphinx' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index cb1afa8..5846383 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -3,7 +3,7 @@ name: "pyexcel-xls" nick_name: xls version: 0.5.0 current_version: 0.5.0 -release: 0.4.1 +release: 0.5.0 file_type: xls dependencies: - pyexcel-io>=0.5.0 diff --git a/setup.py b/setup.py index 5bb53b5..3a10665 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -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 = [ 'xls', From df7924f73539f1bb765bb52395229a16f7c94502 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 20 Oct 2017 07:55:56 +0100 Subject: [PATCH 069/163] #21 being able to detect hidden row and column --- MANIFEST.in | 1 + pyexcel_xls/xlsr.py | 21 ++++++++++---- setup.py | 57 ++++++++++++++++++++++++++++++++------ test.bat | 2 +- test.sh | 2 +- tests/fixtures/hidden.xls | Bin 0 -> 25600 bytes tests/test_hidden.py | 8 ++++++ 7 files changed, 74 insertions(+), 17 deletions(-) create mode 100755 tests/fixtures/hidden.xls create mode 100644 tests/test_hidden.py 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/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index ee09ff4..bb454f3 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -72,19 +72,26 @@ class XLSBook(BookReader): def __init__(self): BookReader.__init__(self) self._file_content = None + self.__skip_hidden_sheets = True + self.__skip_hidden_row_column = True - def open(self, file_name, skip_hidden_sheets=True, **keywords): + def open(self, file_name, **keywords): + self.__parse_keywords(**keywords) BookReader.open(self, file_name, **keywords) - self.__skip_hidden_sheets = skip_hidden_sheets - def open_stream(self, file_stream, skip_hidden_sheets=True, **keywords): + def open_stream(self, file_stream, **keywords): + self.__parse_keywords(**keywords) BookReader.open_stream(self, file_stream, **keywords) - self.__skip_hidden_sheets = skip_hidden_sheets - def open_content(self, file_content, skip_hidden_sheets=True, **keywords): + def open_content(self, file_content, **keywords): + self.__parse_keywords(**keywords) self._keywords = keywords self._file_content = file_content - self.__skip_hidden_sheets = skip_hidden_sheets + + def __parse_keywords(self, **keywords): + self.__skip_hidden_sheets = keywords.get('skip_hidden_sheets', True) + self.__skip_hidden_row_column = keywords.get( + 'skip_hidden_row_and_column', True) def close(self): if self._native_book: @@ -131,6 +138,8 @@ class XLSBook(BookReader): xlrd_params['file_contents'] = self._file_content else: raise IOError("No valid file name or file content found.") + if self.__skip_hidden_row_column: + xlrd_params['formatting_info'] = True xls_book = xlrd.open_workbook(**xlrd_params) return xls_book diff --git a/setup.py b/setup.py index 3a10665..4de8481 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,9 @@ -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 sys +import codecs +from shutil import rmtree +from setuptools import setup, find_packages, Command PY2 = sys.version_info[0] == 2 PY26 = PY2 and sys.version_info[1] < 7 @@ -20,7 +19,7 @@ DESCRIPTION = ( ) URL = 'https://github.com/pyexcel/pyexcel-xls' DOWNLOAD_URL = '%s/archive/0.5.0.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', 'xlsx', @@ -53,6 +52,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-xls v0.5.0 ' + + "Find 0.5.0 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): @@ -66,7 +101,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 @@ -114,5 +149,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 fd8fdd3..a09129d 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index fd8fdd3..a09129d 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/tests/fixtures/hidden.xls b/tests/fixtures/hidden.xls new file mode 100755 index 0000000000000000000000000000000000000000..e2d03fff1a4426e88e48eb63d7325cb9d878b94c GIT binary patch literal 25600 zcmeHQ2Urxzv+rHf5|k()C@x7+f+UeMp&~|5R6GMJ5|*GK9)bsdMG)bHQxU@%5D^0> zV#1sN19vDVo&k|lOqe}IJ=Eij`>JMGn4Jy6|9$U$FKqMm%ydonud1u7Yr1=SmdlrP z?`_#{Qb$-}08t`egz7|jv8BT-Y^@l4C$pNY^=}1YY zM;-O4<31{1F?H-u^q|aHWil$<&>gM_l$*pINab5j9WAJ1dpL5)QL4;MisD4f$Sugv zBUxzbz*>#tNdieEi6B8F29E!8a`YhKAfsEer0rOe@`*Rd8%DxOEG4xahXc8bQJpgC zrTo<#w?JR=F;IKD%`(Z-p21gh^!sX#0bj|%As%vTi*<4RN)7@!ixJJ5I{{F;{K*wh?0s&aOXi5t^504gxuEdtWv#gn+sB{y5QBjI* zOSyZ*0NR0&cS1gOrVpq2NJn=<(cg-0$){sCm6l%?9Z{v_|G!M<5I$Cq4qRHFDv+Y| zaHxr{yphtsBz>O@dWH;owha1a8T3LK^xZP(vgBDSBmXWLbXoXx{tgoQq4P`9X?Y~+ zv^ zzJw%$!>8qeQ5}s#(TSmmuHHiD!=)sh#kZX(f3tpQ`+>2g2!94#nuzeVMD%7kS@xWx zt81uf2zsXbU3*b}z^C;r>KE!#^@Fn(Y5veaM85{ZI)3E=U>1xAPZ1I&0zqs zPr0=`k!Md5#psxUOWJ{-SAr|__0+Qjo)7Ke$;*{2fLYp9fF8EBfddNCCJxGNEr2ey zO&qXI+Ef6IwoL`FQQA}h&Ad$ouz$6w06LU56~La+rUKaY+Ef7hQkx2(^J`N9+qM?4 zYij}fwia+`Yk@v(Ezno20QNto6W}EB2C=+`6J$|p_8RO0Twaqq!H$XJV4QSIf;hJZ zMCc(O#HBSL&Mx90Y$xanAT3rRQ5{LqVJ^^AfAntPkA+Nyah0L|c%%H)??T!2w-E!$ zA*#|rgy-ae^cDvZ$dE+%Jcl94N>+3B0uVK-IZMn9OO`lw{3%G}jF6AA?kr&d<+p1`*i+ zQ?(*yOj_&J&F+}}K@7TMV$Gnf#BD&b7BF{iG8(Lf#BfH`F@?fPiCP>ua6rOnm^4u> zkOtUP5E%`VCOKrnwdIytpdE;*Hjy`h)gSvo0p(`*Dp3p6J64bB)KKpt8r>VExm*h< z)#A4yA=$_x5ZQhU2gWTR64IfLm53meDV?MTg<<*EK`OoFgLD!DfrPZ`u$@1<_gJ>?$om!z2`5>mP0jczs z4`MC`0tx9lVS=pY>Jc4yd=Y0yYrZ{yP;jtdcC6DXo)1}ts%r`yWiw$r;tcER)`U;& zAr2zJ@FyU%srNpp01nY2YRZDp+s_+?DtL`g8yE#xqsDag$`@EQbv}tfiEuE(pE<>ZWuyhRDWMzNK{m zHmHW`zJ<{12v)M?ov~F_PFfFapySBDgI-8Dc zHc~9jRt_7crB!+hA8(M(#)QpAilz0G!-i>TmEMQSpGaq8%4Q?Q(p==QVOmDk>_Zv+2TSBgN9}7Z6EpkP02P-_+_(`E?4wFK&^F0N%Q7!Wj9AFPE9+MNZ;v=Hb@r-^jX zt}UQo8*ET}7AVsm2pJOdi*(R#EudftY)~f_D6{nmnX_k@G*BL~fu}1O92l~S_lH(#rG6MMy}!|vE(umYJgnfFc=IbvtVfG30INu$COH{`G};#^(WP4 zspynQDmo>SicYPDMO)isCE+R_UtAOwC8)Y5s3Z#h0zm*mFt1&*D&)0c51Z>oU zxdKa2B^}W0a1aP>KLP{|0|Du`5D2FR9cGB%Od1YNQ4J)c9pP$jdzfS}z`^&i!F8p8 z)BaBexX@#F<)2Uy1b1PAgAZhb>q!Bp{h$nRdT79mE+6yn62jB5b(83CG|1Gb2b-qQVruON5=|Q@q)xLxEj!35F-|Z!nH<`=f#C;kxRox<`zdwr$jD|PKjI^ zom$P+B;Vi~-I%yos>Q!&G3@}*V<;U+wmH+~qlXl0b0oA#LZ?KM&?%85bP642pJWx# zot3xnl@6CAPkRdKdW-y0)SenwT!>4~~aS42+qLE{k@r9^!&>HNjI) z1P(D^$Re*L&8^}?oYHV6ZxYF5ERtkF?R4SK4?u#b+Kva26R0a6s5?5tIIufs&|(Cc zM_Euy4(2vmH!_3TE}RCn^1(O6U>W1X1%gn2%u&ayarmdjkL*Y092m&6ewK1B^W4@2r_XP&GOYOHz>WzY z8@;dk4KCmtM%vwQY0T~WAf}{?+TpVGIXgz~YZz>6_1tvWwEVlh$K2TSZN?%K<9>np z+Uwt*C@r?>y(D==M)tV;`H$y>c^~MXnHAF|Yx~s??%WH#=5MZ*@QG&(Yr@_@)jRFz3SSFg7-r!3>cD&m=hwZi* zTP{vM>-WB6(bMUIURQb*+~GH9F4HS3(#i<96vppp|M*nj+>95s*C$67-_AUcxxj6D z<>)g)gBkBUp6XXsCiy3UMuad@6xUb&^&L-6gPz==$#82&K#U-AZchh1rmna&v&>Oz z$*Z)I#a9x?UM(}Wp4T%!%d_XUL{evy6mDT!Yx=x)%sEw!lf2aJuNrsu|FU=K`?@tx z_=eeqs%7^*JuZaT&Fg-e3O=RgtXdtc10Oi=l!)Lc}*jvEhO! zK~Kif2gXEUf*7eA31%=)i@&C;uj%IVOY7_28BCEgf;7EdLd1b;0Ft_xXX{Bc7QUM!enRayMu0 z+f6HDKbJp9?{m(*F7;QRqYL&t?Bi~>-zj5o--TE-P|b<8b?S{u{Hjs!4Ocaok!l@I?6!X=gK6{HAxtsMu5giSd=6 zHQy||QK92uxYtwHXwH^rYp-qgzg04QNZ$>*9sDDEohu> zjVa&04B!;}@yolJC3!{Px9r)_=zyjy#^@nh%ot&1k+8N7-r*$4%7c$R)yyJ*UQZ-&ed&8 ztsGMI*`WA@$-|4!Yj#|kzG=Y6cW>XnsS5K5n`=Aqhuda9?l^J#WS7zp&re?3}=HTB%7&(D?~J@xs^fX1Tx6Kw7*c+*h7Yh85d=Y|zs0wxt7)r&1CTVi$g z*74UaZc@sZ#bH5GGkIm#t6RnZ@Oqjz@OCG&dhQRr|b6V2)4fn=JRJA-l~xuJYWL_3hC4Rw>1H zk;>-PLnGUpxkn9++V%2&u)g|Hm92&ip5DtH?+lr{$YSFK^B)V$UME@&Hmx{g(ec?a zGo!3$-G8opw%qB7+s3}?yC;tNVDD=@|EBg+3+I&?{9$gJKc+i%z9AU4Nyp2@bl$-G zzULO6U6D6r<=l1Zrk|2Ge4pNLNx!`KStq*aL~j2WX?{%me&P5j9ny=P$JiY&&e$;a z)MAxQ{M~-4hwf&*P5&kA&yU#$J_?r|@V_3{D|`0$ks*JZ@{x0{Xf7R=#V@X?L zzQ5A1bZK4ajTcjenvKG<^oi}H2t~KmFU0$)M{@bc| z{T(@$@!JO*tPtd0_3L?X*Q$h{Hrz4v-o~9_w10Q9f$tPslfxfAPMYdgGvnyqcCOcdN-6(+ zL{+=O0c$FG7qed~=YFhn%pO!f=Xjl0tVYjELoG%`|8v3Sf?eI#rSa=kr)G>URMpjW z|IQ{Od+*eRxvD0%?Z)2vt%FXg_S&gRA&)#Q)kgGQy{wylKfQn5JgnRC*;@mH0o5AM zCkPfM6dekgJG_zKX|wy1*xXy5zCjE3*eSVp?KEAurYbyBz4%gPTI7VJSKX|ZR(f~R-8{!wSCv%;ZRC3pOp2|emAc&5zoboHIT%FpedVS?QOf2GWv zgu&S_SFgI;(5J(x@ix_;r=QvNul&KcqbF$E-`%%%{=(zeq9*1J4%Q9y`@3p|Lt?zH zm(h(KM!ib^dT%|Ybk<3?ps_1=Ub6M_nwq$<`@|zj3%}!~|Gql!YP6qeect7QBOg@u z)$TPi*_1c!sp_UFNAK4E^KPhc=krdsMKy)YU3z`n^xy>%MKpw+}70{XFRW$;-nV;}Y}!+Q?b(t5r#m&irc9ajkE*@Ze{6lZ>#Q zT@0sv89Qk1jWiXTt>u;XEH@T0g^p<;B^Ib3_#8zXD{3fUMz%4pVilsEu; zK-W^*5%kFz-mwd^2S_aiJHp73*$8a)vys@Nl@_Gy(vYaJ3mb!N1T7e4uxi7UMvh7N zj#9zh8!(AeA=9Atr7-CrWFyR8HZmp=aDyxZ+A;NCV^STlk4ZJT26&qaV8A38 zHp)7|=B#!w&%qfw7v^8u)U_@g2`sts$fuouUG)j_^$4KoJt(>@bxffs$<*|P#WX*-YKwXxuh5iab+SMA}nN(H4t%iArB%N?h&wg z+)jphL?4yIrA!)j3!jMKnCQ9Dp|O0g_+UXK8HfckOFpUgt>WNy^1TWtHMpj`6W&w= zg$5KFP-sA*0fhz>8c=9Jp#g;k6dF)yK%oJJ1{4|)X+YlmpId#gI>*6OXZ1Rm|J%La zi}U~U5MfD?n*aO48JBw|LB#Lw!Xe^Yah(6-oIM^Q&ij)g;(J)pdO#LjZHD zIM>ImB{-4BIXk}3$BipE@5ebl{%8-r^T&CIA_e|H9dX9a&(1b;^ZH)^y3|7QRn&gKv;AX-ASf@lq~D@43+1Ly7#dqA{>Xa^BKdLRxE@&0FscvggeUjyUd za~J%AhYz1H;%|oFXNzqKhD3$hw1X0$9r1a1B;+)8Btz+w_z~MoM41TOW8ed|AWDu| zB66$G@LvF$`J)W2Ew~Z3pkYuU%Ed;E#O>`%i26 jcR?8JJP=gK5a5O%4oAVKNZ0~xlgItvs6TEK74iQMR72i{ literal 0 HcmV?d00001 diff --git a/tests/test_hidden.py b/tests/test_hidden.py new file mode 100644 index 0000000..cb6ed64 --- /dev/null +++ b/tests/test_hidden.py @@ -0,0 +1,8 @@ +import os +from pyexcel_xls import get_data + + +def test_hidden_row(): + data = get_data(os.path.join("tests", "fixtures", "hidden.xls"), + skip_hidden_row_and_column=True) + print(data) From f57f7ed85151300f44a22d41d1896c6b0cae3ddd Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 20 Oct 2017 07:57:34 +0100 Subject: [PATCH 070/163] :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 | 9 +++++++ MANIFEST.in | 1 + docs/source/conf.py | 4 +-- pyexcel_xls.yaml | 6 ++--- setup.py | 61 +++++++++++++++++++++++++++++++++++++-------- test.bat | 2 +- test.sh | 2 +- 7 files changed, 67 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 27a0ef3..798ef82 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ 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 7ecd0e1..548dc4c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,8 +21,8 @@ master_doc = 'index' project = u'pyexcel-xls' 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_xls.yaml b/pyexcel_xls.yaml index 5846383..343ad87 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -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: xls dependencies: - pyexcel-io>=0.5.0 diff --git a/setup.py b/setup.py index 3a10665..ea995cb 100644 --- a/setup.py +++ b/setup.py @@ -1,16 +1,15 @@ -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 sys +import codecs +from shutil import rmtree +from setuptools import setup, find_packages, Command PY2 = sys.version_info[0] == 2 PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.0' +VERSION = '0.5.1' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -19,8 +18,8 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -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 = [ 'xls', 'xlsx', @@ -53,6 +52,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-xls 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): @@ -66,7 +101,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 @@ -114,5 +149,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 fd8fdd3..a09129d 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index fd8fdd3..a09129d 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-cov --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long From d7ec09cc03fb56ccb4856dbed3f37a94cb094dfe Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 20 Oct 2017 08:03:57 +0100 Subject: [PATCH 071/163] :bug: fix on-ASCII character '\xe2' in file setup.py on line 81, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index ea995cb..da78df6 100644 --- a/setup.py +++ b/setup.py @@ -78,12 +78,12 @@ class PublishCommand(Command): def run(self): try: - self.status('Removing previous builds…') + self.status('Removing previous builds...') rmtree(os.path.join(here, 'dist')) except OSError: pass - self.status('Building Source and Wheel (universal) distribution…') + self.status('Building Source and Wheel (universal) distribution...') if os.system(GS_COMMAND) == 0: os.system(PUBLISH_COMMAND) From 896492087692b526a85ebbddc471393291dbe6dc Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 20 Oct 2017 18:33:18 +0100 Subject: [PATCH 072/163] :sparkles: initial implementation of #21: skip hidden rows and columns --- CHANGELOG.rst | 9 +++++++++ docs/source/conf.py | 4 ++-- pyexcel_xls.yaml | 6 +++--- pyexcel_xls/xlsr.py | 27 +++++++++++++++++++++++++-- setup.py | 12 ++++++------ tests/test_hidden.py | 4 +++- 6 files changed, 48 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 27a0ef3..ffa0760 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.6.0 - unreleased +-------------------------------------------------------------------------------- + +Added +******************************************************************************** + +#. `#21 `_, skip hidden rows + and columns under 'skip_hidden_row_and_column' flag. + 0.5.0 - 30.08.2017 -------------------------------------------------------------------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index 7ecd0e1..9f48f38 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,8 +21,8 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.5.0' -release = '0.5.0' +version = '0.5.1' +release = '0.6.0' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index 5846383..1f33888 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.5.0 -current_version: 0.5.0 -release: 0.5.0 +version: 0.6.0 +current_version: 0.6.0 +release: 0.5.1 file_type: xls dependencies: - pyexcel-io>=0.5.0 diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index bb454f3..34988f9 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -32,6 +32,15 @@ class XLSheet(SheetReader): def __init__(self, sheet, auto_detect_int=True, **keywords): SheetReader.__init__(self, sheet, **keywords) self.__auto_detect_int = auto_detect_int + self.__hidden_cols = [] + self.__hidden_rows = [] + if keywords.get('skip_hidden_row_and_column') is True: + for col_index, info in self._native_sheet.colinfo_map.items(): + if info.hidden == 1: + self.__hidden_cols.append(col_index) + for row_index, info in self._native_sheet.rowinfo_map.items(): + if info.hidden == 1: + self.__hidden_rows.append(row_index) @property def name(self): @@ -41,18 +50,19 @@ class XLSheet(SheetReader): """ Number of rows in the xls sheet """ - return self._native_sheet.nrows + return self._native_sheet.nrows - len(self.__hidden_rows) def number_of_columns(self): """ Number of columns in the xls sheet """ - return self._native_sheet.ncols + return self._native_sheet.ncols - len(self.__hidden_cols) def cell_value(self, row, column): """ Random access to the xls cells """ + row, column = self._offset_hidden_indices(row, column) cell_type = self._native_sheet.cell_type(row, column) value = self._native_sheet.cell_value(row, column) if cell_type == xlrd.XL_CELL_DATE: @@ -62,6 +72,19 @@ class XLSheet(SheetReader): value = int(value) return value + def _offset_hidden_indices(self, row, column): + row = calculate_offsets(row, self.__hidden_rows) + column = calculate_offsets(column, self.__hidden_cols) + return row, column + + +def calculate_offsets(incoming_index, hidden_indices): + offset = 0 + for index in hidden_indices: + if index <= (incoming_index + offset): + offset += 1 + return incoming_index + offset + class XLSBook(BookReader): """ diff --git a/setup.py b/setup.py index 4de8481..b7b9732 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.0' +VERSION = '0.6.0' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -18,7 +18,7 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -DOWNLOAD_URL = '%s/archive/0.5.0.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.1.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', @@ -54,8 +54,8 @@ EXTRAS_REQUIRE = { } PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( sys.executable) -GS_COMMAND = ('gs pyexcel-xls v0.5.0 ' + - "Find 0.5.0 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls v0.5.1 ' + + "Find 0.5.1 in changelog for more details") here = os.path.abspath(os.path.dirname(__file__)) @@ -78,12 +78,12 @@ class PublishCommand(Command): def run(self): try: - self.status('Removing previous builds…') + self.status('Removing previous builds...') rmtree(os.path.join(here, 'dist')) except OSError: pass - self.status('Building Source and Wheel (universal) distribution…') + self.status('Building Source and Wheel (universal) distribution...') if os.system(GS_COMMAND) == 0: os.system(PUBLISH_COMMAND) diff --git a/tests/test_hidden.py b/tests/test_hidden.py index cb6ed64..76785ca 100644 --- a/tests/test_hidden.py +++ b/tests/test_hidden.py @@ -1,8 +1,10 @@ import os +from nose.tools import eq_ from pyexcel_xls import get_data def test_hidden_row(): data = get_data(os.path.join("tests", "fixtures", "hidden.xls"), skip_hidden_row_and_column=True) - print(data) + expected = [[1, 3], [7, 9]] + eq_(data['Sheet1'], expected) From c3b6c6580a7e1903a784c38e9e2e9689c349b16f Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 23 Oct 2017 18:39:36 +0100 Subject: [PATCH 073/163] :egg: :ferris_wheel: release 0.5.2. related to https://github.com/pyexcel/pyexcel/issues/105 --- .travis.yml | 1 - CHANGELOG.rst | 10 ++++++++++ README.rst | 5 +++-- docs/source/conf.py | 4 ++-- pyexcel_xls.yaml | 8 ++++---- requirements.txt | 2 +- setup.py | 42 ++++++++++++++++++++++++++++++++---------- 7 files changed, 52 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7a38bf0..3805bcd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,6 @@ python: - 3.4 - 3.3 - 2.7 - - 2.6 matrix: include: - python: 2.7 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 798ef82..f5a7b2c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,16 @@ 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 +#. update its dependecy on pyexcel-io to 0.5.3 + 0.5.1 - 20.10.2017 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index debaced..1e35e9d 100644 --- a/README.rst +++ b/README.rst @@ -25,7 +25,8 @@ Fonts, colors and charts are not supported. Installation ================================================================================ -You can install it via pip: + +You can install pyexcel-xls via pip: .. code-block:: bash @@ -48,7 +49,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 548dc4c..4428e91 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,8 +21,8 @@ master_doc = 'index' project = u'pyexcel-xls' 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_xls.yaml b/pyexcel_xls.yaml index 343ad87..3b6ad15 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,12 +1,12 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -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: xls dependencies: - - pyexcel-io>=0.5.0 + - pyexcel-io>=0.5.3 - xlrd - xlwt description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format diff --git a/requirements.txt b/requirements.txt index 3f33157..cc6ba29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -pyexcel-io>=0.5.0 +pyexcel-io>=0.5.3 xlrd xlwt diff --git a/setup.py b/setup.py index da78df6..185d2a9 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.1' +VERSION = '0.5.2' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -18,7 +18,7 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -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 = [ 'xls', @@ -43,7 +43,7 @@ CLASSIFIERS = [ ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.5.0', + 'pyexcel-io>=0.5.3', 'xlrd', 'xlwt', ] @@ -52,11 +52,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-xls v0.5.1 ' + - "Find 0.5.1 in changelog for more details") -here = os.path.abspath(os.path.dirname(__file__)) +GS_COMMAND = ('gs pyexcel-xls 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): @@ -79,17 +83,36 @@ class PublishCommand(Command): def run(self): try: self.status('Removing previous builds...') - rmtree(os.path.join(here, 'dist')) + 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) + 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 = "" @@ -150,7 +173,6 @@ if __name__ == '__main__': include_package_data=True, zip_safe=False, classifiers=CLASSIFIERS, - setup_requires=['gease'], cmdclass={ 'publish': PublishCommand, } From 66aece656837226140691ab73afc9cba176f3f17 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Nov 2017 08:41:34 +0000 Subject: [PATCH 074/163] :umbrella: test complex hidden sheets, #21 --- tests/fixtures/complex_hidden_sheets.xls | Bin 0 -> 6144 bytes tests/test_hidden.py | 10 +++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/complex_hidden_sheets.xls diff --git a/tests/fixtures/complex_hidden_sheets.xls b/tests/fixtures/complex_hidden_sheets.xls new file mode 100644 index 0000000000000000000000000000000000000000..5ad2ca0a42dbaa9817990ddd3af6e9619c04fb78 GIT binary patch literal 6144 zcmeHLU2IfU5T3igw*|Uw`B6deQe~lZF%%+V1X(C37?7r5G=@Z%_O?{EEh!~xR9uRf zXvC-_ni!%X!3X0nG3tX7i%&jiG#V20349~?uo%=}pzHU|xi`J8yJ1&}2GY5iIp@rr zb7sz*Ie+)tZyHV>Ix_u~6v6EhmeE3u!~%Q^`5M1mFA_qYywO6T;Iok(hbzbf7d=}! zhY?I-6v#P`18pGrwO)D!4Qt%g3O&#v1Ner-ku}nfbWk3{Y*!A`5HUejm9z}*7nRh% zRGo4CV;;DauP6`tpZhoW@i4H|`saSn^*;eP5jY802TTBQ1V{t05jYt*1vnKr4R{Uk zTHtlS>A)Gl>wzOqiTZ`7Ui210)LM!CuU9gXl_DwX zT`uXY$V55J^Yt#b-yO_kPwKikEWZ{UXz^jhA)kgR|6FB!daG3Za(wn$s{Yl>KMbEb z9G(ZhpIeL{^2Pk-GW=8-{`@lhnv#4$B&a>SYAK932SQkDIVmu$&xJK@$i*~m%tbVv zoQrEZB^NC`q%pk@>*7r`%f+{TSI=%{Yt3vWv&Ew-lh=mQH&r5Dh)xIYJ2W@G+ZI{a-eziD=e^!EjkO=m6@` z&4stlez#$3`-%sZp99B-Idm&VxCfGBk@?!9Md`5Cor2?Mwn(xq*|fR0&)wm7dNzwZJAvo2Xql~8=A2R zapni*5d=a|9>vWrD34)IgYr1$Iw*&$EnhAn-Vw}cV&05)h!LZC8icwDA&&(_mhv2r z$7u9tn?YB&nbOD>B~xAQTm$F*FkNygVygF^M){c2AZZd0X0ksHlM2GDTj;^|)piU z-R9b2+Eh*92cxv=mZrfdMq-udg8n_Z?~Py1Z`@Y@_Di<3%>D2O`uPbU-9|YL$2wIH z(iiK2d?(xw`(J71Jb~Vy?gz;o4)6HBS&`K z{rE@7Bl|ZfXFqj>j(>gp;LS7Y54;NdQ|I4X4PLZ}w*@?&g6y2g*kN1RT8E$b!wsCXg0KDr6T5Bl=)UCL}iog!ub2} z>fyhib@&U^t#d-o5MDzA;FO1Xo__ABm5!hL^gCXcQCSTQooa)tf1s+fXX!r}e+zUE SdHOF$Qmy}k|6l%Z{eJ=l^D!a- literal 0 HcmV?d00001 diff --git a/tests/test_hidden.py b/tests/test_hidden.py index 76785ca..77b1a71 100644 --- a/tests/test_hidden.py +++ b/tests/test_hidden.py @@ -3,8 +3,16 @@ from nose.tools import eq_ from pyexcel_xls import get_data -def test_hidden_row(): +def test_simple_hidden_sheets(): data = get_data(os.path.join("tests", "fixtures", "hidden.xls"), skip_hidden_row_and_column=True) expected = [[1, 3], [7, 9]] eq_(data['Sheet1'], expected) + + +def test_complex_hidden_sheets(): + data = get_data( + os.path.join("tests", "fixtures", "complex_hidden_sheets.xls"), + skip_hidden_row_and_column=True) + expected = [[1, 3, 5, 7, 9], [31, 33, 35, 37, 39], [61, 63, 65, 67]] + eq_(data['Sheet1'], expected) From 1a4ac9e3296dfddf89def69480009e5faa5e669e Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Nov 2017 22:59:32 +0000 Subject: [PATCH 075/163] :bug: fix xlsx notimplementederror #24 --- .moban.d/README.rst | 2 +- pyexcel_xls/xlsr.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.moban.d/README.rst b/.moban.d/README.rst index bbf4597..19bb3be 100644 --- a/.moban.d/README.rst +++ b/.moban.d/README.rst @@ -6,7 +6,7 @@ {%block description%} **pyexcel-{{file_type}}** is a tiny wrapper library to read, manipulate and write data in {{file_type}} format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. -New flag: `skip_hidden_row_and_column=True` allow you to skip hidden rows and columns. It may slow down its reading performance. +New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. {%endblock%} diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 34988f9..0d915a7 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -161,7 +161,7 @@ class XLSBook(BookReader): xlrd_params['file_contents'] = self._file_content else: raise IOError("No valid file name or file content found.") - if self.__skip_hidden_row_column: + if self.__skip_hidden_row_column and self._file_type == 'xls': xlrd_params['formatting_info'] = True xls_book = xlrd.open_workbook(**xlrd_params) return xls_book From 13ccfa7e0979c8c4f7139abf215f431e1979d6da Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 2 Nov 2017 23:01:02 +0000 Subject: [PATCH 076/163] release 0.5.4 :egg: :ferris_wheel: --- CHANGELOG.rst | 9 +++++++++ README.rst | 2 +- docs/source/conf.py | 4 ++-- pyexcel_xls.yaml | 6 +++--- setup.py | 8 ++++---- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 28b2c54..53620f7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.5.4 - 2.11.2017 +-------------------------------------------------------------------------------- + +Added +******************************************************************************** + +#. `#24 `_, xlsx format cannot + use skip_hidden_row_and_column. please use pyexcel-xlsx instead. + 0.5.3 - 2.11.2017 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index 91906e1..6f3f805 100644 --- a/README.rst +++ b/README.rst @@ -17,7 +17,7 @@ pyexcel-xls - Let you focus on data, instead of xls format **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. -New flag: `skip_hidden_row_and_column=True` allow you to skip hidden rows and columns. It may slow down its reading performance. +New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. Known constraints diff --git a/docs/source/conf.py b/docs/source/conf.py index e1b451b..2e15ac4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,8 +21,8 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.5.3' -release = '0.5.3' +version = '0.5.4' +release = '0.5.4' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index 3fd1e72..a2cb0c9 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.5.3 -current_version: 0.5.3 -release: 0.5.3 +version: 0.5.4 +current_version: 0.5.4 +release: 0.5.4 file_type: xls dependencies: - pyexcel-io>=0.5.3 diff --git a/setup.py b/setup.py index b95174a..4d39762 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.3' +VERSION = '0.5.4' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -18,7 +18,7 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -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 = [ 'xls', @@ -55,8 +55,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-xls v0.5.3 ' + - "Find 0.5.3 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls 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 4cea637cce16da531bcb49594d6764c59a809070 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 8 Dec 2017 22:44:34 +0000 Subject: [PATCH 077/163] :sparkles: detect merged cells, resolve #25 --- .moban.d/README.rst | 2 ++ CHANGELOG.rst | 9 +++++++ README.rst | 2 ++ pyexcel_xls.yaml | 4 +-- pyexcel_xls/xlsr.py | 37 +++++++++++++++++++++++++-- setup.py | 2 +- tests/fixtures/merged-cell-sheet.xls | Bin 0 -> 23552 bytes tests/test_merged_cells.py | 11 ++++++++ 8 files changed, 62 insertions(+), 5 deletions(-) create mode 100755 tests/fixtures/merged-cell-sheet.xls create mode 100644 tests/test_merged_cells.py diff --git a/.moban.d/README.rst b/.moban.d/README.rst index 19bb3be..f6090f3 100644 --- a/.moban.d/README.rst +++ b/.moban.d/README.rst @@ -6,6 +6,8 @@ {%block description%} **pyexcel-{{file_type}}** is a tiny wrapper library to read, manipulate and write data in {{file_type}} format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. +:fire: New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. + New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. {%endblock%} diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 53620f7..5099414 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.5.5 - unreleased +-------------------------------------------------------------------------------- + +Added +******************************************************************************** + +#. `#25 `_, detect merged + cell in .xls + 0.5.4 - 2.11.2017 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index 6f3f805..d63eb77 100644 --- a/README.rst +++ b/README.rst @@ -17,6 +17,8 @@ pyexcel-xls - Let you focus on data, instead of xls format **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. +:fire: New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. + New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index a2cb0c9..9db61aa 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.5.4 -current_version: 0.5.4 +version: 0.5.5 +current_version: 0.5.5 release: 0.5.4 file_type: xls dependencies: diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 0d915a7..94bdd3f 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -12,7 +12,7 @@ import xlrd from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader -from pyexcel_io._compact import OrderedDict +from pyexcel_io._compact import OrderedDict, irange from pyexcel_io.service import has_no_digits_in_float @@ -23,6 +23,21 @@ XLS_KEYWORDS = [ ] +class MergedCell(object): + def __init__(self, row_low, row_high, column_low, column_high): + self.__rl = row_low + self.__rh = row_high + self.__cl = column_low + self.__ch = column_high + self.value = None + + def register_cells(self, registry): + for rowx in irange(self.__rl, self.__rh): + for colx in irange(self.__cl, self.__ch): + key = "%s-%s" % (rowx, colx) + registry[key] = self + + class XLSheet(SheetReader): """ xls, xlsx, xlsm sheet reader @@ -34,6 +49,11 @@ class XLSheet(SheetReader): self.__auto_detect_int = auto_detect_int self.__hidden_cols = [] self.__hidden_rows = [] + self.__merged_cells = {} + if keywords.get('detect_merged_cells') is True: + for merged_cell_ranges in sheet.merged_cells: + merged_cells = MergedCell(*merged_cell_ranges) + merged_cells.register_cells(self.__merged_cells) if keywords.get('skip_hidden_row_and_column') is True: for col_index, info in self._native_sheet.colinfo_map.items(): if info.hidden == 1: @@ -62,14 +82,23 @@ class XLSheet(SheetReader): """ Random access to the xls cells """ - row, column = self._offset_hidden_indices(row, column) + if self._keywords.get('skip_hidden_row_and_column') is True: + row, column = self._offset_hidden_indices(row, column) cell_type = self._native_sheet.cell_type(row, column) value = self._native_sheet.cell_value(row, column) + if cell_type == xlrd.XL_CELL_DATE: value = xldate_to_python_date(value) elif cell_type == xlrd.XL_CELL_NUMBER and self.__auto_detect_int: if has_no_digits_in_float(value): value = int(value) + if self.__merged_cells: + merged_cell = self.__merged_cells.get("%s-%s" % (row, column)) + if merged_cell: + if merged_cell.value: + value = merged_cell.value + else: + merged_cell.value = value return value def _offset_hidden_indices(self, row, column): @@ -97,6 +126,7 @@ class XLSBook(BookReader): self._file_content = None self.__skip_hidden_sheets = True self.__skip_hidden_row_column = True + self.__detect_merged_cells = False def open(self, file_name, **keywords): self.__parse_keywords(**keywords) @@ -115,6 +145,7 @@ class XLSBook(BookReader): self.__skip_hidden_sheets = keywords.get('skip_hidden_sheets', True) self.__skip_hidden_row_column = keywords.get( 'skip_hidden_row_and_column', True) + self.__detect_merged_cells = keywords.get('detect_merged_cells', False) def close(self): if self._native_book: @@ -163,6 +194,8 @@ class XLSBook(BookReader): raise IOError("No valid file name or file content found.") if self.__skip_hidden_row_column and self._file_type == 'xls': xlrd_params['formatting_info'] = True + if self.__detect_merged_cells: + xlrd_params['formatting_info'] = True xls_book = xlrd.open_workbook(**xlrd_params) return xls_book diff --git a/setup.py b/setup.py index 4d39762..e6c4168 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.4' +VERSION = '0.5.5' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( diff --git a/tests/fixtures/merged-cell-sheet.xls b/tests/fixtures/merged-cell-sheet.xls new file mode 100755 index 0000000000000000000000000000000000000000..c5754b896fcd7298261410fef0adb2a4ddd804a7 GIT binary patch literal 23552 zcmeHP36LE{8UAPXz1>+tj?J+NIW{kwV{;$7NeJY4D>t$+ApwEnNJ4mELx_kQVZ-3M9>W+Jdzb1jONNVKcLcP>#bPLZ@z4QP)SIMuAdvMe|APDN7Y`3d& z*Qjf=y7t4>l802CJ&H0*2FqTQcjS7SyL{&`+uC^Q@+F@KeXV85Jb9E&_VJw>K~F`{ z_o7WE9JZ?=qFsX{=nEp~i;Q$jvIhAn&uk-IKsV{xlKP192N=uSGSo=7(2rq#QV;cp z@(+Ms*x;9^DK!kXKS-o`XY<&pW5>>%kB8HysmG?&DEP-=THdM4a%Y{c7if|?m};r= z^qG2nq?%G=A!3uiL;yt8WlMa^gh0*V=*uB+I^*0% zPMUw(#NzX5lbTYaq3_{(u2Pn-NCp}oQ7S?{8U~Vt84r+5po||$6?_%mfZ?A7c*#=O zl_8z(LDB!=WyI4ttWD*k=tMP@|6itCqUqUo^@%r+s|OBGhSbeU|6%%F5%ix%(C?0* zZ;zng6G6W-g8qXD`o;))lsr-R_bVKXm4JSJ7(sXC372=}3Da+jz_~Yq{(z#V;aip6 z{!8^1E^a?^CTX(gI*EXCt!ue{@@_wnfUWqJmW{X_J?ctpj3eq1{_AVhcVgd<+b z`GTwxSyYlI4X0>oR~nw#M2BE5eQQI*4SjCtBdKjlKMf^%XXoRiA0I8LhZG&}7`J>t z{(%v6j+CODEAa@Y=#7^tMtRbB37F&z_xmrEJYo8GBj}Gr(5tnd2NlkNUb{-;{SHO% z=h2~0S8uL9`)YJo&w+8;+tAS1rxE(UN#US4d^fb}xf=MH%bdY-84a!!vU0)Ow{Puo zrb(BN&H}ddh5xU?6W;;qMS+)VKg<*Ca0M2rssi5!RaKxMRaHn;TY;{&Dh?d$RaK~~ zwgNk)Dh_lTRaKyWsHy@TO;r_W=~Y#rsaI8jW2UMKbXrwaz?`(Y3T@R^;I2YdB5{kN zstV23Rv7E6!11R$0jtaTQow7BLy?-2*9cayouWJ8z{H#$v-V6T3^KkFkU};dWI`n% zt!;jgpc8BXNLj<7=7dGZ@}t;(dN;gR3%bJW6xz>>r{4K>A-eq&eIUJ3YX&Ji9S4GC zjV4KNE<%#R+r643n*-gs03da$J1KQGdr5>O`R|uN>WWR=uwg?1y{iJdod7zmUZWvP zg#!$76@wmOwlk&{gX((`l8fJ2)_BLJW6c z(yq`~ej5n4Vj+sTM#ENwrZe8aEEMvgR@`^reIcXKXWK=K{&AftRB zNSJjJ4>GqB5bU#~ShSsRp;v)U;z6(*`N<&pj(8C4M`|EQm~|2la&RRe^geMq;i9+# zoy3D+1NM_a@*VLY*ay%+kTB~c9%No6ApH0crxR{aRG^c15NsEGGDyB79wg%fLBgz) zc#uOX0pW&yoKCn|QGrh4L9l83$sqZTc#ttZ5G2ex@q+~4g$CSCB=%>0Iajy)T>j4vgp9X5c#^mM<5gMZUGU z&bQxv#msk5Jm1*{zLR75x^oJp=ek_y>wox*neX6uzHlk42G@9$>5 zL*n_)HSleXb@WzQM#jjK_%=hn9G z-M`!AOXrMG^3S8<`I_u`Tr6MRo?F}YY};z)+Z4~&WX}_0`RexE+VEv$HenB+4JmJzPdfPwtevUbtb+k zY3@!JdYqAP|FF1Xu+r&5jePTx+GQ`CL(&$zUdCeLV%4p^@x~r!iobA8|AH;d;oL^e zEwFYTeQcMqU2BWoSH@w9uIjq;mxY1)0}3fspSc_hK@7VNx~anwc**6Dp%FwJUq+x@9F2bB$l@o!;Zn?${M>u&faUOZJ`ad5$!4qp|)y6coM>)~MCb&AfK`@0@%ZUPrs*W(K+jOOTb=dbK>j`la8<{*P&DY z;ZUF|TaTGGB;B#`hHvyZ>--h$M!+(MYg$fss9{ zOKq|H%XBEg+O_tLH771V{P+cHdz^~{QVa#Za=tDLw<47W(Uj6F!;^*kkF`pJl*LVX zvbZTv7B@v%W>A(tUH$ClmX%lKrmpF6xad%tQWwjf1AgUv&w{+h7JI)h^owENx$(;< zxF~@EVE4fQ@N#tw$mv;7e|QAQ^6}Q4t3ADB1F{T*EaiO9eNdKCztDb2;Kr|OKds$0 zu#6@@RJsNN9lm_=lG= zi&M<_2Z!!*FC$2l0dYQU+BWsQU%Vvc7g%B1l<%kx9M_~=#gyz_~( z<+=}!5Bswrz+sN=Lv(*eN8s~kB$WM`o6>ypq*s@uQr%PlVa?2$;KwBeg zL7RoaxKbTqz7p!apC6{M)4Y6bF1LObDTi>jwgGdSmUGw}mTU)Y zyGEl7n?T#7(Fnjp8Satw0lp*aeeA)^R)OC@p20VyyYMxvFS{4-VjJ4*ubvxl<=G!c zKD_s{!*zoz>L2q;2t1_Vib7?!=h36?P85H6j2e? z1>*7zTXRI56}r0iDjkP$_QkP4Hqf&??~WzHr?fy%2j~;_l1jFhiH2UX-ClCb(2N*9 z)BboFqb2E&&!<1!?n|!!z!IPdGHI$@%QSLH}8Lc$=U&TY<6Ty%l$9meJZyg zamPevSwxE7IT8@myCWN{PXAVh5ZC@=dH`1mF~vyS>v8SbVuo$2DU zS6{g9qII3?Ge=&!I(M$(*~W@(Lkbs zL<5Ni5)C98NHmaWAklzX199tr`^D#8?43Shz?K`Z{-65(-CY0gLgc!g>;GdAc?N$e zB7gkI^*`6_D-pTg=RN?p{Vzb|KES1j+!xq^$lX@%1Gww+)o?j z$JX*=n;eLO1m}hV3qNw(?)UEftE%hr0xb!N1`-V<8b~ydXdux*qJcyMi3So4BpOIG zkZ9olOaolUbGgj5F~8;WckVn<#icXX`TU(K58ZKn&$T<(@jPP2BU)VRHz4wxKiB)- zu{f^zxi2sbk-xp>Z;kmsg8A Date: Fri, 8 Dec 2017 22:44:57 +0000 Subject: [PATCH 078/163] :handshake: synchronize with pyexcel-commons --- docs/source/conf.py | 4 +--- tests/test_formatters.py | 32 ++++++++++++++++++-------------- tests/test_stringio.py | 6 ++++-- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 2e15ac4..b485710 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -10,11 +10,9 @@ 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' @@ -22,7 +20,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' version = '0.5.4' -release = '0.5.4' +release = '0.5.5' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 109c2f8..76b8f87 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -1,6 +1,6 @@ import os -from unittest import TestCase from textwrap import dedent +from nose.tools import eq_ import pyexcel as pe @@ -10,7 +10,7 @@ class TestDateFormat: """ date time 25/12/14 11:11:11 - 25/12/14 12:11:11 + 25/12/14 12:12:12 01/01/15 13:13:13 0.0 0.0 """ @@ -18,8 +18,8 @@ class TestDateFormat: r = pe.get_sheet(file_name=os.path.join("tests", "fixtures", "date_field.xls"), library='pyexcel-xls') - assert isinstance(r[1, 0], datetime.date) is True - assert r[1, 0].strftime("%d/%m/%y") == "25/12/14" + assert isinstance(r[1, 0], datetime.date) + eq_(r[1, 0].strftime("%d/%m/%y"), "25/12/14") assert isinstance(r[1, 1], datetime.time) is True assert r[1, 1].strftime("%H:%M:%S") == "11:11:11" assert r[4, 0].strftime("%d/%m/%Y") == "01/01/1900" @@ -42,47 +42,51 @@ class TestDateFormat: os.unlink(excel_filename) -class TestAutoDetectInt(TestCase): +class TestAutoDetectInt: def setUp(self): self.content = [[1, 2, 3.1]] self.test_file = "test_auto_detect_init.xls" - 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-xls") 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-xls") 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-xls") 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-xls") 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 11d532a..8e9a1a1 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="xls", file_content=content) + r = pyexcel.get_sheet(file_type="xls", file_content=content, + library="pyexcel-xls") 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="xls", array=data) - r = pyexcel.get_sheet(file_type="xls", file_content=io.getvalue()) + r = pyexcel.get_sheet(file_type="xls", file_content=io.getvalue(), + library="pyexcel-xls") result = [1, 2, 3, 4, 5, 6] actual = list(r.enumerate()) eq_(result, actual) From 3ec21dd7370591a62d7c91a6cbf4d5511a0f5456 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 8 Dec 2017 23:17:21 +0000 Subject: [PATCH 079/163] :microscope: more test cases, related to #25 --- tests/fixtures/complex-merged-cells-sheet.xls | Bin 0 -> 24064 bytes tests/test_merged_cells.py | 31 ++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100755 tests/fixtures/complex-merged-cells-sheet.xls diff --git a/tests/fixtures/complex-merged-cells-sheet.xls b/tests/fixtures/complex-merged-cells-sheet.xls new file mode 100755 index 0000000000000000000000000000000000000000..d576c46b001d47e01dfb62b4239d4e820f28cade GIT binary patch literal 24064 zcmeHP3y>7W8UAN(_jVTKaR(fTa4g6BI1ui5DUZGQHXeeYQA-6B_rR#ZQna+<>6ye> z27Da^2wb8@sl;eBf<~< zsd{~ZG>~@CkhMu!)B0@ciEc}3(crI%Ek8>g6>1I{D=Z500J(1VP!;>~@v! z26b;z_kp-u@{lU?vZBnCp|TJ89l4q2F5f=FwlNPZiz953W$Vj&&YmlGv%repibd#PfNk`=GXUuQQa3kG9JBIa1J){l! z9{@dnwO^jb#0c2_5Rs;xP2*a|jhitaFK13uuZ@Y(@Q)+3v@@3F&OJ-d&?qUGYO(P2 z8G3od8WZCnVxvDt07Ye+E6vg>vN8ko=8R&$GBdvrEyz8})fZ1W5n=LV&BU5Fj#?;GO2_nkJM9@vV2)G(D)(6EaanMAWE1C0LcXM_>ok`SK$qK{VNYIS-kdU zNT+*H^nZE@@pN`;Q~oGAQBC>(m+6*hdbVACV&rl4!0yQ_ajVjQnEulU`cES0_eRin zM9}Yxpx+Zg|9%90Lj*lao+$j?3I}~9pr0Q^&|P`L`CWO!^gAPP?vJ29py)~XR%N&U zR;`7b+m4(`n(R5{(Vv&4cpc;Acl`AJ9z9*6XYe{GL=W^w6b$IcwUd4!x@#xw@k-9; z{($`T z5p?#Hf}E@H3a9Axm#Id1k{AR`a)#S|kCG=$|4sz`kqCOF_Vb{^ImoM5vA^G~=mR}E z^y%u&)#m_>?&>+vPkZa?8u~Xt|JxM~vcq>ntDdWYpSjW*Dp%6ridR-Hdi$=;UCuP= z^3j>WmI3hpHF)C~pau#It^+You)_tIrJ@2H4=O4^K`JVcsI&lGZABc|*DETJsfPJQ-0(4px6~LUdvI1?D7MNOT0d7N7REMTY z3ykv>VE@ydfYs%EDd086BTG%uYXl3}PQjh9V`5H^S$ifE2ANO}NIn}6GO-+x);2## z&V!qd@}p3HdN+)#d0k<40`+IYQ}6ydA6@^+K9F9iHG|}zjswB6Mw6sB z7a>Xh?OsiiTLR6w03a#VoRm77y(~hKzV8)5QiUpBef8COw640?>;%whX^n;?b@emQ zx}2a;^O08&QX$N*n}pJ}^51DH z*c-7f)odUnl*cUJZ51^YuG#cr&1nC;j3&Kv=guOCX9K!wJ!U$se02vq<_w78c1+q8 z+RASO;aV(2Hn)9Pi_mn&>zMg`U#J$lcI^rojZX7wK^m~tZx%frO-^j%y^> zsY@4@q@f&;zK(d1Q9ckvOw|cG|6uQ#T@HwF!#HLv<07aGoy3C-F9)QrBOYY54+Igj zPU1o4lmmi&c4UjT6E5`1&`CT9b|XI>q^~0$1pAR12qI>k#DmN&2ZY`yPA6Oxm!Xq* z5NyDHI!IqfJP7syG!R70I*A9FR}Kh2KE&yS8x&>eBpw9Y1)mPm*AWkr@qr*>)=50b zVda2u!#++Y+^i@=C-ETIH2!puzK(d1u|5z)%sTOd1jq43C{~(ahlY$z_E_v*3>2$X zX2=A|;Hzv#4qsWb@w(ipXY_8n_!}AQz4tgv5Ga6qS&7E{Kzu`pF2UMca*(7Fxz2rW zzL!t(oy;+hn84i)@~w;K+iKw36w8+@$O7MFu5e2mFs-{kAF4u9U9Mfwt?^TSibJKt@t{*&X?c$hnerN zc)oKCd|PArx?`i_o6dE9{Fj%^d>hDjR*ZFq?RgCN#+4|xZ=$c`;l9_+e22&LHQDpH zSiZVF_jSDa@Iz+4BjWj*?0HfwU)`SjI)4B9qh`Jb$MZGW^VC?rx;^)G^zD7w%y(ow zUz0r_8p~I==e~}IUU|#R_mFtLCVOs+<*VCsU&lu;JYeQKihSo(WX~D!jVn>I=hn9G z?tanbOXrNM=$}W&^EKJ?_*lNWJ-4>Kyk)bQZ(}@PlRZz4<*VCsYul4A?lAKm6VKOV z&n>Zhb$f1YyZ^SQ&3rTQd`d#y=C~pf>IJZ%A z3#^^T9N(pE*V<$cknvcetFrF=WnrNF;Cw=rXDa(b5W`MEHz_QEmt6B0DnY~vB}7_& z5V5X^=vsLMVm|w$$2mP9;=~dnZ90fpUqp26Hv-Y^z_vo1R6?Y+9vZ0ikRl>2Gpsqx z%2F~J6F2Lfvw9rb9h<_vEbEZGCGVW&d5$Evgs?wKsrb%K)Pm=L+PVcT9B4F4&}j2k zJb8VQwSPjG!dFGG?m9ipdL&qPovyRy{;tQGo4^IuX?#J2(Hwih{8c^9vHl9w91Q+U z;r5MErp~`sYj6uo$x`#zLbVB*+MPg^M*1O>2|!M|!CFBbF;`1>3b`_YTq%gkTxYnh zZL$Z+bSS~vyY`JWrz}76qy=kxoJ#{z3J8# z+?Xee8>1|TQkFko|I96uR$Z5CS<~Zi(V;Y@Zk9b8{7UJb1$mV%wEh6-7u~*d!9957Qzi-1C$f|FAGVhvp#u%n-gl z9E-faSkG^;D?yv*@-e~e9!XyP%l1u6+Q2K;%vI< z!;`}PY#4BuqWcitpV1Nc{22))f9A$?AHq|eZVz+QI9*ua^3NIg4^{kgKK^-pQuFG; z?`}T+mHX4QEF}N8E_mja9%qGLk9I%sXA1YSJ%7#*A)d?RM~qT+-I!NhH|AB>jos*+ zCO2v=bu-$l4u2T%JTa4Jba-Li&7h=n1Dc&xVbx1Ac=m2evtOac* zI^!yJg!x*icQ-#wVW)Zd+FWk^Oj6dc%XySmQr>4L@hENEoe{EKlgk}o-OnX=;CT2Q zS{lo3guDI<{+_TL1d$i!+42$0-MjKosUxeM1_X~L(olG{WeYI3Xemd$VaX2Ac4#!p zuo1M48jS!vl;Iv(AM87_-rpX|WOcE~uka0N6I|HPC-s^DZ*&jzfy6e5) zEk0*ycBP_o3L-eP%KJAIrCY1h1h{ySfz~xhc_Kkx!w|lya(_$RCn9&Jy57uA(%vT* zQQpc<(cW*DCWVN}6aErHEwriYxvckGFTKu01Z0f37O1vm;wg{<8EqcBLv0+wCG;)I=8 ztqRKyVAW$8<6@0(r`!|UVGWR_20W+(rq`(QlT~_KJElr1J&APIxJDt0%mw~Ih*1-+ zq)cT?k$W>z8KY(w0h`E)0&+_`InM&}9`p;&vR#A{3fq=>W&?%C;a!wcu2N369&;Y1 za#E-MTyD-iIIT!K2&YlQFXDsfE~t1TyyA({AuHqmi5BXwArJMo`zx}ovLCpvmvP{Qj+SO zPyVs&yC~Tp{L;0?8IFLL!Uea(`B=?SwDu^U<@QXk$QAI)UmSnM3VMFZd!|3Lzw&f| zHf1ZTXnTohXl2`NWjBxO+2r$Wk2I!YU+nh40{=6PA0^cvnD!{~tG*pj4Sa(2ZmpU; z`q{Eay?X7f`#)H+cJSS|I5Kt8?w4kOb{hiyCezyyIKUi-K-YH~LOsG-1fFf}M&Oav zjR->!u<@sS>W?wzHR7FR)Q<}BG{xy27oWHK;&qp->s+5X`tsGe3lz`p728K#anW;D zJJP$iU3dfEIgD1Xss^eWsA{09fvN_o8mMZZs)4Eosv4+jpsInY2C5n`Yanj@Z@=*D z3%%118N6vL*8eRZ+{^X*xy-dOzvc5>6VF(2 z>CAOL&qVP66W8}#yK^1SBZfRw#Allz3&~1w=E35O94%kN z^I{x8uH Date: Fri, 8 Dec 2017 23:22:59 +0000 Subject: [PATCH 080/163] :bug: fix python 3 unit test failure --- tests/test_merged_cells.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test_merged_cells.py b/tests/test_merged_cells.py index 8263c7c..44fe8f2 100644 --- a/tests/test_merged_cells.py +++ b/tests/test_merged_cells.py @@ -34,9 +34,8 @@ def test_merged_cell_class(): test_dict = {} merged_cell = MergedCell(1, 4, 1, 4) merged_cell.register_cells(test_dict) - keys = list(test_dict.keys()) - expected = ['2-2', '2-3', '2-1', '1-1', - '1-3', '1-2', '3-3', '3-2', - '3-1'] + keys = sorted(list(test_dict.keys())) + expected = ['1-1', '1-2', '1-3', '2-1', + '2-2', '2-3', '3-1', '3-2', '3-3'] eq_(keys, expected) eq_(merged_cell, test_dict['3-1']) From 10a6530a9c42b99250551c0d4ec5311cd7d02863 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 8 Dec 2017 23:25:58 +0000 Subject: [PATCH 081/163] :egg: :ferris_wheel: release #25 in 0.5.5 --- .moban.d/README.rst | 2 +- CHANGELOG.rst | 2 +- README.rst | 2 +- docs/source/conf.py | 2 +- pyexcel_xls.yaml | 2 +- setup.py | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.moban.d/README.rst b/.moban.d/README.rst index f6090f3..e176dd4 100644 --- a/.moban.d/README.rst +++ b/.moban.d/README.rst @@ -6,7 +6,7 @@ {%block description%} **pyexcel-{{file_type}}** is a tiny wrapper library to read, manipulate and write data in {{file_type}} format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. -:fire: New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. +New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5099414..1e0b5e8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.5.5 - unreleased +0.5.5 - 8.11.2017 -------------------------------------------------------------------------------- Added diff --git a/README.rst b/README.rst index d63eb77..786673f 100644 --- a/README.rst +++ b/README.rst @@ -17,7 +17,7 @@ pyexcel-xls - Let you focus on data, instead of xls format **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. -:fire: New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. +New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. diff --git a/docs/source/conf.py b/docs/source/conf.py index b485710..34d645b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -19,7 +19,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2017 Onni Software Ltd.' -version = '0.5.4' +version = '0.5.5' release = '0.5.5' exclude_patterns = [] pygments_style = 'sphinx' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index 9db61aa..c8c1660 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -3,7 +3,7 @@ name: "pyexcel-xls" nick_name: xls version: 0.5.5 current_version: 0.5.5 -release: 0.5.4 +release: 0.5.5 file_type: xls dependencies: - pyexcel-io>=0.5.3 diff --git a/setup.py b/setup.py index e6c4168..7948f6b 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ DESCRIPTION = ( '' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -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 = [ 'xls', @@ -55,8 +55,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-xls v0.5.4 ' + - "Find 0.5.4 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls 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 ba793b104f5db19eb8ea389e3eb3899aa65bd8a2 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 18 Dec 2017 22:22:15 +0000 Subject: [PATCH 082/163] :microscope: more test cases on merge cells --- tests/fixtures/merged-sheet-exploration.xls | Bin 0 -> 24064 bytes tests/test_merged_cells.py | 52 ++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100755 tests/fixtures/merged-sheet-exploration.xls diff --git a/tests/fixtures/merged-sheet-exploration.xls b/tests/fixtures/merged-sheet-exploration.xls new file mode 100755 index 0000000000000000000000000000000000000000..ef359ab5adcc3ddb1d7cfe9f36e38e7f8162b03e GIT binary patch literal 24064 zcmeHP3y>7W8UAN)A9Em&<8dI!-Ezm91K|z<1#XFN;}K9aYN3MS9%s~G5G|~DaxpQM z0UsO$ja;Hesl;e}8?<5+DwbBPHAzJ&qM?i?YD|%6BuS~1y7|7Io!y?9o^dy^tTJwI z^=!}I-QWNB-+%wp-P60j{Y~8~w?8oIRq=&(sgaNJwUX567Shw)`@w?ze4e-NcMH-W zRl{dU1GP3fGMSK7tcnhqgSfJHNAFg$Bu##?wx(-#>`&8M-)pdakk<(+>$S+TPWXxQZYvF#ON?oU} zP3k%jS4(!NIxi{8Oc^G7!PAx-Y3}mvQ88=7vZaeZ4SJVl$y|AyP4@6@38BYB=zGy7 z6As%|7t*d_A@unn^mZfNl8ixq$}`JI7tl?5wxl+sd_QCPn2a#eE%akhpVULGq5Q+3 z=hu7XX^4-6?GF`c+TPUM(%d{_9uj9xQ^|(-82HDLTHdmgv*(?q7if?aOtn~f`V753 z?i%9F5V65q!iS=Y&5 zq(b`4$qn&F=zEl&tCZy_l7_}d7mJXOhJjncj0Z^CSH_E^3cdnw!0_)pyks%#Op{Lc zpy>Z{GotAn)~51dbfTKd|3A|$(exa1^ob{rqX!O8hWM>Y|3UgsL+C#Vq2C)q-xfl@ zFNA(i2>tsZ^bH~OFnPl8A5u6ND?a`FAcXG76D;q@6Qti6g7ZKK{b5B1skCTX(gluLg>mLS>ambbn1{w}??L{B3*C_wj(M^yCb$FY-s0lH%+9Pvud7vvm~ z_M$uqI7L&t67b9>Is|j*Tk7g=>VH#ziEmZ#VGuHtyVThRx)bm-I3 zo1@PG8r{*eZ=Ckk)z$Z}hyHI-I4BO^4XwJa27cxWdzf57gDZxNT)gkDE#3As>GsfB zASMIg|7(!qGeA8k@NgZ7c|t5$fki5+z~@0l6(~qW72=gvpsTHj1IKzr6;hQ}V5d~X zfo`Ls3iJ;ZRiLA(r~)m$q6#$iiYjo-R8)aZtD*{+lU7!ttF_KRB44~ zPX&%Y-3eIT_7{9!V;qXq6upMOLd-6>6Anzw=`m|hr-LBl%K^z}qCqB<1Jc^&1@Sw< zi2x~SIMAG+=vaOf+E4F>=W1S8SS*hAGvn#Ef1M9+|0EAcpCrv7`Dda)u&mJ}>C1*l zlHb>-NwUe;o$~>bQr$_ZGnvamB*}fR2$Cu^asB%BdGxLd>~;d^v|5dZEEW10Xx+A7 zsCg)>3zabowSWKqfKZuCCLokfbA=+UAd|R4>9n9w+%7B$b)Y*$-6o-Qt^9AA@{dNW zOEnt^2<0-%_gFm(XvPB|d-K2bX1qPPs5M1x=h z_Txcv9nm1z2hc!pW7bJD$lP*3`0^o2C)}VYLnqN7*e>{ZkX%PJNZJE}8?#QLK@Kkm zgd6rzI^kwT89Ipu!KU%YgXB7*LB@JOaAVeq7sUS@Z%4J#1UvA^*c=;+-HU-@waN?` zFKN7$P0JC>Yc^h!J#AUv&1A-o1#Z^=QDif23bzVS{z z!8Dm;9x3w)E=&VBE^ zZ00*On(r(F-zkxNojHZlb1K{U+8_UB<~uB!?_mbM(4&Y(Rvf^SrfV*kc-9gpT-GxHr0&DUhl&5?X{ zd(L&d@#qdS-;vRLP4+x7lCN&hxsKnz_PCkv!O?t8_B=I`uWrw|j@-_d%zQ^h^EKJ? zp^QnQuCpugRWgMDo?`xwWnLxxHq-W25<+?0HrsU)`Qt+YUT=gNbikntBrX zUi%QZe^^{0ScycwMy|XpdGZSvkhD2gE6td=SgEd?Z|=3HdJESK%EyE`oZG0m1=h}u zCv+>@wKm5F$T%#~Rb6NPvcOk=a6Yc;GnZq*j}c2jHz_QE7k}dyXao_*mk??Be#E*W zqGRPDi22Nqp5*j^h!aYPv}r%$kRqaEzafau0FEidi6ul@>!H3@4=p0nGJ~4KtSlvy zFmbcqI;+>F-LWg2U|FN{mb`VA>p2qK62kr{rDB?!s0Ggfwe<*k*w<;6pws4_{nWKZ z*4_zW3U3v`y8DbE>rr6ceTL4O`@1e{ZUPrr*WwK-jOMrt=dI|qkMlO5=3ww=4!3WV zGIjn*t-~!WB}?6(glgk5wI_}yjq*Y!;((lZopm;K#8NFiDU?e4N~ItwOD%&BhXPgE zTFkT|>FpbC`g*Uu+FK!34_M}KP0Q&H70iuIx5eCOR4t~|%;e6NBX#M{_T<%i?l#8; z$#f{e+S&E`s#BL9b<+HW3-cZRSp)xJihtI_KaW>xZaeti z&BMQPe_AUG$p6g?pWW1JpY7FStRMI@hkMzsKj(`O*Jbi0Mya{Zo!eaJ&TX!9cfEbO zT(9-ijp(mBd``im@Lai2va(dx%H=Ax2zTen`EsdTge{vTNL?nYky|R!0op3*0&OM+ z;|g_z`D&>5A-^PYt-#!>uKel{u*E_#k zbncSOaz*D9L~v-8*Q*qzM{Cn~xOkC));Ex|D^6a+5x=QQe@k5_pme7SZ)7HF=}ASD zH#3v9^zG855HWeeCoa@Nn+nfo-0!v0XHP&x!H_VY?o@?SAq5J?c;v&;lk>j8jydO? zV6{%iT7!f%-uP*3yPwAQTYegK;ivHhiJ!(71b!NyRDK#8=%;amRHt1TW541+9^yYT zPpH#d7Vg|nLRf;WVhLGj#geLD+TkXXSS*mv6lHf(l-Nm8PA5g_oD^kpQk0}!_Tb?0 z@qm9A{WcJGsDIjHL*!>D1-9y{P9@3)*zX2U-}RF*u)-SWS2gs8NF`s#Su`r1fsTgk zMBYZ@>xJ)7R@oyE6;WMa(0tO@99`aMV2k$Pq5cO^d zaz_KEdV$g4r?FG~G}@7$MvL;(Xj^_7txTus7Hungb*$H9xh%`gYTEYTg|z+}7>#TD z?J$;T+uj2sdk=Nj6>PUf*>A;m%Vs%tn@G5J%Vu$^LGhBGoZWI5+ftwcEJL_tFvu8a<%DZpuKjeKf~L6Uy!cc1ItaRCbqA{+9e{lf#t#lC$ek z-4waF9+jy*u-#`-<2>OGspCbJ9V$Coh#Urh;}Q9QIvsHc zVizLMw)P7xg4z6tC9miO=F`hO=P*X>;YACJi2U@Sr8k6*d|=bC*5BG>!e z2jFX;ixIgGunv*?0=FY_bCvr5&bob|st;1=cLRV~mU|D*tF2P9wUlg=gHVv*+)!ZQ z$L`$o?gM{Ubsb)yRYO$+RSi@%P}M+H162)FHBi++RRdKGR5ei5Kve^uGYxPZ&*d`L z#(bC06Fxj$!KE|T`8tI2N%9u^Ey1NLP-_`KRXy9ZV zE9SxCv>YQ}#rGN Date: Thu, 15 Mar 2018 09:44:45 +0000 Subject: [PATCH 083/163] :bug: give a graceful exception instead of stack trace. fix https://github.com/pyexcel/pyexcel/issues/120 --- pyexcel_xls/xlsw.py | 7 +++++++ tests/test_bug_fixes.py | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 7af5cb5..28ab8e8 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -18,6 +18,7 @@ from pyexcel_io.sheet import SheetWriter DEFAULT_DATE_FORMAT = "DD/MM/YY" DEFAULT_TIME_FORMAT = "HH:MM:SS" DEFAULT_DATETIME_FORMAT = "%s %s" % (DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT) +EMPTY_SHEET_NOT_ALLOWED = "xlwt does not support a book without any sheets" class XLSheetWriter(SheetWriter): @@ -76,6 +77,12 @@ class XLSWriter(BookWriter): self.work_book = Workbook(style_compression=style_compression, encoding=encoding) + def write(self, incoming_dict): + if incoming_dict: + BookWriter.write(self, incoming_dict) + else: + raise NotImplementedError(EMPTY_SHEET_NOT_ALLOWED) + def create_sheet(self, name): return XLSheetWriter(self.work_book, None, name) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 6d43b46..fc6f38c 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -7,6 +7,7 @@ import os import pyexcel as pe from pyexcel_xls import save_data +from pyexcel_xls.xlsw import XLSWriter as Writer from _compact import OrderedDict from nose.tools import eq_, raises from nose import SkipTest @@ -90,5 +91,14 @@ def test_issue_20(): pe.get_book(url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls"); # flake8: noqa +@raises(NotImplementedError) +def test_empty_book_pyexcel_issue_120(): + """ + https://github.com/pyexcel/pyexcel/issues/120 + """ + writer = Writer() + writer.write({}) + + def get_fixture(file_name): return os.path.join("tests", "fixtures", file_name) From b6ee3d0153d908c19451fb7fb4a179f7dd750267 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 15 Mar 2018 09:45:08 +0000 Subject: [PATCH 084/163] :handshake: sync with latest pyexcel-commons --- .gitignore | 1 - README.rst | 4 +++- docs/source/conf.py | 4 ++-- pyexcel_xls.yaml | 4 ++-- setup.py | 19 ++++++++++++------- 5 files changed, 19 insertions(+), 13 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/README.rst b/README.rst index 786673f..3dd263c 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ pyexcel-xls - Let you focus on data, instead of xls 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-xls.svg?branch=master +.. image:: https://travis-ci.org/pyexcel/pyexcel-xls.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-xls .. image:: https://codecov.io/gh/pyexcel/pyexcel-xls/branch/master/graph/badge.svg @@ -57,6 +57,8 @@ If you are an individual, you are welcome to support me too on patreon and for h you feel like. As a patreon, 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 34d645b..e6f6fda 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,9 +18,9 @@ source_suffix = '.rst' master_doc = 'index' project = u'pyexcel-xls' -copyright = u'2015-2017 Onni Software Ltd.' +copyright = u'2015-2018 Onni Software Ltd.' version = '0.5.5' -release = '0.5.5' +release = '0.5.6' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml index c8c1660..9902b40 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel_xls.yaml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.5.5 -current_version: 0.5.5 +version: 0.5.6 +current_version: 0.5.6 release: 0.5.5 file_type: xls dependencies: diff --git a/setup.py b/setup.py index 7948f6b..5717147 100644 --- a/setup.py +++ b/setup.py @@ -9,17 +9,16 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' 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 xls format. It' + - ' reads xlsx and xlsm format' + - '' + 'reads xlsx and xlsm format' ) URL = 'https://github.com/pyexcel/pyexcel-xls' DOWNLOAD_URL = '%s/archive/0.5.5.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', 'xlsx', @@ -47,6 +46,7 @@ INSTALL_REQUIRES = [ 'xlrd', 'xlwt', ] +SETUP_COMMANDS = {} PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) @@ -85,6 +85,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_xls.egg-info')) except OSError: pass @@ -101,6 +103,11 @@ class PublishCommand(Command): sys.exit() +SETUP_COMMANDS.update({ + 'publish': PublishCommand +}) + + def has_gease(): """ test if github release command is installed @@ -174,7 +181,5 @@ if __name__ == '__main__': include_package_data=True, zip_safe=False, classifiers=CLASSIFIERS, - cmdclass={ - 'publish': PublishCommand, - } + cmdclass=SETUP_COMMANDS ) From d8d80927e7a64cffd8d9351f5d4bd37398ba7600 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 15 Mar 2018 19:47:58 +0000 Subject: [PATCH 085/163] :hammer: no log changelog is edited in rst but in yml --- .moban.yml | 3 ++ CHANGELOG.rst | 73 ++++++++++++++--------------- changelog.yml | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 38 deletions(-) create mode 100644 changelog.yml diff --git a/.moban.yml b/.moban.yml index e837507..357220b 100644 --- a/.moban.yml +++ b/.moban.yml @@ -21,3 +21,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" + - output: CHANGELOG.rst + configuration: changelog.yml + template: CHANGELOG.rst.jj2 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1e0b5e8..cb22cb1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,25 +5,25 @@ Change log -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. `#25 `_, detect merged - cell in .xls +#. `#25 `_, detect merged cell + in .xls 0.5.4 - 2.11.2017 -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#24 `_, xlsx format cannot use skip_hidden_row_and_column. please use pyexcel-xlsx instead. - + 0.5.3 - 2.11.2017 -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#21 `_, skip hidden rows and columns under 'skip_hidden_row_and_column' flag. @@ -32,9 +32,10 @@ Added -------------------------------------------------------------------------------- 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 #. update its dependecy on pyexcel-io to 0.5.3 @@ -42,18 +43,17 @@ updated -------------------------------------------------------------------------------- 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 -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#20 `_, is handled in pyexcel-io @@ -64,7 +64,7 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#20 `_, handle unseekable stream given by http response. @@ -73,17 +73,18 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. `#15 `_, close file handle -#. pyexcel-io plugin interface now updated to use - `lml `_. +#. `pyexcel-xlsx#15 `_, close + file handle +#. pyexcel-io plugin interface now updated to use `lml + `_. 0.3.3 - 30/05/2017 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#18 `_, pass on encoding_override and others to xlrd. @@ -92,17 +93,16 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** - -#. `#16 `_, allow mmap to - be passed as file content +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. `#16 `_, allow mmap to be + passed as file content 0.3.1 - 16.01.2017 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#14 `_, Python 3.6 - cannot use LOCALE flag with a str pattern @@ -112,7 +112,7 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#13 `_, alert on empyty file content @@ -122,7 +122,7 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#10 `_, To support generator as member of the incoming two dimensional data @@ -131,7 +131,7 @@ Updated -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. support pagination. two pairs: start_row, row_limit and start_column, column_limit help you deal with large files. @@ -140,28 +140,26 @@ Added -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#9 `_, `skip_hidden_sheets` is added. By default, hidden sheets are skipped when reading all sheets. Reading sheet by name or by index are not affected. - 0.2.0 - 01.06.2016 -------------------------------------------------------------------------------- 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-xls' was added so as to inform pyexcel to use it instead of - other libraries, in the situation where there are more than one plugin for - a file type, e.g. xlsm - + other libraries, in the situation where there are more than one plugin for a + file type, e.g. xlsm Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. support the auto-import feature of pyexcel-io 0.2.0 #. xlwt is now used for python 2 implementation while xlwt-future is used for @@ -171,9 +169,8 @@ Updated -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. Passing "streaming=True" to get_data, you will get the two dimensional array as a generator #. Passing "data=your_generator" to save_data is acceptable too. - diff --git a/changelog.yml b/changelog.yml new file mode 100644 index 0000000..79a3eff --- /dev/null +++ b/changelog.yml @@ -0,0 +1,127 @@ +name: pyexcel-xls +organisation: pyexcel +releases: +- changes: + - action: Added + details: + - '`#25`, detect merged cell in .xls' + date: 8.11.2017 + version: 0.5.5 +- changes: + - action: Added + details: + - '`#24`, xlsx format cannot use skip_hidden_row_and_column. please use pyexcel-xlsx + instead.' + date: 2.11.2017 + version: 0.5.4 +- changes: + - action: Added + details: + - '`#21`, skip hidden rows and columns under ''skip_hidden_row_and_column'' flag.' + date: 2.11.2017 + 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 + - update its dependecy on pyexcel-io to 0.5.3 + 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: + - '`#20`, is handled in pyexcel-io' + - 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. + date: 30.08.2017 + version: 0.5.0 +- changes: + - action: Updated + details: + - '`#20`, handle unseekable stream given by http response.' + date: 25.08.2017 + version: 0.4.1 +- changes: + - action: Updated + details: + - '`pyexcel-xlsx#15`, close file handle' + - pyexcel-io plugin interface now updated to use `lml `_. + date: 19.06.2017 + version: 0.4.0 +- changes: + - action: Updated + details: + - '`#18`, pass on encoding_override and others to xlrd.' + date: 30/05/2017 + version: 0.3.3 +- changes: + - action: Updated + details: + - '`#16`, allow mmap to be passed as file content' + date: 18.05.2017 + version: 0.3.2 +- changes: + - action: Updated + details: + - '`#14`, Python 3.6 - cannot use LOCALE flag with a str pattern' + - fix its dependency on pyexcel-io 0.3.0 + date: 16.01.2017 + version: 0.3.1 +- changes: + - action: Updated + details: + - '`#13`, alert on empyty file content' + - Support pyexcel-io v0.3.0 + date: 22.12.2016 + version: 0.3.0 +- changes: + - action: Updated + details: + - '`#10`, To support generator as member of the incoming two dimensional data' + date: 20.09.2016 + version: 0.2.3 +- changes: + - action: Added + details: + - 'support pagination. two pairs: start_row, row_limit and start_column, column_limit + help you deal with large files.' + date: 31.08.2016 + version: 0.2.2 +- changes: + - action: Added + details: + - '`#9`, `skip_hidden_sheets` is added. By default, hidden sheets are skipped + when reading all sheets. Reading sheet by name or by index are not affected.' + date: 13.07.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-xls'' was added so as to inform pyexcel to use it instead + of other libraries, in the situation where there are more than one plugin for a + file type, e.g. xlsm' + - action: Updated + details: + - support the auto-import feature of pyexcel-io 0.2.0 + - xlwt is now used for python 2 implementation while xlwt-future is used for python + 3 + date: 01.06.2016 + version: 0.2.0 +- changes: + - action: Added + details: + - Passing "streaming=True" to get_data, you will get the two dimensional array as + a generator + - Passing "data=your_generator" to save_data is acceptable too. + date: 17.01.2016 + version: 0.1.0 From ad716c0aa9fdede11755dfef14cbe3ce309c11e3 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 15 Mar 2018 19:55:37 +0000 Subject: [PATCH 086/163] :books: update changelog --- CHANGELOG.rst | 10 ++++++++++ changelog.yml | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cb22cb1..6d9d141 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,16 @@ Change log ================================================================================ +0.5.6 - 15.03.2018 +-------------------------------------------------------------------------------- + +Added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `pyexcel#120 `_, xlwt cannot + save a book without any sheet. So, let's raise an exception in this case in + order to warn the developers. + 0.5.5 - 8.11.2017 -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index 79a3eff..a58164c 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-xls organisation: pyexcel releases: +- changes: + - action: Added + details: + - "`pyexcel#120`, xlwt cannot save a book without any sheet. So, let's raise an exception in this case in order to warn the developers." + date: 15.03.2018 + version: 0.5.6 - changes: - action: Added details: From 40462db4897047fddc7601c3e2ca813f091164de Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 15 Mar 2018 19:59:50 +0000 Subject: [PATCH 087/163] :egg: :ferris_wheel: relase 0.5.6 --- .moban.yml | 2 +- docs/source/conf.py | 2 +- pyexcel_xls.yaml | 12 ------------ setup.py | 6 +++--- 4 files changed, 5 insertions(+), 17 deletions(-) delete mode 100644 pyexcel_xls.yaml diff --git a/.moban.yml b/.moban.yml index 357220b..1089516 100644 --- a/.moban.yml +++ b/.moban.yml @@ -4,7 +4,7 @@ configuration: - "commons/templates" - "setupmobans/templates" - ".moban.d" - configuration: pyexcel_xls.yaml + configuration: pyexcel-xls.yml targets: - README.rst: README.rst - setup.py: setup.py diff --git a/docs/source/conf.py b/docs/source/conf.py index e6f6fda..43c7a00 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -19,7 +19,7 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2018 Onni Software Ltd.' -version = '0.5.5' +version = '0.5.6' release = '0.5.6' exclude_patterns = [] pygments_style = 'sphinx' diff --git a/pyexcel_xls.yaml b/pyexcel_xls.yaml deleted file mode 100644 index 9902b40..0000000 --- a/pyexcel_xls.yaml +++ /dev/null @@ -1,12 +0,0 @@ -overrides: "pyexcel.yaml" -name: "pyexcel-xls" -nick_name: xls -version: 0.5.6 -current_version: 0.5.6 -release: 0.5.5 -file_type: xls -dependencies: - - pyexcel-io>=0.5.3 - - xlrd - - xlwt -description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format diff --git a/setup.py b/setup.py index 5717147..f7bd12e 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ DESCRIPTION = ( 'reads xlsx and xlsm format' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -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 = [ 'xls', @@ -55,8 +55,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-xls v0.5.5 ' + - "Find 0.5.5 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls 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 = ( From 94aec7c9bb649079fb9f2f1592fe01b91fe0a761 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 10 May 2018 22:55:54 +0100 Subject: [PATCH 088/163] :bug: fix date offset problem, #54, #135 --- CHANGELOG.rst | 9 +++++++++ pyexcel_xls/xlsr.py | 13 ++++++++----- tests/test_bug_fixes.py | 7 +++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6d9d141..70bb9c2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.5.7 - 15.03.2018 +-------------------------------------------------------------------------------- + +Added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `pyexcel#54 `_, Book.datemode + attribute of that workbook should be passed always. + 0.5.6 - 15.03.2018 -------------------------------------------------------------------------------- diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 94bdd3f..8d7345c 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -44,12 +44,13 @@ class XLSheet(SheetReader): Currently only support first sheet in the file """ - def __init__(self, sheet, auto_detect_int=True, **keywords): + def __init__(self, sheet, auto_detect_int=True, date_mode=0, **keywords): SheetReader.__init__(self, sheet, **keywords) self.__auto_detect_int = auto_detect_int self.__hidden_cols = [] self.__hidden_rows = [] self.__merged_cells = {} + self._book_date_mode = date_mode if keywords.get('detect_merged_cells') is True: for merged_cell_ranges in sheet.merged_cells: merged_cells = MergedCell(*merged_cell_ranges) @@ -88,7 +89,7 @@ class XLSheet(SheetReader): value = self._native_sheet.cell_value(row, column) if cell_type == xlrd.XL_CELL_DATE: - value = xldate_to_python_date(value) + value = xldate_to_python_date(value, self._book_date_mode) elif cell_type == xlrd.XL_CELL_NUMBER and self.__auto_detect_int: if has_no_digits_in_float(value): value = int(value) @@ -176,7 +177,8 @@ class XLSBook(BookReader): return result def read_sheet(self, native_sheet): - sheet = XLSheet(native_sheet, **self._keywords) + sheet = XLSheet(native_sheet, date_mode=self._native_book.datemode, + **self._keywords) return {sheet.name: sheet.to_array()} def _get_book(self, on_demand=False): @@ -208,11 +210,12 @@ class XLSBook(BookReader): return params -def xldate_to_python_date(value): +def xldate_to_python_date(value, date_mode): """ convert xl date to python date """ - date_tuple = xlrd.xldate_as_tuple(value, 0) + date_tuple = xlrd.xldate_as_tuple(value, date_mode) + ret = None if date_tuple == (0, 0, 0, 0, 0, 0): ret = datetime.datetime(1900, 1, 1, 0, 0, 0) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index fc6f38c..35ee894 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -7,6 +7,7 @@ import os import pyexcel as pe from pyexcel_xls import save_data +from pyexcel_xls.xlsr import xldate_to_python_date from pyexcel_xls.xlsw import XLSWriter as Writer from _compact import OrderedDict from nose.tools import eq_, raises @@ -100,5 +101,11 @@ def test_empty_book_pyexcel_issue_120(): writer.write({}) +def test_pyexcel_issue_54(): + xlvalue = 41071.0 + date = xldate_to_python_date(xlvalue, 1) + eq_(date, datetime.date(2016, 6, 12)) + + def get_fixture(file_name): return os.path.join("tests", "fixtures", file_name) From c88163a67d2a187e1902db509c0208916aa7a220 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 10 May 2018 22:57:26 +0100 Subject: [PATCH 089/163] :egg: :ferris_wheel: release 0.5.7, fixing https://github.com/pyexcel/pyexcel/issues/135, https://github.com/pyexcel/pyexcel/issues/54 --- .travis.yml | 1 - README.rst | 12 ++++++++---- changelog.yml | 6 ++++++ docs/source/conf.py | 4 ++-- setup.py | 8 ++++---- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3805bcd..440dd77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ python: - 3.6 - 3.5 - 3.4 - - 3.3 - 2.7 matrix: include: diff --git a/README.rst b/README.rst index 3dd263c..d2b5ea5 100644 --- a/README.rst +++ b/README.rst @@ -5,6 +5,9 @@ pyexcel-xls - Let you focus on data, instead of xls 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 + .. image:: https://travis-ci.org/pyexcel/pyexcel-xls.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-xls @@ -50,11 +53,12 @@ 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`. diff --git a/changelog.yml b/changelog.yml index a58164c..3734e3c 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-xls organisation: pyexcel releases: +- changes: + - action: Added + details: + - "`pyexcel#54`, Book.datemode attribute of that workbook should be passed always." + date: 15.03.2018 + version: 0.5.7 - changes: - action: Added details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 43c7a00..90bf2ea 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -19,8 +19,8 @@ master_doc = 'index' project = u'pyexcel-xls' copyright = u'2015-2018 Onni Software Ltd.' -version = '0.5.6' -release = '0.5.6' +version = '0.5.7' +release = '0.5.7' exclude_patterns = [] pygments_style = 'sphinx' html_theme = 'default' diff --git a/setup.py b/setup.py index f7bd12e..f18938b 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.6' +VERSION = '0.5.7' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -17,7 +17,7 @@ DESCRIPTION = ( 'reads xlsx and xlsm format' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -DOWNLOAD_URL = '%s/archive/0.5.6.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.7.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', @@ -55,8 +55,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-xls v0.5.6 ' + - "Find 0.5.6 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls v0.5.7 ' + + "Find 0.5.7 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') UPLOAD_FAILED_MSG = ( From b0dd6081907d2d141690a0d7281b441c2386056a Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 21 Aug 2018 18:26:50 +0100 Subject: [PATCH 090/163] :sparkles: enhance the behaivor of pyexcel-xls, return #N/A for cell error. https://github.com/pyexcel/pyexcel/issues/151 --- .gitignore | 395 +++++++++++++++++++++++++- .moban.yml | 2 +- .travis.yml | 3 +- README.rst | 19 +- docs/source/conf.py | 186 ++++++++++-- pyexcel_xls.yaml => pyexcel-xls.yml | 6 +- pyexcel_xls/xlsr.py | 3 + setup.py | 71 +++-- test.bat | 2 +- test.sh | 2 +- tests/fixtures/pyexcel_issue_151.xlsx | Bin 0 -> 4465 bytes tests/test_bug_fixes.py | 8 + tests/test_formatters.py | 32 ++- tests/test_stringio.py | 6 +- 14 files changed, 656 insertions(+), 79 deletions(-) rename pyexcel_xls.yaml => pyexcel-xls.yml (81%) create mode 100644 tests/fixtures/pyexcel_issue_151.xlsx 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/.moban.yml b/.moban.yml index e837507..3e6b8f6 100644 --- a/.moban.yml +++ b/.moban.yml @@ -4,7 +4,7 @@ configuration: - "commons/templates" - "setupmobans/templates" - ".moban.d" - configuration: pyexcel_xls.yaml + configuration: pyexcel-xls.yml targets: - README.rst: README.rst - setup.py: setup.py diff --git a/.travis.yml b/.travis.yml index 7a38bf0..5817466 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,11 @@ notifications: email: false python: - pypy-5.3.1 + - 3.7-dev - 3.6 - 3.5 - 3.4 - - 3.3 - 2.7 - - 2.6 matrix: include: - python: 2.7 diff --git a/README.rst b/README.rst index debaced..5aae913 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,10 @@ pyexcel-xls - Let you focus on data, instead of xls 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-xls.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-xls.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-xls .. image:: https://codecov.io/gh/pyexcel/pyexcel-xls/branch/master/graph/badge.svg @@ -25,7 +28,8 @@ Fonts, colors and charts are not supported. Installation ================================================================================ -You can install it via pip: + +You can install pyexcel-xls via pip: .. code-block:: bash @@ -44,13 +48,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 9f48f38..5c8f650 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -4,6 +4,45 @@ DESCRIPTION = ( ' reads xlsx and xlsm 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-xls' +copyright = u'2015-2018 Onni Software Ltd.' +author = u'C.W.' + +# The short X.Y version +version = u'0.5.6' +# The full version, including alpha/beta/rc tags +release = u'0.5.7' + + +# -- 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', @@ -11,34 +50,146 @@ 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-xls' -copyright = u'2015-2017 Onni Software Ltd.' -version = '0.5.1' -release = '0.6.0' +# 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-xlsdoc' -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-xls.tex', - 'pyexcel-xls Documentation', - 'Onni Software Ltd.', 'manual'), + (master_doc, 'pyexcel-xls.tex', u'pyexcel-xls 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-xls', - 'pyexcel-xls Documentation', - [u'Onni Software Ltd.'], 1) + (master_doc, 'pyexcel-xls', u'pyexcel-xls 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-xls', u'pyexcel-xls Documentation', + author, 'pyexcel-xls', '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-xls', 'pyexcel-xls Documentation', @@ -46,3 +197,6 @@ texinfo_documents = [ DESCRIPTION, 'Miscellaneous'), ] +intersphinx_mapping.update({ + 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), +}) diff --git a/pyexcel_xls.yaml b/pyexcel-xls.yml similarity index 81% rename from pyexcel_xls.yaml rename to pyexcel-xls.yml index 1f33888..5aa768a 100644 --- a/pyexcel_xls.yaml +++ b/pyexcel-xls.yml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.6.0 -current_version: 0.6.0 -release: 0.5.1 +version: 0.5.7 +current_version: 0.5.7 +release: 0.5.6 file_type: xls dependencies: - pyexcel-io>=0.5.0 diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 34988f9..7d6356d 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -21,6 +21,7 @@ XLS_KEYWORDS = [ 'file_contents', 'encoding_override', 'formatting_info', 'on_demand', 'ragged_rows' ] +DEFAULT_ERROR_VALUE = '#N/A' class XLSheet(SheetReader): @@ -70,6 +71,8 @@ class XLSheet(SheetReader): elif cell_type == xlrd.XL_CELL_NUMBER and self.__auto_detect_int: if has_no_digits_in_float(value): value = int(value) + elif cell_type == xlrd.XL_CELL_ERROR: + value = DEFAULT_ERROR_VALUE return value def _offset_hidden_indices(self, row, column): diff --git a/setup.py b/setup.py index b7b9732..c518fa1 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 @@ -9,27 +11,24 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.6.0' +VERSION = '0.5.7' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( 'A wrapper library to read, manipulate and write data in xls format. It' + - ' reads xlsx and xlsm format' + - '' + 'reads xlsx and xlsm format' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -DOWNLOAD_URL = '%s/archive/0.5.1.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +DOWNLOAD_URL = '%s/archive/0.5.6.tar.gz' % URL +FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', 'xlsx', - 'xlsm' - 'python' + 'xlsm', + 'python', ] CLASSIFIERS = [ - 'Topic :: Office/Business', - 'Topic :: Utilities', 'Topic :: Software Development :: Libraries', 'Programming Language :: Python', 'Intended Audience :: Developers', @@ -47,16 +46,22 @@ INSTALL_REQUIRES = [ 'xlrd', 'xlwt', ] +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-xls v0.5.1 ' + - "Find 0.5.1 in changelog for more details") -here = os.path.abspath(os.path.dirname(__file__)) +GS_COMMAND = ('gs pyexcel-xls 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 = ( + 'Upload failed. please run "%s" yourself.' % PUBLISH_COMMAND) +HERE = os.path.abspath(os.path.dirname(__file__)) class PublishCommand(Command): @@ -79,17 +84,43 @@ class PublishCommand(Command): def run(self): try: self.status('Removing previous builds...') - rmtree(os.path.join(here, 'dist')) + rmtree(os.path.join(HERE, 'dist')) + rmtree(os.path.join(HERE, 'build')) + rmtree(os.path.join(HERE, 'pyexcel_xls.egg-info')) except OSError: pass self.status('Building Source and Wheel (universal) distribution...') - if os.system(GS_COMMAND) == 0: - os.system(PUBLISH_COMMAND) + 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): """Read files into setup""" text = "" @@ -101,7 +132,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 @@ -150,8 +182,5 @@ if __name__ == '__main__': include_package_data=True, zip_safe=False, classifiers=CLASSIFIERS, - setup_requires=['gease'], - cmdclass={ - 'publish': PublishCommand, - } + cmdclass=SETUP_COMMANDS ) diff --git a/test.bat b/test.bat index a09129d..351d266 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index a09129d..351d266 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long diff --git a/tests/fixtures/pyexcel_issue_151.xlsx b/tests/fixtures/pyexcel_issue_151.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..fd2b54a454e6c0a34795802fd5098e2865d647a4 GIT binary patch literal 4465 zcmaJ^c|278_h-g34T_@3S`k8)Y-351eIIMG4r4crrLoIW#)KJzvSu4=i;RpVTh_={ zM7ANMgi^}1V1A?L_5Aeo`aaLOf86`JuY1mYea?BG_jw;PLm&eu9S8)X%MCwZO!u1| zr#*-IN;?I@eS@S?{((L)e}A8|p?KGP?L^Q^0HQhD~LP+~k(xm$kT5l@dk*62Mv~XI0Ki-y7Iw+o^~p0=Hfy za(Sy7O3rv59trnX%1ie~;y8J4su+1MGOff1v(-cM-Qpv&g(W_;^59If?o}`}6dS~5 zmUKJ4Dtn-MUA1Hg=&j-Uqz|hO6*8D8Jhm~0oTn?OciJ7@^`1$xyF}IBKwJ;N;#)f| z@f1WVw*k!znL$_pfUbph#4LI`In3qyO)PjtHIQ1MfO&T zI0F~RuCUHmG}l;(7?)Cy0Q;_KH+x+pd!`Z5rOIIa$;$;80lXHu=)#;(V`*Y@{EiMk z{>NPDqn~Vq3>osDuGtJIjZ0?f91AMszN(Yp-e7}Q zxFWYn4F0)%`~kZssYE!{dr`QIPuLKK~ebyA*wPmU-IdNm|7WWYW< z0@)DlUJ<#?YF<)xJd%D|9PLrT1fHAwmMQK@-#r1*3GI^`g&rr`$vuH~dd?xtd16g& z)pvt08D6-obH>FN^zNW#yuZwXzS#YH0P&(nXUmL05rZ;%>yrg()YtJcujo0SWq>%n z>?I6;9QkEvS!Y9W2!Sg*AZ=pQXmk=&*q>}F6Rl&#zp%J#njO(|`Vxt{I z3D0hed}vdu%x>&|VmV<@_+dE9iVMhl=phkRfr=jk$KU>p_seSE9D)mKiR`cy$291{ zGK?RWbD80w)0{5}UZrfD)yfKCH{awzPq)3BfJi;%y*u}f!KrcGcp6==$YBjNRXEOO z(tMEom}Mo78{Y*c#RgiF8xK9&Bzp&NCTi?R7b{ay570{WAAEZrsmAsk9h8YBsLN|m zm#3Bc@uBIF>e!)0PgkvKzk)5lI&;*$k1Y?{)yS{?{#3*TI-Zo~45Zj_^xPHF_-Ia0U$&b9#| zaL`0B|IU~cS*qs14C{HG0+PnS2$;2O$xyYC_XNKtlXLiL1%IejQk1n^-IA(gp`h72 zM^g`bFIQERBbUVT%^tSiCg)uEw5p4<*RlTZWe+naAn7cYbQ0P~&i27YecL!WOu*Xv zOre#*MnZKUVk(T+Ogp?*s#~Doq6_n5(xU!JYcECB)DOyB$3zMeDC^oee8GBPk$Omo z@xsd-ND838mUUA&W%1)h?|H^j4MbC`9;|T8bZtpMyua6i@D|uV&E3)0>$_U>8xn6T z%djP_fCgWUg}%8x258lY7HkI6(a7(=7~s%81N=>ZDHeu^X&Lre3MYU<5~h0d-U8aB z;^=lxn4~L+q)3i)isKfYFlVQHzMNFo2`ot!Q#F2mwh7nuePb{;yL_^{2v0tk%w?x7 zxyCdA%v`ar2C;q`OC$V~I<1LKfNHlu@9@7u~$*_Hb;H1h_7RrteF8H4PoR zHRy327cil?^rtrg6WO`=bmFty*=fQ^jJ$7;WppLPVJN z@K9%qStD6D**Z89Nq)T8^0bD)nEGS!$s~#q<^b#Jc}?h5TUs$bSAk{&Hd%vQpK~F_ z@>C}2U;0RTKaF{wHa+=$Ra|MLR}iaF(5fDFh?lg~I#k(^4u%Gc-qRCFQ?$^e56Y+T zz2iwz8S-QVJTZ&DSC6qxV3PuNtL7i+iW@Qc^mZq2O+;_0tCp9+1<1l2>GM3w6o$_k ziaB6_8M`2HqWtu-Ukduw?THeym;g3BpL}u+)v*!yDr{7cRkaU}A6Z*~tLeAmiG1%f z?lhG8KOgZA1a`mIn^u2x=8Cexd3c?F?|{Zl*e=T+hLWdpRhR*EbVwSG{(XwD{e_{R z;4oi!(B9}+&vNk3mEpYcks={ESB;a`pH4EX%a>bsuNt?^kzem%1X}OJ`j)fpd{yna zAY@f1^4RvwoBpk55Uf+GU$=0RJxl7H3Pqznh(LYv2Sv;B5`-?Az%S zcHmYQ;UbcCy<^B2^pHZO&Z3ue5yF|wTx#*kZU_GLumMkBrto%a-ePiq7E(0IdYH(y zh#nmP*w!`&+_!?y3yq(l&sXdmp&Fx_x)1cM<{IXyo1H1^uu)NVqeBkfvy!+|$#4m;r9{!BnKFvlR zL458_s_*G{PIEi(RuoonJtD=)qdK3mvt9BP6;OUC2fB40*F+o&FxCEG5tQ22=#L=Z zo$16NpShhgux4^xn(}FBB*`infL=g#M(LM>byDSjjdevKsK3w2`2cyerWt-yTv7K?=JZ8Mj`-={NJ(qDbD8J?SFDSFnp!}C4 z{7VMnhYf(T?1>+vFt`X5iR+SEZ3}uNS1;;X*1)cdQnn0FNK`~T$gZ-K8LJIJG z6fqs?bIly4!IAaBaNA!QtT_lhKin zm9OxhfFFr8MeypJ**N35NKp^ty|b!NDQ8e!$|evV7-vLUxY1U|exfMWo-1xx9U|1j zR(hGgy>Etd`j`i}PhV1Q-7D*K$-H>QWUTI#+_XEyhm!8Lv?cS`Ag5?S zlbQ_%!FFv44uTb|Uf!`Yd0rEp>hv2)#P7 z`W+^H*O|EoWA{cZ3C4L1rf{rk;Q6y~o*^@5eycp|x;Q@m_F`?Mf=AB7srHge1#Z!H zCbHh;j^I?%kXKv{{0eSN$FWGQu`-1)R9@DVLzK1ym@IxfZWxeZp^Nn3e&5HzF9pe! z3~{X@UpvRjrDry@AZ)OqzuK-B@#*4lo_J{hGuyG!Q;ioCmniBTV;D8YdW)2vaXo(nybc1Aa$Zl0N=J*2u&N42GT z*tk(u_xLIJj8ElJhveOZ*DMp`2_0dNwu!+mxHN1Lqx4Gy5@-S*2JD|iD=y21q07Qy z_A*?P!9#Il{m3$jKgp} zyB*~X>uG0=1&y(3s0b?7VH3SMuSU;Xz<)&P-dIJ@@Gb6Q$eqva)@SEeHloG}yC!*- zGSMT;zq)|haqH+QT8@W*NdkHRC*A&j{rl3nw_pF${(ajvGyG?q-=*u`in?!%v_I40 z{Lh8;&nUl(mpz%gZ_JGUALVb+`=@j3Z{uQ5-|U+q^DpOpwezRz?}WNHPxkF7_#e~d zPsiU0W{+?8O_~ Date: Tue, 21 Aug 2018 18:28:28 +0100 Subject: [PATCH 091/163] :lipstick: pump version number --- docs/source/conf.py | 4 ++-- pyexcel-xls.yml | 6 +++--- setup.py | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 5c8f650..5e08605 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -29,9 +29,9 @@ copyright = u'2015-2018 Onni Software Ltd.' author = u'C.W.' # The short X.Y version -version = u'0.5.6' +version = u'0.5.7' # The full version, including alpha/beta/rc tags -release = u'0.5.7' +release = u'0.5.8' # -- General configuration --------------------------------------------------- diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 5aa768a..a77e423 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.5.7 -current_version: 0.5.7 -release: 0.5.6 +version: 0.5.8 +current_version: 0.5.8 +release: 0.5.7 file_type: xls dependencies: - pyexcel-io>=0.5.0 diff --git a/setup.py b/setup.py index c518fa1..6615ef2 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.7' +VERSION = '0.5.8' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -19,7 +19,7 @@ DESCRIPTION = ( 'reads xlsx and xlsm format' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -DOWNLOAD_URL = '%s/archive/0.5.6.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.7.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', @@ -55,8 +55,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-xls v0.5.6 ' + - "Find 0.5.6 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls v0.5.7 ' + + "Find 0.5.7 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') UPLOAD_FAILED_MSG = ( From 629c2c8e765aca5180bae2448d4566ac38eb155c Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 22 Aug 2018 07:51:12 +0100 Subject: [PATCH 092/163] :green_heart: use xlrd 1.1.0 --- .moban.d/tests/requirements.txt | 1 + tests/requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/.moban.d/tests/requirements.txt b/.moban.d/tests/requirements.txt index da5ea12..414637d 100644 --- a/.moban.d/tests/requirements.txt +++ b/.moban.d/tests/requirements.txt @@ -1,4 +1,5 @@ {% extends 'tests/requirements.txt.jj2' %} {%block extras %} pyexcel +xlrd==1.1.0 {%endblock%} diff --git a/tests/requirements.txt b/tests/requirements.txt index a29762c..131361c 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -4,3 +4,4 @@ codecov coverage flake8 pyexcel +xlrd==1.1.0 From 7aec2d0407492dff4cf18bd52dd4d5b759800474 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 22 Aug 2018 18:45:07 +0100 Subject: [PATCH 093/163] :sparkles: use yml for changelog --- .moban.yml | 3 ++ CHANGELOG.rst | 47 ++++++++++++------------ changelog.yml | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 25 deletions(-) create mode 100644 changelog.yml diff --git a/.moban.yml b/.moban.yml index 3e6b8f6..1089516 100644 --- a/.moban.yml +++ b/.moban.yml @@ -21,3 +21,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" + - output: CHANGELOG.rst + configuration: changelog.yml + template: CHANGELOG.rst.jj2 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ffa0760..b5e65e0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,7 +5,7 @@ Change log -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#21 `_, skip hidden rows and columns under 'skip_hidden_row_and_column' flag. @@ -14,7 +14,7 @@ Added -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#20 `_, is handled in pyexcel-io @@ -25,7 +25,7 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#20 `_, handle unseekable stream given by http response. @@ -34,17 +34,18 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#. `#15 `_, close file handle -#. pyexcel-io plugin interface now updated to use - `lml `_. +#. `pyexcel-xlsx#15 `_, close + file handle +#. pyexcel-io plugin interface now updated to use `lml + `_. 0.3.3 - 30/05/2017 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#18 `_, pass on encoding_override and others to xlrd. @@ -53,17 +54,16 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** - -#. `#16 `_, allow mmap to - be passed as file content +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#. `#16 `_, allow mmap to be + passed as file content 0.3.1 - 16.01.2017 -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#14 `_, Python 3.6 - cannot use LOCALE flag with a str pattern @@ -73,7 +73,7 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#13 `_, alert on empyty file content @@ -83,7 +83,7 @@ Updated -------------------------------------------------------------------------------- Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#10 `_, To support generator as member of the incoming two dimensional data @@ -92,7 +92,7 @@ Updated -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. support pagination. two pairs: start_row, row_limit and start_column, column_limit help you deal with large files. @@ -101,28 +101,26 @@ Added -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#9 `_, `skip_hidden_sheets` is added. By default, hidden sheets are skipped when reading all sheets. Reading sheet by name or by index are not affected. - 0.2.0 - 01.06.2016 -------------------------------------------------------------------------------- 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-xls' was added so as to inform pyexcel to use it instead of - other libraries, in the situation where there are more than one plugin for - a file type, e.g. xlsm - + other libraries, in the situation where there are more than one plugin for a + file type, e.g. xlsm Updated -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. support the auto-import feature of pyexcel-io 0.2.0 #. xlwt is now used for python 2 implementation while xlwt-future is used for @@ -132,9 +130,8 @@ Updated -------------------------------------------------------------------------------- Added -******************************************************************************** +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. Passing "streaming=True" to get_data, you will get the two dimensional array as a generator #. Passing "data=your_generator" to save_data is acceptable too. - diff --git a/changelog.yml b/changelog.yml new file mode 100644 index 0000000..815accb --- /dev/null +++ b/changelog.yml @@ -0,0 +1,99 @@ +name: pyexcel-xls +organisation: pyexcel +releases: +- changes: + - action: Added + details: + - '`#21`, skip hidden rows and columns under ''skip_hidden_row_and_column'' flag.' + date: unreleased + version: 0.6.0 +- changes: + - action: Updated + details: + - '`#20`, is handled in pyexcel-io' + - 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. + date: 30.08.2017 + version: 0.5.0 +- changes: + - action: Updated + details: + - '`#20`, handle unseekable stream given by http response.' + date: 25.08.2017 + version: 0.4.1 +- changes: + - action: Updated + details: + - '`pyexcel-xlsx#15`, close file handle' + - pyexcel-io plugin interface now updated to use `lml `_. + date: 19.06.2017 + version: 0.4.0 +- changes: + - action: Updated + details: + - '`#18`, pass on encoding_override and others to xlrd.' + date: 30/05/2017 + version: 0.3.3 +- changes: + - action: Updated + details: + - '`#16`, allow mmap to be passed as file content' + date: 18.05.2017 + version: 0.3.2 +- changes: + - action: Updated + details: + - '`#14`, Python 3.6 - cannot use LOCALE flag with a str pattern' + - fix its dependency on pyexcel-io 0.3.0 + date: 16.01.2017 + version: 0.3.1 +- changes: + - action: Updated + details: + - '`#13`, alert on empyty file content' + - Support pyexcel-io v0.3.0 + date: 22.12.2016 + version: 0.3.0 +- changes: + - action: Updated + details: + - '`#10`, To support generator as member of the incoming two dimensional data' + date: 20.09.2016 + version: 0.2.3 +- changes: + - action: Added + details: + - 'support pagination. two pairs: start_row, row_limit and start_column, column_limit + help you deal with large files.' + date: 31.08.2016 + version: 0.2.2 +- changes: + - action: Added + details: + - '`#9`, `skip_hidden_sheets` is added. By default, hidden sheets are skipped + when reading all sheets. Reading sheet by name or by index are not affected.' + date: 13.07.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-xls'' was added so as to inform pyexcel to use it instead + of other libraries, in the situation where there are more than one plugin for a + file type, e.g. xlsm' + - action: Updated + details: + - support the auto-import feature of pyexcel-io 0.2.0 + - xlwt is now used for python 2 implementation while xlwt-future is used for python + 3 + date: 01.06.2016 + version: 0.2.0 +- changes: + - action: Added + details: + - Passing "streaming=True" to get_data, you will get the two dimensional array as + a generator + - Passing "data=your_generator" to save_data is acceptable too. + date: 17.01.2016 + version: 0.1.0 From 8443709d84364386b0f0867f8fd40d77c207e5aa Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 22 Aug 2018 18:54:41 +0100 Subject: [PATCH 094/163] :egg: :ferris_wheel: release 0.5.8 --- CHANGELOG.rst | 9 +++++++++ changelog.yml | 6 ++++++ docs/source/conf.py | 2 +- pyexcel-xls.yml | 2 +- setup.py | 6 +++--- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 70bb9c2..e4677db 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.5.8 - 22.08.2018 +-------------------------------------------------------------------------------- + +Added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `pyexcel#151 `_, read cell + error as #N/A. + 0.5.7 - 15.03.2018 -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index 3734e3c..f25f270 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-xls organisation: pyexcel releases: +- changes: + - action: Added + details: + - "`pyexcel#151`, read cell error as #N/A." + date: 22.08.2018 + version: 0.5.8 - changes: - action: Added details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 5e08605..f3b62db 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -29,7 +29,7 @@ copyright = u'2015-2018 Onni Software Ltd.' author = u'C.W.' # The short X.Y version -version = u'0.5.7' +version = u'0.5.8' # The full version, including alpha/beta/rc tags release = u'0.5.8' diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 8ddf1b8..c620ccb 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -3,7 +3,7 @@ name: "pyexcel-xls" nick_name: xls version: 0.5.8 current_version: 0.5.8 -release: 0.5.7 +release: 0.5.8 file_type: xls dependencies: - pyexcel-io>=0.5.3 diff --git a/setup.py b/setup.py index 0a02bd1..92b2a0e 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ DESCRIPTION = ( 'reads xlsx and xlsm format' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -DOWNLOAD_URL = '%s/archive/0.5.7.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.8.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', @@ -55,8 +55,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-xls v0.5.7 ' + - "Find 0.5.7 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls v0.5.8 ' + + "Find 0.5.8 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') UPLOAD_FAILED_MSG = ( From aa7222de6124fee9e8707bfe5a1abbf4f7f601e9 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 10 Nov 2018 22:26:43 +0000 Subject: [PATCH 095/163] :hammer: kick start 0.6.0 --- .moban.d/tests/requirements.txt | 3 +++ .moban.yml | 11 ++++++++--- Makefile | 4 ++++ docs/source/conf.py | 11 +++-------- pyexcel-xls.yml | 4 ++-- pyexcel_xls/__init__.py | 2 +- setup.py | 10 ++++++---- tests/requirements.txt | 3 +++ tests/test_bug_fixes.py | 6 +++--- 9 files changed, 33 insertions(+), 21 deletions(-) diff --git a/.moban.d/tests/requirements.txt b/.moban.d/tests/requirements.txt index 414637d..6ca5326 100644 --- a/.moban.d/tests/requirements.txt +++ b/.moban.d/tests/requirements.txt @@ -2,4 +2,7 @@ {%block extras %} pyexcel xlrd==1.1.0 +moban +black;python_version>="3.6" +isort;python_version>="3.6" {%endblock%} diff --git a/.moban.yml b/.moban.yml index 1089516..c0d7ab1 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-xls.yml targets: diff --git a/Makefile b/Makefile index 10b28ae..54d3bf5 100644 --- a/Makefile +++ b/Makefile @@ -3,3 +3,7 @@ all: test test: bash test.sh +format: + isort -y $(find pyexcel_xls -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) + black -l 79 pyexcel_xls + black -l 79 tests diff --git a/docs/source/conf.py b/docs/source/conf.py index f3b62db..e840796 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -31,7 +31,7 @@ author = u'C.W.' # The short X.Y version version = u'0.5.8' # The full version, including alpha/beta/rc tags -release = u'0.5.8' +release = u'0.6.0' # -- General configuration --------------------------------------------------- @@ -43,12 +43,7 @@ release = u'0.5.8' # 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'] @@ -75,7 +70,7 @@ language = 'en' exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = None # -- Options for HTML output ------------------------------------------------- diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index c620ccb..28fbf55 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -1,8 +1,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.5.8 -current_version: 0.5.8 +version: 0.6.0 +current_version: 0.6.0 release: 0.5.8 file_type: xls dependencies: diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index 839f600..00e704c 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -11,7 +11,7 @@ # 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, save_data as write_data __FILE_TYPE__ = 'xls' IOPluginInfoChain(__name__).add_a_reader( diff --git a/setup.py b/setup.py index 92b2a0e..f6238c9 100644 --- a/setup.py +++ b/setup.py @@ -5,13 +5,15 @@ import os import sys import codecs from shutil import rmtree -from setuptools import setup, find_packages, Command + +from setuptools import Command, setup, find_packages + PY2 = sys.version_info[0] == 2 PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.8' +VERSION = '0.6.0' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -22,10 +24,10 @@ URL = 'https://github.com/pyexcel/pyexcel-xls' DOWNLOAD_URL = '%s/archive/0.5.8.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ + 'python', 'xls', 'xlsx', - 'xlsm', - 'python', + 'xlsm' ] CLASSIFIERS = [ diff --git a/tests/requirements.txt b/tests/requirements.txt index 131361c..a2a17f7 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -5,3 +5,6 @@ coverage flake8 pyexcel xlrd==1.1.0 +moban +black;python_version>="3.6" +isort;python_version>="3.6" diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index af8bf42..7d7fb02 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -89,7 +89,7 @@ def test_issue_18_encoding_override_isnt_passed(fake_open): def test_issue_20(): if not IN_TRAVIS: raise SkipTest() - pe.get_book(url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls"); # flake8: noqa + pe.get_book(url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls") # noqa: E501 def test_issue_151(): @@ -97,7 +97,7 @@ def test_issue_151(): file_name=get_fixture('pyexcel_issue_151.xlsx'), skip_hidden_row_and_column=False, library='pyexcel-xls') - eq_('#N/A', s[0,0]) + eq_('#N/A', s[0, 0]) @raises(NotImplementedError) @@ -113,7 +113,7 @@ def test_pyexcel_issue_54(): xlvalue = 41071.0 date = xldate_to_python_date(xlvalue, 1) eq_(date, datetime.date(2016, 6, 12)) - + def get_fixture(file_name): return os.path.join("tests", "fixtures", file_name) From 6af34ace269c4e0ef79d4c975d5860a883246f31 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 10 Nov 2018 22:29:42 +0000 Subject: [PATCH 096/163] :hammer: black and isort now rules the coding style --- .moban.d/tests/base.py | 2 +- pyexcel_xls/__init__.py | 18 ++++++---- pyexcel_xls/xlsr.py | 64 ++++++++++++++++++++--------------- pyexcel_xls/xlsw.py | 24 ++++++++----- tests/_compact.py | 1 - tests/base.py | 17 ++++++---- tests/test_bug_fixes.py | 51 ++++++++++++++++------------ tests/test_filter.py | 49 ++++++++++++++++----------- tests/test_formatters.py | 64 +++++++++++++++++++++++------------ tests/test_hidden.py | 14 +++++--- tests/test_merged_cells.py | 54 ++++++++++++++--------------- tests/test_multiple_sheets.py | 28 +++++++-------- tests/test_stringio.py | 25 +++++++------- tests/test_writer.py | 8 +++-- 14 files changed, 240 insertions(+), 179 deletions(-) diff --git a/.moban.d/tests/base.py b/.moban.d/tests/base.py index b7510db..156f96c 100644 --- a/.moban.d/tests/base.py +++ b/.moban.d/tests/base.py @@ -1,4 +1,4 @@ {% extends 'tests/base.py.jj2' %} {%block ods_types%} -{%endblock%} \ No newline at end of file +{%endblock%} diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index 00e704c..c2175cb 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -11,17 +11,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, save_data as write_data +from pyexcel_io.io import ( + get_data as read_data, + isstream, + save_data as write_data, +) -__FILE_TYPE__ = 'xls' +__FILE_TYPE__ = "xls" IOPluginInfoChain(__name__).add_a_reader( - relative_plugin_class_path='xlsr.XLSBook', - file_types=[__FILE_TYPE__, 'xlsx', 'xlsm'], - stream_type='binary' + relative_plugin_class_path="xlsr.XLSBook", + file_types=[__FILE_TYPE__, "xlsx", "xlsm"], + stream_type="binary", ).add_a_writer( - relative_plugin_class_path='xlsw.XLSWriter', + relative_plugin_class_path="xlsw.XLSWriter", file_types=[__FILE_TYPE__], - stream_type='binary' + stream_type="binary", ) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 0476857..a6b9b97 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -8,20 +8,26 @@ :license: New BSD License """ import datetime + import xlrd from pyexcel_io.book import BookReader from pyexcel_io.sheet import SheetReader -from pyexcel_io._compact import OrderedDict, irange from pyexcel_io.service import has_no_digits_in_float - +from pyexcel_io._compact import OrderedDict, irange XLS_KEYWORDS = [ - 'filename', 'logfile', 'verbosity', 'use_mmap', - 'file_contents', 'encoding_override', 'formatting_info', - 'on_demand', 'ragged_rows' + "filename", + "logfile", + "verbosity", + "use_mmap", + "file_contents", + "encoding_override", + "formatting_info", + "on_demand", + "ragged_rows", ] -DEFAULT_ERROR_VALUE = '#N/A' +DEFAULT_ERROR_VALUE = "#N/A" class MergedCell(object): @@ -45,6 +51,7 @@ class XLSheet(SheetReader): Currently only support first sheet in the file """ + def __init__(self, sheet, auto_detect_int=True, date_mode=0, **keywords): SheetReader.__init__(self, sheet, **keywords) self.__auto_detect_int = auto_detect_int @@ -52,11 +59,11 @@ class XLSheet(SheetReader): self.__hidden_rows = [] self.__merged_cells = {} self._book_date_mode = date_mode - if keywords.get('detect_merged_cells') is True: + if keywords.get("detect_merged_cells") is True: for merged_cell_ranges in sheet.merged_cells: merged_cells = MergedCell(*merged_cell_ranges) merged_cells.register_cells(self.__merged_cells) - if keywords.get('skip_hidden_row_and_column') is True: + if keywords.get("skip_hidden_row_and_column") is True: for col_index, info in self._native_sheet.colinfo_map.items(): if info.hidden == 1: self.__hidden_cols.append(col_index) @@ -84,7 +91,7 @@ class XLSheet(SheetReader): """ Random access to the xls cells """ - if self._keywords.get('skip_hidden_row_and_column') is True: + if self._keywords.get("skip_hidden_row_and_column") is True: row, column = self._offset_hidden_indices(row, column) cell_type = self._native_sheet.cell_type(row, column) value = self._native_sheet.cell_value(row, column) @@ -126,6 +133,7 @@ class XLSBook(BookReader): It reads xls, xlsm, xlsx work book """ + def __init__(self): BookReader.__init__(self) self._file_content = None @@ -147,10 +155,11 @@ class XLSBook(BookReader): self._file_content = file_content def __parse_keywords(self, **keywords): - self.__skip_hidden_sheets = keywords.get('skip_hidden_sheets', True) + self.__skip_hidden_sheets = keywords.get("skip_hidden_sheets", True) self.__skip_hidden_row_column = keywords.get( - 'skip_hidden_row_and_column', True) - self.__detect_merged_cells = keywords.get('detect_merged_cells', False) + "skip_hidden_row_and_column", True + ) + self.__detect_merged_cells = keywords.get("detect_merged_cells", False) def close(self): if self._native_book: @@ -181,27 +190,30 @@ class XLSBook(BookReader): return result def read_sheet(self, native_sheet): - sheet = XLSheet(native_sheet, date_mode=self._native_book.datemode, - **self._keywords) + sheet = XLSheet( + native_sheet, + date_mode=self._native_book.datemode, + **self._keywords + ) return {sheet.name: sheet.to_array()} def _get_book(self, on_demand=False): xlrd_params = self._extract_xlrd_params() - xlrd_params['on_demand'] = on_demand + xlrd_params["on_demand"] = on_demand if self._file_name: - xlrd_params['filename'] = self._file_name + xlrd_params["filename"] = self._file_name elif self._file_stream: file_content = self._file_stream.read() - xlrd_params['file_contents'] = file_content + xlrd_params["file_contents"] = file_content elif self._file_content is not None: - xlrd_params['file_contents'] = self._file_content + xlrd_params["file_contents"] = self._file_content else: raise IOError("No valid file name or file content found.") - if self.__skip_hidden_row_column and self._file_type == 'xls': - xlrd_params['formatting_info'] = True + if self.__skip_hidden_row_column and self._file_type == "xls": + xlrd_params["formatting_info"] = True if self.__detect_merged_cells: - xlrd_params['formatting_info'] = True + xlrd_params["formatting_info"] = True xls_book = xlrd.open_workbook(**xlrd_params) return xls_book @@ -224,13 +236,9 @@ def xldate_to_python_date(value, date_mode): if date_tuple == (0, 0, 0, 0, 0, 0): ret = datetime.datetime(1900, 1, 1, 0, 0, 0) elif date_tuple[0:3] == (0, 0, 0): - ret = datetime.time(date_tuple[3], - date_tuple[4], - date_tuple[5]) + ret = datetime.time(date_tuple[3], date_tuple[4], date_tuple[5]) elif date_tuple[3:6] == (0, 0, 0): - ret = datetime.date(date_tuple[0], - date_tuple[1], - date_tuple[2]) + ret = datetime.date(date_tuple[0], date_tuple[1], date_tuple[2]) else: ret = datetime.datetime( date_tuple[0], @@ -238,6 +246,6 @@ def xldate_to_python_date(value, date_mode): date_tuple[2], date_tuple[3], date_tuple[4], - date_tuple[5] + date_tuple[5], ) return ret diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 28ab8e8..5dd1520 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -8,13 +8,13 @@ :license: New BSD License """ import datetime + import xlrd -from xlwt import Workbook, XFStyle +from xlwt import XFStyle, Workbook from pyexcel_io.book import BookWriter from pyexcel_io.sheet import SheetWriter - DEFAULT_DATE_FORMAT = "DD/MM/YY" DEFAULT_TIME_FORMAT = "HH:MM:SS" DEFAULT_DATETIME_FORMAT = "%s %s" % (DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT) @@ -25,6 +25,7 @@ class XLSheetWriter(SheetWriter): """ xls sheet writer """ + def set_sheet_name(self, name): """Create a sheet """ @@ -40,8 +41,12 @@ class XLSheetWriter(SheetWriter): tmp_array = [] if isinstance(value, datetime.datetime): tmp_array = [ - value.year, value.month, value.day, - value.hour, value.minute, value.second + value.year, + value.month, + value.day, + value.hour, + value.minute, + value.second, ] value = xlrd.xldate.xldate_from_datetime_tuple(tmp_array, 0) style = XFStyle() @@ -67,15 +72,18 @@ class XLSWriter(BookWriter): """ xls writer """ + def __init__(self): BookWriter.__init__(self) self.work_book = None - def open(self, file_name, - encoding='ascii', style_compression=2, **keywords): + def open( + self, file_name, encoding="ascii", style_compression=2, **keywords + ): BookWriter.open(self, file_name, **keywords) - self.work_book = Workbook(style_compression=style_compression, - encoding=encoding) + self.work_book = Workbook( + style_compression=style_compression, encoding=encoding + ) def write(self, incoming_dict): if incoming_dict: diff --git a/tests/_compact.py b/tests/_compact.py index 08694b3..e47d675 100644 --- a/tests/_compact.py +++ b/tests/_compact.py @@ -1,7 +1,6 @@ # flake8: noqa import sys - if sys.version_info[0] == 2 and sys.version_info[1] < 7: from ordereddict import OrderedDict else: diff --git a/tests/base.py b/tests/base.py index 4339f70..71474a3 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,11 +1,13 @@ import os # noqa -import pyexcel import datetime # noqa -from nose.tools import raises, eq_ # 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 +19,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 +39,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 +58,6 @@ class PyexcelWriterBase: class PyexcelMultipleSheetBase: - def _write_test_file(self, filename): pyexcel.save_book_as(bookdict=self.content, dest_file_name=filename) @@ -80,7 +83,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) diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 7d7fb02..ee0f668 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -5,17 +5,19 @@ """ import os +import datetime + import pyexcel as pe +from _compact import OrderedDict + +from mock import patch +from nose import SkipTest +from nose.tools import eq_, raises from pyexcel_xls import save_data from pyexcel_xls.xlsr import xldate_to_python_date from pyexcel_xls.xlsw import XLSWriter as Writer -from _compact import OrderedDict -from nose.tools import eq_, raises -from nose import SkipTest -import datetime -from mock import patch -IN_TRAVIS = 'TRAVIS' in os.environ +IN_TRAVIS = "TRAVIS" in os.environ def test_pyexcel_issue_5(): @@ -41,16 +43,15 @@ def test_issue_9_hidden_sheet(): test_file = get_fixture("hidden_sheets.xls") book_dict = pe.get_book_dict(file_name=test_file) assert "hidden" not in book_dict - eq_(book_dict['shown'], [['A', 'B']]) + eq_(book_dict["shown"], [["A", "B"]]) def test_issue_9_hidden_sheet_2(): test_file = get_fixture("hidden_sheets.xls") - book_dict = pe.get_book_dict(file_name=test_file, - skip_hidden_sheets=False) + book_dict = pe.get_book_dict(file_name=test_file, skip_hidden_sheets=False) assert "hidden" in book_dict - eq_(book_dict['shown'], [['A', 'B']]) - eq_(book_dict['hidden'], [['a', 'b']]) + eq_(book_dict["shown"], [["A", "B"]]) + eq_(book_dict["hidden"], [["a", "b"]]) def test_issue_10_generator_as_content(): @@ -58,46 +59,52 @@ def test_issue_10_generator_as_content(): def custom_row_renderer(row): for e in row: yield e + for i in range(2): yield custom_row_renderer([1, 2]) + save_data("test.xls", {"sheet": data_gen()}) @raises(IOError) def test_issue_13_empty_file_content(): - pe.get_sheet(file_content='', file_type='xls') + pe.get_sheet(file_content="", file_type="xls") def test_issue_16_file_stream_has_no_getvalue(): test_file = get_fixture("hidden_sheets.xls") - with open(test_file, 'rb') as f: - pe.get_sheet(file_stream=f, file_type='xls') + with open(test_file, "rb") as f: + pe.get_sheet(file_stream=f, file_type="xls") -@patch('xlrd.open_workbook') +@patch("xlrd.open_workbook") def test_issue_18_encoding_override_isnt_passed(fake_open): fake_open.return_value = None - test_encoding = 'utf-32' + test_encoding = "utf-32" from pyexcel_xls.xlsr import XLSBook + book = XLSBook() - book.open('fake_file.xls', encoding_override=test_encoding) + book.open("fake_file.xls", encoding_override=test_encoding) book._get_book() keywords = fake_open.call_args[1] - assert keywords['encoding_override'] == test_encoding + assert keywords["encoding_override"] == test_encoding def test_issue_20(): if not IN_TRAVIS: raise SkipTest() - pe.get_book(url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls") # noqa: E501 + pe.get_book( + url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls" # noqa: E501 + ) def test_issue_151(): s = pe.get_sheet( - file_name=get_fixture('pyexcel_issue_151.xlsx'), + file_name=get_fixture("pyexcel_issue_151.xlsx"), skip_hidden_row_and_column=False, - library='pyexcel-xls') - eq_('#N/A', s[0, 0]) + library="pyexcel-xls", + ) + eq_("#N/A", s[0, 0]) @raises(NotImplementedError) diff --git a/tests/test_filter.py b/tests/test_filter.py index 2d760b2..c9bc9e0 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-xls") + filtered_data = get_data( + self.test_file, start_row=3, library="pyexcel-xls" + ) 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-xls") + filtered_data = get_data( + self.test_file, start_row=3, row_limit=1, library="pyexcel-xls" + ) 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-xls") - 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-xls" + ) + 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-xls") + filtered_data = get_data( + self.test_file, + start_column=1, + column_limit=1, + library="pyexcel-xls", + ) 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-xls") + filtered_data = get_data( + self.test_file, start_column=1, start_row=3, library="pyexcel-xls" + ) 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-xls") + filtered_data = get_data( + self.test_file, + start_column=1, + column_limit=1, + start_row=3, + row_limit=1, + library="pyexcel-xls", + ) expected = [[24]] eq_(filtered_data[self.sheet_name], expected) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 76b8f87..0dcd74a 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -1,9 +1,10 @@ import os from textwrap import dedent -from nose.tools import eq_ import pyexcel as pe +from nose.tools import eq_ + class TestDateFormat: def test_reading_date_format(self): @@ -15,9 +16,11 @@ class TestDateFormat: 0.0 0.0 """ import datetime - r = pe.get_sheet(file_name=os.path.join("tests", "fixtures", - "date_field.xls"), - library='pyexcel-xls') + + r = pe.get_sheet( + file_name=os.path.join("tests", "fixtures", "date_field.xls"), + library="pyexcel-xls", + ) assert isinstance(r[1, 0], datetime.date) eq_(r[1, 0].strftime("%d/%m/%y"), "25/12/14") assert isinstance(r[1, 1], datetime.time) is True @@ -27,12 +30,17 @@ class TestDateFormat: def test_writing_date_format(self): import datetime + excel_filename = "testdateformat.xls" - data = [[datetime.date(2014, 12, 25), + data = [ + [ + datetime.date(2014, 12, 25), datetime.time(11, 11, 11), - datetime.datetime(2014, 12, 25, 11, 11, 11)]] + datetime.datetime(2014, 12, 25, 11, 11, 11), + ] + ] pe.save_as(dest_file_name=excel_filename, array=data) - r = pe.get_sheet(file_name=excel_filename, library='pyexcel-xls') + r = pe.get_sheet(file_name=excel_filename, library="pyexcel-xls") assert isinstance(r[0, 0], datetime.date) is True assert r[0, 0].strftime("%d/%m/%y") == "25/12/14" assert isinstance(r[0, 1], datetime.time) is True @@ -46,46 +54,58 @@ class TestAutoDetectInt: def setUp(self): self.content = [[1, 2, 3.1]] self.test_file = "test_auto_detect_init.xls" - 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-xls") - 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-xls") - 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-xls") - expected = dedent(""" + sheet = pe.get_sheet( + file_name=self.test_file, + auto_detect_int=False, + library="pyexcel-xls", + ) + 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-xls") - expected = dedent(""" + book = pe.get_book( + file_name=self.test_file, + auto_detect_int=False, + library="pyexcel-xls", + ) + expected = dedent( + """ pyexcel_sheet1: +-----+-----+-----+ | 1.0 | 2.0 | 3.1 | - +-----+-----+-----+""").strip() + +-----+-----+-----+""" + ).strip() eq_(str(book), expected) def tearDown(self): diff --git a/tests/test_hidden.py b/tests/test_hidden.py index 77b1a71..aa72f9c 100644 --- a/tests/test_hidden.py +++ b/tests/test_hidden.py @@ -1,18 +1,22 @@ import os + from nose.tools import eq_ from pyexcel_xls import get_data def test_simple_hidden_sheets(): - data = get_data(os.path.join("tests", "fixtures", "hidden.xls"), - skip_hidden_row_and_column=True) + data = get_data( + os.path.join("tests", "fixtures", "hidden.xls"), + skip_hidden_row_and_column=True, + ) expected = [[1, 3], [7, 9]] - eq_(data['Sheet1'], expected) + eq_(data["Sheet1"], expected) def test_complex_hidden_sheets(): data = get_data( os.path.join("tests", "fixtures", "complex_hidden_sheets.xls"), - skip_hidden_row_and_column=True) + skip_hidden_row_and_column=True, + ) expected = [[1, 3, 5, 7, 9], [31, 33, 35, 37, 39], [61, 63, 65, 67]] - eq_(data['Sheet1'], expected) + eq_(data["Sheet1"], expected) diff --git a/tests/test_merged_cells.py b/tests/test_merged_cells.py index 0247ccc..d4744e5 100644 --- a/tests/test_merged_cells.py +++ b/tests/test_merged_cells.py @@ -1,23 +1,26 @@ import os + +from nose.tools import eq_ from pyexcel_xls import get_data from pyexcel_xls.xlsr import MergedCell -from nose.tools import eq_ def test_merged_cells(): data = get_data( get_fixture("merged-cell-sheet.xls"), detect_merged_cells=True, - library="pyexcel-xls") + library="pyexcel-xls", + ) expected = [[1, 2, 3], [1, 5, 6], [1, 8, 9], [10, 11, 11]] - eq_(data['Sheet1'], expected) + eq_(data["Sheet1"], expected) def test_complex_merged_cells(): data = get_data( get_fixture("complex-merged-cells-sheet.xls"), detect_merged_cells=True, - library="pyexcel-xls") + library="pyexcel-xls", + ) expected = [ [1, 1, 2, 3, 15, 16, 22, 22, 24, 24], [1, 1, 4, 5, 15, 17, 22, 22, 24, 24], @@ -26,16 +29,17 @@ def test_complex_merged_cells(): [13, 11, 11, 14, 20, 20, 23, 23, 24, 24], [21, 21, 21, 21, 21, 21, 23, 23, 24, 24], [25, 25, 25, 25, 25, 25, 25, 25, 25, 25], - [25, 25, 25, 25, 25, 25, 25, 25, 25, 25] + [25, 25, 25, 25, 25, 25, 25, 25, 25, 25], ] - eq_(data['Sheet1'], expected) + eq_(data["Sheet1"], expected) def test_exploration(): data = get_data( get_fixture("merged-sheet-exploration.xls"), detect_merged_cells=True, - library="pyexcel-xls") + library="pyexcel-xls", + ) expected_sheet1 = [ [1, 1, 1, 1, 1, 1], [2], @@ -46,28 +50,23 @@ def test_exploration(): [2], [2], [2], - [2]] - eq_(data['Sheet1'], expected_sheet1) - expected_sheet2 = [ - [3], - [3], - [3], - [3, 4, 4, 4, 4, 4, 4], - [3], - [3], - [3]] - eq_(data['Sheet2'], expected_sheet2) + [2], + ] + eq_(data["Sheet1"], expected_sheet1) + expected_sheet2 = [[3], [3], [3], [3, 4, 4, 4, 4, 4, 4], [3], [3], [3]] + eq_(data["Sheet2"], expected_sheet2) expected_sheet3 = [ - ['', '', '', '', '', 2, 2, 2], + ["", "", "", "", "", 2, 2, 2], [], [], [], - ['', '', '', 5], - ['', '', '', 5], - ['', '', '', 5], - ['', '', '', 5], - ['', '', '', 5]] - eq_(data['Sheet3'], expected_sheet3) + ["", "", "", 5], + ["", "", "", 5], + ["", "", "", 5], + ["", "", "", 5], + ["", "", "", 5], + ] + eq_(data["Sheet3"], expected_sheet3) def test_merged_cell_class(): @@ -75,10 +74,9 @@ def test_merged_cell_class(): merged_cell = MergedCell(1, 4, 1, 4) merged_cell.register_cells(test_dict) keys = sorted(list(test_dict.keys())) - expected = ['1-1', '1-2', '1-3', '2-1', - '2-2', '2-3', '3-1', '3-2', '3-3'] + expected = ["1-1", "1-2", "1-3", "2-1", "2-2", "2-3", "3-1", "3-2", "3-3"] eq_(keys, expected) - eq_(merged_cell, test_dict['3-1']) + eq_(merged_cell, test_dict["3-1"]) def get_fixture(file_name): diff --git a/tests/test_multiple_sheets.py b/tests/test_multiple_sheets.py index d20dc61..3f526f7 100644 --- a/tests/test_multiple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -1,9 +1,11 @@ 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: @@ -31,8 +33,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.xls" @@ -45,12 +46,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): @@ -219,18 +220,17 @@ class TestMultiSheetReader: self.testfile = "file_with_an_empty_sheet.xls" 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_stringio.py b/tests/test_stringio.py index 8e9a1a1..e1aa055 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 +from nose.tools import eq_ + class TestStringIO: - def test_xls_stringio(self): testfile = "cute.xls" create_sample_file1(testfile) with open(testfile, "rb") as f: content = f.read() - r = pyexcel.get_sheet(file_type="xls", file_content=content, - library="pyexcel-xls") - result = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 1.1, 1] + r = pyexcel.get_sheet( + file_type="xls", file_content=content, library="pyexcel-xls" + ) + 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_xls_output_stringio(self): - data = [ - [1, 2, 3], - [4, 5, 6] - ] - io = pyexcel.save_as(dest_file_type="xls", - array=data) - r = pyexcel.get_sheet(file_type="xls", file_content=io.getvalue(), - library="pyexcel-xls") + data = [[1, 2, 3], [4, 5, 6]] + io = pyexcel.save_as(dest_file_type="xls", array=data) + r = pyexcel.get_sheet( + file_type="xls", file_content=io.getvalue(), library="pyexcel-xls" + ) 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 a045814..6ae707b 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,15 +1,17 @@ import os -from pyexcel_xls.xlsw import XLSWriter as Writer -from pyexcel_xls.xlsr import XLSBook as Reader + from base import PyexcelWriterBase, PyexcelHatWriterBase +from pyexcel_xls.xlsr import XLSBook as Reader +from pyexcel_xls.xlsw import XLSWriter as Writer + class TestNativeXLSWriter: def test_write_book(self): 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.xls" writer = Writer() From 942c53ddc5e47e932da2e0749e2520294cffefb6 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 8 Nov 2019 20:21:41 +0000 Subject: [PATCH 097/163] :handshake: synchronize with latest pyexcel-mobans and pypi-mobans --- .gitignore | 38 +++++- .../{README.rst => custom_README.rst.jj2} | 0 .moban.d/{setup.py => custom_setup.py.jj2} | 0 .../tests/{base.py => custom_base.py.jj2} | 0 ...ements.txt => custom_requirements.txt.jj2} | 0 .moban.d/{travis.yml => xls_travis.yml.jj2} | 0 .moban.yml | 26 ++-- .travis.yml | 56 +++++++- CHANGELOG.rst | 63 +++------ MANIFEST.in | 2 + README.rst | 29 +--- docs/source/conf.py | 129 ++---------------- pyexcel_xls/__init__.py | 10 +- setup.py | 111 +++++++++------ test.bat | 2 +- test.sh | 2 +- tests/test_bug_fixes.py | 6 +- tests/test_hidden.py | 3 +- tests/test_merged_cells.py | 3 +- tests/test_writer.py | 1 - 20 files changed, 216 insertions(+), 265 deletions(-) rename .moban.d/{README.rst => custom_README.rst.jj2} (100%) rename .moban.d/{setup.py => custom_setup.py.jj2} (100%) rename .moban.d/tests/{base.py => custom_base.py.jj2} (100%) rename .moban.d/tests/{requirements.txt => custom_requirements.txt.jj2} (100%) rename .moban.d/{travis.yml => xls_travis.yml.jj2} (100%) 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/custom_README.rst.jj2 similarity index 100% rename from .moban.d/README.rst rename to .moban.d/custom_README.rst.jj2 diff --git a/.moban.d/setup.py b/.moban.d/custom_setup.py.jj2 similarity index 100% rename from .moban.d/setup.py rename to .moban.d/custom_setup.py.jj2 diff --git a/.moban.d/tests/base.py b/.moban.d/tests/custom_base.py.jj2 similarity index 100% rename from .moban.d/tests/base.py rename to .moban.d/tests/custom_base.py.jj2 diff --git a/.moban.d/tests/requirements.txt b/.moban.d/tests/custom_requirements.txt.jj2 similarity index 100% rename from .moban.d/tests/requirements.txt rename to .moban.d/tests/custom_requirements.txt.jj2 diff --git a/.moban.d/travis.yml b/.moban.d/xls_travis.yml.jj2 similarity index 100% rename from .moban.d/travis.yml rename to .moban.d/xls_travis.yml.jj2 diff --git a/.moban.yml b/.moban.yml index c0d7ab1..ce1cd98 100644 --- a/.moban.yml +++ b/.moban.yml @@ -1,31 +1,29 @@ -requires: - - type: git - url: https://github.com/moremoban/pypi-mobans - submodule: true - - https://github.com/pyexcel/pyexcel-mobans configuration: - configuration_dir: "pyexcel-mobans:config" + configuration_dir: "git://github.com/pyexcel/pyexcel-mobans!/config" template_dir: - - "pyexcel-mobans:templates" - - "pypi-mobans:templates" + - "git://github.com/moremoban/pypi-mobans.git?branch=dev&submodule=true!/templates" + - "git://github.com/pyexcel/pyexcel-mobans.git!/templates" + - "git://github.com/pyexcel/pyexcel-mobans.git!/statics" - ".moban.d" configuration: pyexcel-xls.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 - - requirements.txt: requirements.txt + - .travis.yml: xls_travis.yml.jj2 + - requirements.txt: requirements.txt.jj2 - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 - - "tests/requirements.txt": "tests/requirements.txt" + - "tests/requirements.txt": "tests/custom_requirements.txt.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.jj2" - "tests/test_stringio.py": "tests/test_stringio.py.jj2" - "tests/test_writer.py": "tests/test_writer.py.jj2" - - "tests/base.py": "tests/base.py" + - "tests/base.py": "tests/custom_base.py.jj2" - output: CHANGELOG.rst configuration: changelog.yml template: CHANGELOG.rst.jj2 + - ".github/FUNDING.yml": "FUNDING.yml" + - ".github/PULL_REQUEST_TEMPLATE.md": PULL_REQUEST_TEMPLATE.md diff --git a/.travis.yml b/.travis.yml index 5817466..322b461 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,15 @@ sudo: false +dist: xenial language: python notifications: email: false python: - - pypy-5.3.1 - - 3.7-dev + - &pypy2 pypy2.7-6.0 + - &pypy3 pypy3.5-6.0 + - 3.8-dev + - 3.7 - 3.6 - 3.5 - - 3.4 - 2.7 matrix: include: @@ -24,13 +26,57 @@ matrix: - python-coverage - python-nose - python-mock + +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 [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install ordereddict; fi - - 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 - - test ! -f rnd_requirements.txt || pip install --no-deps -r rnd_requirements.txt + - 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: diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e4677db..9f16100 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,8 +4,7 @@ Change log 0.5.8 - 22.08.2018 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. `pyexcel#151 `_, read cell error as #N/A. @@ -13,8 +12,7 @@ Added 0.5.7 - 15.03.2018 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. `pyexcel#54 `_, Book.datemode attribute of that workbook should be passed always. @@ -22,8 +20,7 @@ Added 0.5.6 - 15.03.2018 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. `pyexcel#120 `_, xlwt cannot save a book without any sheet. So, let's raise an exception in this case in @@ -32,8 +29,7 @@ Added 0.5.5 - 8.11.2017 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. `#25 `_, detect merged cell in .xls @@ -41,8 +37,7 @@ Added 0.5.4 - 2.11.2017 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. `#24 `_, xlsx format cannot use skip_hidden_row_and_column. please use pyexcel-xlsx instead. @@ -50,8 +45,7 @@ Added 0.5.3 - 2.11.2017 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. `#21 `_, skip hidden rows and columns under 'skip_hidden_row_and_column' flag. @@ -59,8 +53,7 @@ Added 0.5.2 - 23.10.2017 -------------------------------------------------------------------------------- -updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**updated** #. pyexcel `pyexcel#105 `_, remove gease from setup_requires, introduced by 0.5.1. @@ -70,8 +63,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 @@ -80,8 +72,7 @@ added 0.5.0 - 30.08.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `#20 `_, is handled in pyexcel-io @@ -91,8 +82,7 @@ Updated 0.4.1 - 25.08.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `#20 `_, handle unseekable stream given by http response. @@ -100,8 +90,7 @@ Updated 0.4.0 - 19.06.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `pyexcel-xlsx#15 `_, close file handle @@ -111,8 +100,7 @@ Updated 0.3.3 - 30/05/2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `#18 `_, pass on encoding_override and others to xlrd. @@ -120,8 +108,7 @@ Updated 0.3.2 - 18.05.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `#16 `_, allow mmap to be passed as file content @@ -129,8 +116,7 @@ Updated 0.3.1 - 16.01.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `#14 `_, Python 3.6 - cannot use LOCALE flag with a str pattern @@ -139,8 +125,7 @@ Updated 0.3.0 - 22.12.2016 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `#13 `_, alert on empyty file content @@ -149,8 +134,7 @@ Updated 0.2.3 - 20.09.2016 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `#10 `_, To support generator as member of the incoming two dimensional data @@ -158,8 +142,7 @@ Updated 0.2.2 - 31.08.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. support pagination. two pairs: start_row, row_limit and start_column, column_limit help you deal with large files. @@ -167,8 +150,7 @@ Added 0.2.1 - 13.07.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. `#9 `_, `skip_hidden_sheets` is added. By default, hidden sheets are skipped when reading all sheets. @@ -177,8 +159,7 @@ 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`. @@ -186,8 +167,7 @@ Added other libraries, in the situation where there are more than one plugin for a file type, e.g. xlsm -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. support the auto-import feature of pyexcel-io 0.2.0 #. xlwt is now used for python 2 implementation while xlwt-future is used for @@ -196,8 +176,7 @@ Updated 0.1.0 - 17.01.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. Passing "streaming=True" to get_data, you will get the two dimensional array as a generator 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 d2b5ea5..a306087 100644 --- a/README.rst +++ b/README.rst @@ -2,20 +2,12 @@ pyexcel-xls - Let you focus on data, instead of xls 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 - -.. image:: https://travis-ci.org/pyexcel/pyexcel-xls.svg?branch=master +.. image:: https://api.travis-ci.org/pyexcel/pyexcel-xls.svg :target: http://travis-ci.org/pyexcel/pyexcel-xls -.. image:: https://codecov.io/gh/pyexcel/pyexcel-xls/branch/master/graph/badge.svg - :target: https://codecov.io/gh/pyexcel/pyexcel-xls +.. image:: https://codecov.io/github/pyexcel/pyexcel-xls/coverage.png + :target: https://codecov.io/github/pyexcel/pyexcel-xls -.. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg - :target: https://gitter.im/pyexcel/Lobby **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. @@ -53,7 +45,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. @@ -348,8 +340,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 @@ -362,17 +352,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 -#. Please update CHANGELOG.rst -#. Please add yourself to CONTRIBUTORS.rst -#. Agree on NEW BSD License for your contribution - Known Issues ============= diff --git a/docs/source/conf.py b/docs/source/conf.py index e840796..2b391c5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -4,13 +4,11 @@ DESCRIPTION = ( ' reads xlsx and xlsm 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 +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- @@ -24,22 +22,16 @@ DESCRIPTION = ( # -- Project information ----------------------------------------------------- -project = u'pyexcel-xls' -copyright = u'2015-2018 Onni Software Ltd.' -author = u'C.W.' - +project = 'pyexcel-xls' +copyright = ' Onni Software Ltd.' +author = 'C.W.' # The short X.Y version -version = u'0.5.8' +version = '0.6.0' # The full version, including alpha/beta/rc tags -release = u'0.6.0' - +release = '0.5.8' # -- 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. @@ -48,15 +40,6 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext. # 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. # @@ -69,9 +52,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 = None - # -- Options for HTML output ------------------------------------------------- @@ -80,107 +60,16 @@ pygments_style = None # 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-xlsdoc' - - -# -- 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-xls.tex', u'pyexcel-xls 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-xls', u'pyexcel-xls 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-xls', u'pyexcel-xls Documentation', - author, 'pyexcel-xls', '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} +intersphinx_mapping = {'https://docs.python.org/3/': None} # TODO: html_theme not configurable upstream html_theme = 'default' diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index c2175cb..f512cfc 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -7,15 +7,15 @@ :copyright: (c) 2016-2017 by Onni Software Ltd :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 save_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, - save_data as write_data, -) __FILE_TYPE__ = "xls" IOPluginInfoChain(__name__).add_a_reader( diff --git a/setup.py b/setup.py index f6238c9..ced62af 100644 --- a/setup.py +++ b/setup.py @@ -1,66 +1,86 @@ #!/usr/bin/env python3 -# Template by pypi-mobans import os import sys +# Template by pypi-mobans import codecs +import locale +import platform from shutil import rmtree from setuptools import Command, setup, find_packages PY2 = sys.version_info[0] == 2 PY26 = PY2 and sys.version_info[1] < 7 +PY33 = sys.version_info < (3, 4) -NAME = 'pyexcel-xls' -AUTHOR = 'C.W.' -VERSION = '0.6.0' -EMAIL = 'wangc_2011@hotmail.com' -LICENSE = 'New BSD' +# 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-xls" +AUTHOR = "C.W." +VERSION = "0.6.0" +EMAIL = "info@pyexcel.org" +LICENSE = "New BSD" DESCRIPTION = ( - 'A wrapper library to read, manipulate and write data in xls format. It' + - 'reads xlsx and xlsm format' + "A wrapper library to read, manipulate and write data in xls format. It" + + "reads xlsx and xlsm format" ) -URL = 'https://github.com/pyexcel/pyexcel-xls' -DOWNLOAD_URL = '%s/archive/0.5.8.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +URL = "https://github.com/pyexcel/pyexcel-xls" +DOWNLOAD_URL = "%s/archive/0.5.8.tar.gz" % URL +FILES = ["README.rst", "CHANGELOG.rst"] KEYWORDS = [ - 'python', + "python", 'xls', 'xlsx', 'xlsm' ] 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", + 'Programming Language :: Python :: Implementation :: PyPy' ] INSTALL_REQUIRES = [ - 'pyexcel-io>=0.5.3', - 'xlrd', - 'xlwt', + "pyexcel-io>=0.5.3", + "xlrd", + "xlwt", ] 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-xls v0.5.8 ' + +PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) +GS_COMMAND = ("gs pyexcel-xls v0.5.8 " + "Find 0.5.8 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__)) @@ -69,13 +89,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 @@ -85,14 +105,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_xls.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_xls.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 @@ -100,13 +120,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 }) @@ -135,7 +155,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 @@ -144,11 +164,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() @@ -158,15 +178,16 @@ 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, author=AUTHOR, version=VERSION, @@ -178,7 +199,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.bat b/test.bat index 351d266..823adb3 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls diff --git a/test.sh b/test.sh index 351d266..823adb3 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index ee0f668..d298374 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -9,13 +9,13 @@ import datetime import pyexcel as pe from _compact import OrderedDict +from pyexcel_xls import save_data +from pyexcel_xls.xlsr import xldate_to_python_date +from pyexcel_xls.xlsw import XLSWriter as Writer from mock import patch from nose import SkipTest from nose.tools import eq_, raises -from pyexcel_xls import save_data -from pyexcel_xls.xlsr import xldate_to_python_date -from pyexcel_xls.xlsw import XLSWriter as Writer IN_TRAVIS = "TRAVIS" in os.environ diff --git a/tests/test_hidden.py b/tests/test_hidden.py index aa72f9c..62d6c29 100644 --- a/tests/test_hidden.py +++ b/tests/test_hidden.py @@ -1,8 +1,9 @@ import os -from nose.tools import eq_ from pyexcel_xls import get_data +from nose.tools import eq_ + def test_simple_hidden_sheets(): data = get_data( diff --git a/tests/test_merged_cells.py b/tests/test_merged_cells.py index d4744e5..6f243ac 100644 --- a/tests/test_merged_cells.py +++ b/tests/test_merged_cells.py @@ -1,9 +1,10 @@ import os -from nose.tools import eq_ from pyexcel_xls import get_data from pyexcel_xls.xlsr import MergedCell +from nose.tools import eq_ + def test_merged_cells(): data = get_data( diff --git a/tests/test_writer.py b/tests/test_writer.py index 6ae707b..e36454a 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,7 +1,6 @@ import os from base import PyexcelWriterBase, PyexcelHatWriterBase - from pyexcel_xls.xlsr import XLSBook as Reader from pyexcel_xls.xlsw import XLSWriter as Writer From 7ee28ebfa12643ccbab6a2f2d823ed86cb55797a Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 8 Nov 2019 20:27:43 +0000 Subject: [PATCH 098/163] :books: update badges --- README.rst | 23 ++++++++++++++++++++--- pyexcel-xls.yml | 1 + 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index a306087..eac2b0a 100644 --- a/README.rst +++ b/README.rst @@ -2,12 +2,29 @@ pyexcel-xls - Let you focus on data, instead of xls format ================================================================================ -.. image:: https://api.travis-ci.org/pyexcel/pyexcel-xls.svg +.. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png + :target: https://www.patreon.com/chfw + +.. image:: https://travis-ci.org/pyexcel/pyexcel-xls.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-xls -.. image:: https://codecov.io/github/pyexcel/pyexcel-xls/coverage.png - :target: https://codecov.io/github/pyexcel/pyexcel-xls +.. image:: https://codecov.io/gh/pyexcel/pyexcel-xls/branch/master/graph/badge.svg + :target: https://codecov.io/gh/pyexcel/pyexcel-xls +.. image:: https://badge.fury.io/py/pyexcel-xls.svg + :target: https://pypi.org/project/pyexcel-xls + +.. image:: https://anaconda.org/conda-forge/pyexcel-xls/badges/version.svg + :target: https://anaconda.org/conda-forge/pyexcel-xls + +.. image:: https://pepy.tech/badge/pyexcel-xls/month + :target: https://pepy.tech/project/pyexcel-xls/month + +.. image:: https://anaconda.org/conda-forge/pyexcel-xls/badges/downloads.svg + :target: https://anaconda.org/conda-forge/pyexcel-xls + +.. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg + :target: https://gitter.im/pyexcel/Lobby **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 28fbf55..519666d 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -5,6 +5,7 @@ version: 0.6.0 current_version: 0.6.0 release: 0.5.8 file_type: xls +is_on_conda: true dependencies: - pyexcel-io>=0.5.3 - xlrd From eb6d1d7b72c1e506fd43722bb1cfa56bc0dc7d14 Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 8 Nov 2019 20:29:38 +0000 Subject: [PATCH 099/163] :books: update sponsorship --- .github/FUNDING.yml | 4 ++++ .github/PULL_REQUEST_TEMPLATE.md | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md 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 From 5f6cc3e1e9869c43595b12841920c7d9cf57a3a7 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 10 Nov 2019 11:31:18 +0000 Subject: [PATCH 100/163] :sparkles: use inherited mobanfile. https://github.com/moremoban/moban/pull/348 --- .moban.yml | 15 +-------------- LICENSE | 6 +++--- docs/source/conf.py | 3 ++- test.sh | 1 + 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/.moban.yml b/.moban.yml index ce1cd98..412ecf0 100644 --- a/.moban.yml +++ b/.moban.yml @@ -1,29 +1,16 @@ +overrides: "git://github.com/pyexcel/pyexcel-mobans!/mobanfile.yaml" configuration: - configuration_dir: "git://github.com/pyexcel/pyexcel-mobans!/config" - template_dir: - - "git://github.com/moremoban/pypi-mobans.git?branch=dev&submodule=true!/templates" - - "git://github.com/pyexcel/pyexcel-mobans.git!/templates" - - "git://github.com/pyexcel/pyexcel-mobans.git!/statics" - - ".moban.d" configuration: pyexcel-xls.yml targets: - README.rst: custom_README.rst.jj2 - setup.py: custom_setup.py.jj2 - "docs/source/conf.py": "docs/source/conf.py.jj2" - .travis.yml: xls_travis.yml.jj2 - - requirements.txt: requirements.txt.jj2 - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 - "tests/requirements.txt": "tests/custom_requirements.txt.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.jj2" - "tests/test_stringio.py": "tests/test_stringio.py.jj2" - "tests/test_writer.py": "tests/test_writer.py.jj2" - "tests/base.py": "tests/custom_base.py.jj2" - - output: CHANGELOG.rst - configuration: changelog.yml - template: CHANGELOG.rst.jj2 - - ".github/FUNDING.yml": "FUNDING.yml" - - ".github/PULL_REQUEST_TEMPLATE.md": PULL_REQUEST_TEMPLATE.md diff --git a/LICENSE b/LICENSE index 4066e82..3225ede 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2017 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 @@ -13,7 +13,7 @@ that the following conditions are met: and/or other materials provided with the distribution. * Neither the name of 'pyexcel-xls' 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/docs/source/conf.py b/docs/source/conf.py index 2b391c5..90a3f45 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,7 @@ DESCRIPTION = ( # -- Project information ----------------------------------------------------- project = 'pyexcel-xls' -copyright = ' Onni Software Ltd.' +copyright = '2015-2019 Onni Software Ltd.' author = 'C.W.' # The short X.Y version version = '0.6.0' @@ -84,3 +84,4 @@ texinfo_documents = [ intersphinx_mapping.update({ 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), }) +master_doc = "index" diff --git a/test.sh b/test.sh index 823adb3..fda8353 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,3 @@ +#/bin/bash pip freeze nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls From 376bb595944bd94ae31344b1d819ae82c2bdd368 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 12 Nov 2019 19:40:34 +0000 Subject: [PATCH 101/163] :newspaper: add mising files --- .isort.cfg | 10 ++++++++++ lint.sh | 2 ++ 2 files changed, 12 insertions(+) create mode 100644 .isort.cfg create mode 100644 lint.sh diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..8bdda20 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,10 @@ +[settings] +line_length=79 +known_first_party=pyexcel,xlrd,xlwt +known_third_party=mock,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/lint.sh b/lint.sh new file mode 100644 index 0000000..976f745 --- /dev/null +++ b/lint.sh @@ -0,0 +1,2 @@ +pip install flake8 +flake8 . --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long \ No newline at end of file From 8239c34980c7b60e60cd58e14502487ba71da085 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 12 Nov 2019 19:49:46 +0000 Subject: [PATCH 102/163] :fire: remove test file generation --- .moban.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.moban.yml b/.moban.yml index 412ecf0..2af1b28 100644 --- a/.moban.yml +++ b/.moban.yml @@ -9,8 +9,3 @@ targets: - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 - "tests/requirements.txt": "tests/custom_requirements.txt.jj2" - - "tests/test_filter.py": "tests/test_filter.py.jj2" - - "tests/test_formatters.py": "tests/test_formatters.py.jj2" - - "tests/test_stringio.py": "tests/test_stringio.py.jj2" - - "tests/test_writer.py": "tests/test_writer.py.jj2" - - "tests/base.py": "tests/custom_base.py.jj2" From 4410c1e7e7eb33f79dcc92fe8a1edd64e13d95e5 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 12 Nov 2019 19:55:11 +0000 Subject: [PATCH 103/163] :newspaper: custom setup --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index ced62af..679e5d4 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 +import os import platform +import sys from shutil import rmtree -from setuptools import Command, setup, find_packages +from setuptools import Command, find_packages, setup PY2 = sys.version_info[0] == 2 PY26 = PY2 and sys.version_info[1] < 7 From a3aad6d9fea52d79346d88e34cfc6abf0cb04898 Mon Sep 17 00:00:00 2001 From: chfw Date: Mon, 8 Jun 2020 22:47:48 +0100 Subject: [PATCH 104/163] :handshake: synchronize the organisational meta data --- .github/PULL_REQUEST_TEMPLATE.md | 2 ++ .gitignore | 46 ++++++++++++++++++++++--- .travis.yml | 23 ++++--------- README.rst | 58 +++++++++++++++++++------------- setup.py | 17 +++++----- 5 files changed, 93 insertions(+), 53 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 322b461..4522c91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ notifications: python: - &pypy2 pypy2.7-6.0 - &pypy3 pypy3.5-6.0 - - 3.8-dev + - 3.8 - 3.7 - 3.6 - 3.5 @@ -32,33 +32,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/README.rst b/README.rst index eac2b0a..9d375bd 100644 --- a/README.rst +++ b/README.rst @@ -5,6 +5,9 @@ pyexcel-xls - Let you focus on data, instead of xls 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-xls.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-xls @@ -34,6 +37,24 @@ New flag: `detect_merged_cells` allows you to spread the same value among all me New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. +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 ================== @@ -58,24 +79,6 @@ or clone it and install it: $ cd pyexcel-xls $ 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 ================================================================================ @@ -351,18 +354,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/setup.py b/setup.py index 679e5d4..6329e0b 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,17 @@ #!/usr/bin/env python3 -# Template by pypi-mobans +""" +Template by pypi-mobans +""" + +import os +import sys import codecs import locale -import os import platform -import sys from shutil import rmtree -from setuptools import Command, find_packages, setup +from setuptools import Command, setup, find_packages PY2 = sys.version_info[0] == 2 PY26 = PY2 and sys.version_info[1] < 7 @@ -56,14 +59,13 @@ CLASSIFIERS = [ "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", 'Programming Language :: Python :: Implementation :: PyPy' ] + INSTALL_REQUIRES = [ "pyexcel-io>=0.5.3", "xlrd", @@ -71,8 +73,7 @@ INSTALL_REQUIRES = [ ] 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 From e4870b0a740ea1c8d621284156874d93b844dd03 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 23 Aug 2020 01:23:06 +0100 Subject: [PATCH 105/163] :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 | 7 +++++++ Makefile | 18 ++++++++++++++---- README.rst | 16 ---------------- docs/source/conf.py | 2 +- lint.sh | 3 ++- setup.py | 2 +- tests/requirements.txt | 8 ++++---- 10 files changed, 84 insertions(+), 30 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..7d1b0c8 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-xls.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..c8e37ad --- /dev/null +++ b/CONTRIBUTORS.rst @@ -0,0 +1,7 @@ + +1 contributors +================================================================================ + +In alphabetical order: + +* `John Vandenberg `_ diff --git a/Makefile b/Makefile index 54d3bf5..d7e640e 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,19 @@ all: test -test: +test: lint bash test.sh +install_test: + pip install -r tests/requirements.txt + +git-diff-check: + git diff --exit-code + +lint: + bash lint.sh + format: - isort -y $(find pyexcel_xls -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) - black -l 79 pyexcel_xls - black -l 79 tests + bash format.sh + +git-diff-check: + git diff --exit-code diff --git a/README.rst b/README.rst index 9d375bd..fdde2e0 100644 --- a/README.rst +++ b/README.rst @@ -365,22 +365,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. - Known Issues ============= diff --git a/docs/source/conf.py b/docs/source/conf.py index 90a3f45..7776da0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -24,7 +24,7 @@ DESCRIPTION = ( project = 'pyexcel-xls' copyright = '2015-2019 Onni Software Ltd.' -author = 'C.W.' +author = 'chfw' # 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 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/setup.py b/setup.py index 6329e0b..2cb73a8 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ except (ValueError, UnicodeError, locale.Error): locale.setlocale(locale.LC_ALL, "en_US.UTF-8") NAME = "pyexcel-xls" -AUTHOR = "C.W." +AUTHOR = "chfw" VERSION = "0.6.0" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" diff --git a/tests/requirements.txt b/tests/requirements.txt index a2a17f7..0c3a80f 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,8 +3,8 @@ mock;python_version<"3" codecov coverage flake8 -pyexcel -xlrd==1.1.0 +black +isort +collective.checkdocs +pygments moban -black;python_version>="3.6" -isort;python_version>="3.6" From 82b5759610cd4e856a4cf2a3605702074e798011 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 23 Aug 2020 00:23:39 +0000 Subject: [PATCH 106/163] 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..a8ae3f1 --- /dev/null +++ b/format.sh @@ -0,0 +1,3 @@ +isort $(find pyexcel_xls -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) +black -l 79 pyexcel_xls +black -l 79 tests From 02c7111146b0a7566ca77af2119efaa1d25484a1 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 29 Aug 2020 21:39:29 +0100 Subject: [PATCH 107/163] :sparkles: add contributors list --- .moban.d/custom_setup.py.jj2 | 2 ++ MANIFEST.in | 1 + setup.py | 2 +- tests/requirements.txt | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.moban.d/custom_setup.py.jj2 b/.moban.d/custom_setup.py.jj2 index 8fc8de0..81aed01 100644 --- a/.moban.d/custom_setup.py.jj2 +++ b/.moban.d/custom_setup.py.jj2 @@ -9,6 +9,8 @@ 'xlsm' {%endblock%} +{% block morefiles %}"CONTRIBUTORS.rst",{% endblock %} + {%block additional_classifiers%} 'Programming Language :: Python :: Implementation :: PyPy' {%endblock%} 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/setup.py b/setup.py index 2cb73a8..3aee597 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ DESCRIPTION = ( ) URL = "https://github.com/pyexcel/pyexcel-xls" DOWNLOAD_URL = "%s/archive/0.5.8.tar.gz" % URL -FILES = ["README.rst", "CHANGELOG.rst"] +FILES = ["README.rst","CONTRIBUTORS.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", 'xls', diff --git a/tests/requirements.txt b/tests/requirements.txt index 0c3a80f..c0bd2f4 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -8,3 +8,4 @@ isort collective.checkdocs pygments moban +moban_jinja2_github From 2dab3e93c179648b4908ea4ae289dd4bb158c17e Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 29 Aug 2020 21:39:55 +0100 Subject: [PATCH 108/163] :newspaper: add format.sh --- format.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 format.sh diff --git a/format.sh b/format.sh new file mode 100644 index 0000000..a8ae3f1 --- /dev/null +++ b/format.sh @@ -0,0 +1,3 @@ +isort $(find pyexcel_xls -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) +black -l 79 pyexcel_xls +black -l 79 tests From 63676c382b76eb9d847cc30ec032f3aafd059fce Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 29 Aug 2020 23:38:27 +0100 Subject: [PATCH 110/163] :egg: :ferris_wheel: release 0.5.9 --- .github/workflows/pythonpublish.yml | 26 ++++++++++++++++++++++++++ CHANGELOG.rst | 8 ++++++++ MANIFEST.in | 2 ++ setup.py | 8 ++++---- 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/pythonpublish.yml 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/CHANGELOG.rst b/CHANGELOG.rst index e4677db..bca579a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Change log ================================================================================ +0.5.9 - 29.08.2020 +-------------------------------------------------------------------------------- +Added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `pyexcel-xls#35 `_, include +tests + 0.5.8 - 22.08.2018 -------------------------------------------------------------------------------- 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/setup.py b/setup.py index 92b2a0e..a10a4ba 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.8' +VERSION = '0.5.9' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -19,7 +19,7 @@ DESCRIPTION = ( 'reads xlsx and xlsm format' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -DOWNLOAD_URL = '%s/archive/0.5.8.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.9.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', @@ -55,8 +55,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-xls v0.5.8 ' + - "Find 0.5.8 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls v0.5.9 ' + + "Find 0.5.9 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') UPLOAD_FAILED_MSG = ( From 6a5a8516ac8b93056e418161307774f3439d2ea1 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 29 Aug 2020 23:44:41 +0100 Subject: [PATCH 111/163] :books: update change log --- CHANGELOG.rst | 71 +++++---------------------------------------------- 1 file changed, 7 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bca579a..54af2ad 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,7 +4,7 @@ Change log -------------------------------------------------------------------------------- Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. `pyexcel-xls#35 `_, include tests @@ -13,7 +13,7 @@ tests -------------------------------------------------------------------------------- Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. `pyexcel#151 `_, read cell error as #N/A. @@ -22,7 +22,7 @@ Added -------------------------------------------------------------------------------- Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. `pyexcel#54 `_, Book.datemode attribute of that workbook should be passed always. @@ -31,7 +31,7 @@ Added -------------------------------------------------------------------------------- Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. `pyexcel#120 `_, xlwt cannot save a book without any sheet. So, let's raise an exception in this case in @@ -41,7 +41,7 @@ Added -------------------------------------------------------------------------------- Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. `#25 `_, detect merged cell in .xls @@ -50,7 +50,7 @@ Added -------------------------------------------------------------------------------- Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. `#24 `_, xlsx format cannot use skip_hidden_row_and_column. please use pyexcel-xlsx instead. @@ -59,7 +59,7 @@ Added -------------------------------------------------------------------------------- Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. `#21 `_, skip hidden rows and columns under 'skip_hidden_row_and_column' flag. @@ -68,7 +68,6 @@ Added -------------------------------------------------------------------------------- updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. pyexcel `pyexcel#105 `_, remove gease from setup_requires, introduced by 0.5.1. @@ -79,7 +78,6 @@ updated -------------------------------------------------------------------------------- added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `pyexcel#103 `_, include LICENSE file in MANIFEST.in, meaning LICENSE file will appear in the released @@ -89,7 +87,6 @@ added -------------------------------------------------------------------------------- Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#20 `_, is handled in pyexcel-io @@ -100,7 +97,6 @@ Updated -------------------------------------------------------------------------------- Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#20 `_, handle unseekable stream given by http response. @@ -109,7 +105,6 @@ Updated -------------------------------------------------------------------------------- Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `pyexcel-xlsx#15 `_, close file handle @@ -120,7 +115,6 @@ Updated -------------------------------------------------------------------------------- Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#18 `_, pass on encoding_override and others to xlrd. @@ -129,7 +123,6 @@ Updated -------------------------------------------------------------------------------- Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#16 `_, allow mmap to be passed as file content @@ -138,7 +131,6 @@ Updated -------------------------------------------------------------------------------- Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#14 `_, Python 3.6 - cannot use LOCALE flag with a str pattern @@ -148,7 +140,6 @@ Updated -------------------------------------------------------------------------------- Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#13 `_, alert on empyty file content @@ -158,55 +149,7 @@ Updated -------------------------------------------------------------------------------- Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #. `#10 `_, To support generator as member of the incoming two dimensional data -0.2.2 - 31.08.2016 --------------------------------------------------------------------------------- - -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#. support pagination. two pairs: start_row, row_limit and start_column, - column_limit help you deal with large files. - -0.2.1 - 13.07.2016 --------------------------------------------------------------------------------- - -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#. `#9 `_, `skip_hidden_sheets` - is added. By default, hidden sheets are skipped when reading all sheets. - Reading sheet by name or by index are not affected. - -0.2.0 - 01.06.2016 --------------------------------------------------------------------------------- - -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-xls' was added so as to inform pyexcel to use it instead of - other libraries, in the situation where there are more than one plugin for a - file type, e.g. xlsm - -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#. support the auto-import feature of pyexcel-io 0.2.0 -#. xlwt is now used for python 2 implementation while xlwt-future is used for - python 3 - -0.1.0 - 17.01.2016 --------------------------------------------------------------------------------- - -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#. Passing "streaming=True" to get_data, you will get the two dimensional array - as a generator -#. Passing "data=your_generator" to save_data is acceptable too. From a07d3ca735756e23fdd20586fad1d0bb2a5dcf81 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 19 Sep 2020 19:34:13 +0100 Subject: [PATCH 112/163] :handshake: update meta data --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4522c91..cd0b2ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,7 +47,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 From fba69516be9df9e804ae2e282fd4c905396050df Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 19 Sep 2020 21:16:49 +0100 Subject: [PATCH 114/163] :fire: remove python tests lower than python 3.6 --- .moban.d/xls_travis.yml.jj2 | 28 +++------------------------- .travis.yml | 16 ---------------- 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/.moban.d/xls_travis.yml.jj2 b/.moban.d/xls_travis.yml.jj2 index e6ce23b..4e98375 100644 --- a/.moban.d/xls_travis.yml.jj2 +++ b/.moban.d/xls_travis.yml.jj2 @@ -1,29 +1,7 @@ {% extends "travis.yml.jj2" %} -{%block test_other_python_versions%} - 2.6 - - 3.3 - - 3.4 - - 3.5 - - pypy +{%block test_other_python_versions%} - 3.6 + - 3.7 + - 3.8 {%endblock%} -{%block extra_matrix%} -matrix: - include: - - python: 2.7 - dist: trusty - sudo: required - virtualenv: - system_site_packages: true - addons: - apt: - packages: - - python-xlwt - - python-xlrd - - python-coverage - - python-nose - - python-mock -{%endblock%} - -{%block custom_install %} - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install ordereddict; fi -{%endblock%} diff --git a/.travis.yml b/.travis.yml index cd0b2ed..06d4005 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,21 +11,6 @@ python: - 3.6 - 3.5 - 2.7 -matrix: - include: - - python: 2.7 - dist: trusty - sudo: required - virtualenv: - system_site_packages: true - addons: - apt: - packages: - - python-xlwt - - python-xlrd - - python-coverage - - python-nose - - python-mock stages: - lint @@ -60,7 +45,6 @@ jobs: stage: test before_install: - - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install ordereddict; fi - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then mv min_requirements.txt requirements.txt ; fi From 2459ede331809e114effddced065bf2300bd438a Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 20 Sep 2020 12:04:22 +0100 Subject: [PATCH 116/163] :fire: remove python tests lower than python 3.6 --- .moban.d/xls_travis.yml.jj2 | 7 ++++--- .travis.yml | 4 ---- pyexcel-xls.yml | 2 ++ tests/requirements.txt | 1 + 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.moban.d/xls_travis.yml.jj2 b/.moban.d/xls_travis.yml.jj2 index 4e98375..a62287f 100644 --- a/.moban.d/xls_travis.yml.jj2 +++ b/.moban.d/xls_travis.yml.jj2 @@ -1,7 +1,8 @@ {% extends "travis.yml.jj2" %} -{%block test_other_python_versions%} - - 3.6 - - 3.7 +{%block custom_python_versions%} +python: - 3.8 + - 3.7 + - 3.6 {%endblock%} diff --git a/.travis.yml b/.travis.yml index 06d4005..b457dd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,13 +4,9 @@ language: python notifications: email: false python: - - &pypy2 pypy2.7-6.0 - - &pypy3 pypy3.5-6.0 - 3.8 - 3.7 - 3.6 - - 3.5 - - 2.7 stages: - lint diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 519666d..c4b3ae1 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -10,4 +10,6 @@ dependencies: - pyexcel-io>=0.5.3 - xlrd - xlwt +test_dependencies: + - pyexcel description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format diff --git a/tests/requirements.txt b/tests/requirements.txt index c0bd2f4..3e19c2a 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -9,3 +9,4 @@ collective.checkdocs pygments moban moban_jinja2_github +pyexcel From d3b57b434b7a4920dcf02e2be5d054259e42736b Mon Sep 17 00:00:00 2001 From: jaska Date: Tue, 29 Sep 2020 22:26:05 +0100 Subject: [PATCH 118/163] New style io (#36) * :tada: new style reader * :tada: new style writer and reader plugins * This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst * :green_heart: update moban update * This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst * :green_heart: use pyexcel-io dev branch * :books: update PR template * :horse: code refactoring Co-authored-by: chfw --- .github/PULL_REQUEST_TEMPLATE.md | 6 +- .github/workflows/moban-update.yml | 42 +++++---- .gitignore | 4 + CONTRIBUTORS.rst | 2 +- Makefile | 3 - lint.sh | 3 +- pyexcel_xls/__init__.py | 21 ++++- pyexcel_xls/xlsr.py | 144 ++++++++++++----------------- pyexcel_xls/xlsw.py | 37 ++++---- rnd_requirements.txt | 2 +- tests/test_bug_fixes.py | 12 +-- tests/test_filter.py | 3 +- tests/test_writer.py | 8 +- 13 files changed, 133 insertions(+), 154 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7d1b0c8..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-xls.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 c8e37ad..bfd5904 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -4,4 +4,4 @@ In alphabetical order: -* `John Vandenberg `_ +* `John Vandenberg `_ 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_xls/__init__.py b/pyexcel_xls/__init__.py index f512cfc..a688b5b 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -4,7 +4,7 @@ The lower level xls/xlsx/xlsm file format handler using xlrd/xlwt - :copyright: (c) 2016-2017 by Onni Software Ltd + :copyright: (c) 2016-2020 by Onni Software Ltd :license: New BSD License """ @@ -15,15 +15,28 @@ from pyexcel_io.io import save_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 IOPluginInfoChainV2 __FILE_TYPE__ = "xls" -IOPluginInfoChain(__name__).add_a_reader( - relative_plugin_class_path="xlsr.XLSBook", + +IOPluginInfoChainV2(__name__).add_a_reader( + relative_plugin_class_path="xlsr.XLSInFile", + locations=["file"], + file_types=[__FILE_TYPE__, "xlsx", "xlsm"], + stream_type="binary", +).add_a_reader( + relative_plugin_class_path="xlsr.XLSInMemory", + locations=["memory"], + file_types=[__FILE_TYPE__, "xlsx", "xlsm"], + stream_type="binary", +).add_a_reader( + relative_plugin_class_path="xlsr.XLSInContent", + locations=["content"], file_types=[__FILE_TYPE__, "xlsx", "xlsm"], stream_type="binary", ).add_a_writer( relative_plugin_class_path="xlsw.XLSWriter", + locations=["file", "memory"], file_types=[__FILE_TYPE__], stream_type="binary", ) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index a6b9b97..7a635e9 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -4,17 +4,16 @@ The lower level xls/xlsm file format handler using xlrd - :copyright: (c) 2016-2017 by Onni Software Ltd + :copyright: (c) 2016-2020 by Onni Software Ltd :license: New BSD License """ import datetime import xlrd - -from pyexcel_io.book import BookReader -from pyexcel_io.sheet import SheetReader from pyexcel_io.service import has_no_digits_in_float -from pyexcel_io._compact import OrderedDict, irange +from pyexcel_io._compact import irange +from pyexcel_io.plugin_api.abstract_sheet import ISheet +from pyexcel_io.plugin_api.abstract_reader import IReader XLS_KEYWORDS = [ "filename", @@ -45,7 +44,7 @@ class MergedCell(object): registry[key] = self -class XLSheet(SheetReader): +class XLSheet(ISheet): """ xls, xlsx, xlsm sheet reader @@ -53,12 +52,13 @@ class XLSheet(SheetReader): """ def __init__(self, sheet, auto_detect_int=True, date_mode=0, **keywords): - SheetReader.__init__(self, sheet, **keywords) self.__auto_detect_int = auto_detect_int self.__hidden_cols = [] self.__hidden_rows = [] self.__merged_cells = {} self._book_date_mode = date_mode + self._native_sheet = sheet + self._keywords = keywords if keywords.get("detect_merged_cells") is True: for merged_cell_ranges in sheet.merged_cells: merged_cells = MergedCell(*merged_cell_ranges) @@ -75,17 +75,14 @@ class XLSheet(SheetReader): def name(self): return self._native_sheet.name - def number_of_rows(self): - """ - Number of rows in the xls sheet - """ - return self._native_sheet.nrows - len(self.__hidden_rows) + def row_iterator(self): + number_of_rows = self._native_sheet.nrows - len(self.__hidden_rows) + return range(number_of_rows) - def number_of_columns(self): - """ - Number of columns in the xls sheet - """ - return self._native_sheet.ncols - len(self.__hidden_cols) + def column_iterator(self, row): + number_of_columns = self._native_sheet.ncols - len(self.__hidden_cols) + for column in range(number_of_columns): + yield self.cell_value(row, column) def cell_value(self, row, column): """ @@ -127,93 +124,48 @@ def calculate_offsets(incoming_index, hidden_indices): return incoming_index + offset -class XLSBook(BookReader): +class XLSReader(IReader): """ XLSBook reader It reads xls, xlsm, xlsx work book """ - def __init__(self): - BookReader.__init__(self) - self._file_content = None - self.__skip_hidden_sheets = True - self.__skip_hidden_row_column = True - self.__detect_merged_cells = False - - def open(self, file_name, **keywords): - self.__parse_keywords(**keywords) - BookReader.open(self, file_name, **keywords) - - def open_stream(self, file_stream, **keywords): - self.__parse_keywords(**keywords) - BookReader.open_stream(self, file_stream, **keywords) - - def open_content(self, file_content, **keywords): - self.__parse_keywords(**keywords) - self._keywords = keywords - self._file_content = file_content - - def __parse_keywords(self, **keywords): + def __init__(self, file_type, **keywords): self.__skip_hidden_sheets = keywords.get("skip_hidden_sheets", True) self.__skip_hidden_row_column = keywords.get( "skip_hidden_row_and_column", True ) self.__detect_merged_cells = keywords.get("detect_merged_cells", False) + self._keywords = keywords + xlrd_params = self._extract_xlrd_params() + if self.__skip_hidden_row_column and file_type == "xls": + xlrd_params["formatting_info"] = True + if self.__detect_merged_cells: + xlrd_params["formatting_info"] = True + + self.content_array = [] + self._native_book = self.get_xls_book(**xlrd_params) + for sheet in self._native_book.sheets(): + if self.__skip_hidden_sheets and sheet.visibility != 0: + continue + self.content_array.append(sheet) + + def read_sheet(self, index): + native_sheet = self.content_array[index] + sheet = XLSheet( + native_sheet, + date_mode=self._native_book.datemode, + **self._keywords + ) + return sheet def close(self): if self._native_book: self._native_book.release_resources() self._native_book = None - def read_sheet_by_index(self, sheet_index): - self._native_book = self._get_book(on_demand=True) - sheet = self._native_book.sheet_by_index(sheet_index) - return self.read_sheet(sheet) - - def read_sheet_by_name(self, sheet_name): - self._native_book = self._get_book(on_demand=True) - try: - sheet = self._native_book.sheet_by_name(sheet_name) - except xlrd.XLRDError: - raise ValueError("%s cannot be found" % sheet_name) - return self.read_sheet(sheet) - - def read_all(self): - result = OrderedDict() - self._native_book = self._get_book() - for sheet in self._native_book.sheets(): - if self.__skip_hidden_sheets and sheet.visibility != 0: - continue - data_dict = self.read_sheet(sheet) - result.update(data_dict) - return result - - def read_sheet(self, native_sheet): - sheet = XLSheet( - native_sheet, - date_mode=self._native_book.datemode, - **self._keywords - ) - return {sheet.name: sheet.to_array()} - - def _get_book(self, on_demand=False): - xlrd_params = self._extract_xlrd_params() - xlrd_params["on_demand"] = on_demand - - if self._file_name: - xlrd_params["filename"] = self._file_name - elif self._file_stream: - file_content = self._file_stream.read() - xlrd_params["file_contents"] = file_content - elif self._file_content is not None: - xlrd_params["file_contents"] = self._file_content - else: - raise IOError("No valid file name or file content found.") - if self.__skip_hidden_row_column and self._file_type == "xls": - xlrd_params["formatting_info"] = True - if self.__detect_merged_cells: - xlrd_params["formatting_info"] = True + def get_xls_book(self, **xlrd_params): xls_book = xlrd.open_workbook(**xlrd_params) return xls_book @@ -226,6 +178,24 @@ class XLSBook(BookReader): return params +class XLSInFile(XLSReader): + def __init__(self, file_name, file_type, **keywords): + super().__init__(file_type, filename=file_name, **keywords) + + +class XLSInContent(XLSReader): + def __init__(self, file_content, file_type, **keywords): + super().__init__(file_type, file_contents=file_content, **keywords) + + +class XLSInMemory(XLSReader): + def __init__(self, file_stream, file_type, **keywords): + file_stream.seek(0) + super().__init__( + file_type, file_contents=file_stream.read(), **keywords + ) + + def xldate_to_python_date(value, date_mode): """ convert xl date to python date diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 5dd1520..7d08c1b 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -4,16 +4,15 @@ The lower level xls file format handler using xlwt - :copyright: (c) 2016-2017 by Onni Software Ltd + :copyright: (c) 2016-2020 by Onni Software Ltd :license: New BSD License """ import datetime import xlrd from xlwt import XFStyle, Workbook - -from pyexcel_io.book import BookWriter from pyexcel_io.sheet import SheetWriter +from pyexcel_io.plugin_api.abstract_writer import IWriter DEFAULT_DATE_FORMAT = "DD/MM/YY" DEFAULT_TIME_FORMAT = "HH:MM:SS" @@ -27,8 +26,7 @@ class XLSheetWriter(SheetWriter): """ def set_sheet_name(self, name): - """Create a sheet - """ + """Create a sheet""" self._native_sheet = self._native_book.add_sheet(name) self.current_row = 0 @@ -68,32 +66,33 @@ class XLSheetWriter(SheetWriter): self.current_row += 1 -class XLSWriter(BookWriter): +class XLSWriter(IWriter): """ xls writer """ - def __init__(self): - BookWriter.__init__(self) - self.work_book = None - - def open( - self, file_name, encoding="ascii", style_compression=2, **keywords + def __init__( + self, + file_alike_object, + _, # file_type not used + encoding="ascii", + style_compression=2, + **keywords ): - BookWriter.open(self, file_name, **keywords) + self._file_alike_object = file_alike_object self.work_book = Workbook( style_compression=style_compression, encoding=encoding ) - def write(self, incoming_dict): - if incoming_dict: - BookWriter.write(self, incoming_dict) - else: - raise NotImplementedError(EMPTY_SHEET_NOT_ALLOWED) - def create_sheet(self, name): return XLSheetWriter(self.work_book, None, name) + def write(self, incoming_dict): + if incoming_dict: + IWriter.write(self, incoming_dict) + else: + raise NotImplementedError(EMPTY_SHEET_NOT_ALLOWED) + def close(self): """ This call actually save the file diff --git a/rnd_requirements.txt b/rnd_requirements.txt index 6d9386d..dffaa2d 100644 --- a/rnd_requirements.txt +++ b/rnd_requirements.txt @@ -1,2 +1,2 @@ -https://github.com/pyexcel/pyexcel-io/archive/master.zip +https://github.com/pyexcel/pyexcel-io/archive/dev.zip diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index d298374..f38abfc 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -6,6 +6,7 @@ import os import datetime +from unittest.mock import MagicMock, patch import pyexcel as pe from _compact import OrderedDict @@ -13,7 +14,6 @@ from pyexcel_xls import save_data from pyexcel_xls.xlsr import xldate_to_python_date from pyexcel_xls.xlsw import XLSWriter as Writer -from mock import patch from nose import SkipTest from nose.tools import eq_, raises @@ -79,13 +79,11 @@ def test_issue_16_file_stream_has_no_getvalue(): @patch("xlrd.open_workbook") def test_issue_18_encoding_override_isnt_passed(fake_open): - fake_open.return_value = None + fake_open.return_value = MagicMock(sheets=MagicMock(return_value=[])) test_encoding = "utf-32" - from pyexcel_xls.xlsr import XLSBook + from pyexcel_xls.xlsr import XLSInFile - book = XLSBook() - book.open("fake_file.xls", encoding_override=test_encoding) - book._get_book() + XLSInFile("fake_file.xls", "xls", encoding_override=test_encoding) keywords = fake_open.call_args[1] assert keywords["encoding_override"] == test_encoding @@ -112,7 +110,7 @@ def test_empty_book_pyexcel_issue_120(): """ https://github.com/pyexcel/pyexcel/issues/120 """ - writer = Writer() + writer = Writer("fake.xls", "xls") writer.write({}) diff --git a/tests/test_filter.py b/tests/test_filter.py index c9bc9e0..cd07d3c 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): diff --git a/tests/test_writer.py b/tests/test_writer.py index e36454a..aef9a59 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,7 +1,7 @@ import os from base import PyexcelWriterBase, PyexcelHatWriterBase -from pyexcel_xls.xlsr import XLSBook as Reader +from pyexcel_xls.xlsr import XLSReader as Reader from pyexcel_xls.xlsw import XLSWriter as Writer @@ -13,12 +13,10 @@ class TestNativeXLSWriter: "Sheet3": [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]], } self.testfile = "writer.xls" - writer = Writer() - writer.open(self.testfile) + writer = Writer(self.testfile, "xls") writer.write(self.content) writer.close() - reader = Reader() - reader.open(self.testfile) + reader = Reader("xls", filename=self.testfile) content = reader.read_all() for key in content.keys(): content[key] = list(content[key]) From 0c1dea41bff79f784520e0591e7c1ed808606323 Mon Sep 17 00:00:00 2001 From: jaska Date: Fri, 2 Oct 2020 03:26:26 +0100 Subject: [PATCH 119/163] :hammer: use ISheetWriter interface (#37) --- pyexcel_xls/xlsr.py | 5 ++--- pyexcel_xls/xlsw.py | 22 +++++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 7a635e9..e6108a4 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -11,7 +11,6 @@ import datetime import xlrd from pyexcel_io.service import has_no_digits_in_float -from pyexcel_io._compact import irange from pyexcel_io.plugin_api.abstract_sheet import ISheet from pyexcel_io.plugin_api.abstract_reader import IReader @@ -38,8 +37,8 @@ class MergedCell(object): self.value = None def register_cells(self, registry): - for rowx in irange(self.__rl, self.__rh): - for colx in irange(self.__cl, self.__ch): + for rowx in range(self.__rl, self.__rh): + for colx in range(self.__cl, self.__ch): key = "%s-%s" % (rowx, colx) registry[key] = self diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 7d08c1b..c37fdeb 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -11,7 +11,8 @@ import datetime import xlrd from xlwt import XFStyle, Workbook -from pyexcel_io.sheet import SheetWriter +from pyexcel_io import constants +from pyexcel_io.plugin_api.abstract_sheet import ISheetWriter from pyexcel_io.plugin_api.abstract_writer import IWriter DEFAULT_DATE_FORMAT = "DD/MM/YY" @@ -20,14 +21,18 @@ DEFAULT_DATETIME_FORMAT = "%s %s" % (DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT) EMPTY_SHEET_NOT_ALLOWED = "xlwt does not support a book without any sheets" -class XLSheetWriter(SheetWriter): +class XLSheetWriter(ISheetWriter): """ xls sheet writer """ - def set_sheet_name(self, name): - """Create a sheet""" - self._native_sheet = self._native_book.add_sheet(name) + def __init__(self, xls_book, xls_sheet, sheet_name, **keywords): + if sheet_name is None: + sheet_name = constants.DEFAULT_SHEET_NAME + self._xls_book = xls_book + self._xls_sheet = xls_sheet + self._keywords = keywords + self._xls_sheet = self._xls_book.add_sheet(sheet_name) self.current_row = 0 def write_row(self, array): @@ -60,11 +65,14 @@ class XLSheetWriter(SheetWriter): style = XFStyle() style.num_format_str = DEFAULT_TIME_FORMAT if style: - self._native_sheet.write(self.current_row, i, value, style) + self._xls_sheet.write(self.current_row, i, value, style) else: - self._native_sheet.write(self.current_row, i, value) + self._xls_sheet.write(self.current_row, i, value) self.current_row += 1 + def close(self): + pass + class XLSWriter(IWriter): """ From 95ebd8df2f4508301a01fc843e9acd62d9072ab5 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 6 Oct 2020 23:16:13 +0100 Subject: [PATCH 120/163] :hammer: use module level imports from pyexcel-io --- pyexcel_xls/xlsr.py | 3 +-- pyexcel_xls/xlsw.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index e6108a4..b7c57f1 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -11,8 +11,7 @@ import datetime import xlrd from pyexcel_io.service import has_no_digits_in_float -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, IReader XLS_KEYWORDS = [ "filename", diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index c37fdeb..5c7cf39 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -12,8 +12,7 @@ import datetime import xlrd from xlwt import XFStyle, Workbook from pyexcel_io import constants -from pyexcel_io.plugin_api.abstract_sheet import ISheetWriter -from pyexcel_io.plugin_api.abstract_writer import IWriter +from pyexcel_io.plugin_api import IWriter, ISheetWriter DEFAULT_DATE_FORMAT = "DD/MM/YY" DEFAULT_TIME_FORMAT = "HH:MM:SS" From 86a70d576e3a8b8d8d6cfc5a4dde600dd31dafd3 Mon Sep 17 00:00:00 2001 From: chfw Date: Tue, 6 Oct 2020 22:16:51 +0000 Subject: [PATCH 121/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- CONTRIBUTORS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index bfd5904..9265c0f 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -1,4 +1,5 @@ + 1 contributors ================================================================================ From aec03bb849a6a7eca9d76ff35d781d5d6aaa7796 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 7 Oct 2020 22:28:18 +0100 Subject: [PATCH 122/163] :hammer: remove useless code --- pyexcel_xls/xlsr.py | 28 ++++++++++++++-------------- pyexcel_xls/xlsw.py | 7 +++---- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index b7c57f1..999c023 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -55,30 +55,30 @@ class XLSheet(ISheet): self.__hidden_rows = [] self.__merged_cells = {} self._book_date_mode = date_mode - self._native_sheet = sheet + self.xls_sheet = sheet self._keywords = keywords if keywords.get("detect_merged_cells") is True: for merged_cell_ranges in sheet.merged_cells: merged_cells = MergedCell(*merged_cell_ranges) merged_cells.register_cells(self.__merged_cells) if keywords.get("skip_hidden_row_and_column") is True: - for col_index, info in self._native_sheet.colinfo_map.items(): + for col_index, info in self.xls_sheet.colinfo_map.items(): if info.hidden == 1: self.__hidden_cols.append(col_index) - for row_index, info in self._native_sheet.rowinfo_map.items(): + for row_index, info in self.xls_sheet.rowinfo_map.items(): if info.hidden == 1: self.__hidden_rows.append(row_index) @property def name(self): - return self._native_sheet.name + return self.xls_sheet.name def row_iterator(self): - number_of_rows = self._native_sheet.nrows - len(self.__hidden_rows) + number_of_rows = self.xls_sheet.nrows - len(self.__hidden_rows) return range(number_of_rows) def column_iterator(self, row): - number_of_columns = self._native_sheet.ncols - len(self.__hidden_cols) + number_of_columns = self.xls_sheet.ncols - len(self.__hidden_cols) for column in range(number_of_columns): yield self.cell_value(row, column) @@ -88,8 +88,8 @@ class XLSheet(ISheet): """ if self._keywords.get("skip_hidden_row_and_column") is True: row, column = self._offset_hidden_indices(row, column) - cell_type = self._native_sheet.cell_type(row, column) - value = self._native_sheet.cell_value(row, column) + cell_type = self.xls_sheet.cell_type(row, column) + value = self.xls_sheet.cell_value(row, column) if cell_type == xlrd.XL_CELL_DATE: value = xldate_to_python_date(value, self._book_date_mode) @@ -143,8 +143,8 @@ class XLSReader(IReader): xlrd_params["formatting_info"] = True self.content_array = [] - self._native_book = self.get_xls_book(**xlrd_params) - for sheet in self._native_book.sheets(): + self.xls_book = self.get_xls_book(**xlrd_params) + for sheet in self.xls_book.sheets(): if self.__skip_hidden_sheets and sheet.visibility != 0: continue self.content_array.append(sheet) @@ -153,15 +153,15 @@ class XLSReader(IReader): native_sheet = self.content_array[index] sheet = XLSheet( native_sheet, - date_mode=self._native_book.datemode, + date_mode=self.xls_book.datemode, **self._keywords ) return sheet def close(self): - if self._native_book: - self._native_book.release_resources() - self._native_book = None + if self.xls_book: + self.xls_book.release_resources() + self.xls_book = None def get_xls_book(self, **xlrd_params): xls_book = xlrd.open_workbook(**xlrd_params) diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 5c7cf39..e348b9a 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -25,12 +25,11 @@ class XLSheetWriter(ISheetWriter): xls sheet writer """ - def __init__(self, xls_book, xls_sheet, sheet_name, **keywords): + def __init__(self, xls_book, xls_sheet, sheet_name): if sheet_name is None: sheet_name = constants.DEFAULT_SHEET_NAME self._xls_book = xls_book self._xls_sheet = xls_sheet - self._keywords = keywords self._xls_sheet = self._xls_book.add_sheet(sheet_name) self.current_row = 0 @@ -86,7 +85,7 @@ class XLSWriter(IWriter): style_compression=2, **keywords ): - self._file_alike_object = file_alike_object + self.file_alike_object = file_alike_object self.work_book = Workbook( style_compression=style_compression, encoding=encoding ) @@ -104,4 +103,4 @@ class XLSWriter(IWriter): """ This call actually save the file """ - self.work_book.save(self._file_alike_object) + self.work_book.save(self.file_alike_object) From f8e8b0c1da9ccd4b986f7722017b4c7adc057914 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 7 Oct 2020 22:31:01 +0100 Subject: [PATCH 123/163] :green_heart: update test case --- tests/test_writer.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_writer.py b/tests/test_writer.py index aef9a59..12004e8 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,7 +1,7 @@ import os from base import PyexcelWriterBase, PyexcelHatWriterBase -from pyexcel_xls.xlsr import XLSReader as Reader +from pyexcel_xls import get_data from pyexcel_xls.xlsw import XLSWriter as Writer @@ -16,12 +16,10 @@ class TestNativeXLSWriter: writer = Writer(self.testfile, "xls") writer.write(self.content) writer.close() - reader = Reader("xls", filename=self.testfile) - content = reader.read_all() + content = get_data(self.testfile) 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 82e67d1542563c53c319d93947916f1ec42bd3fd Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 7 Oct 2020 22:40:08 +0100 Subject: [PATCH 124/163] :green_heart: remove moban stage --- pyexcel-xls.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index c4b3ae1..7a4b955 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -13,3 +13,4 @@ dependencies: test_dependencies: - pyexcel description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format +moban_command: false \ No newline at end of file From ac57f60728fd6a817066ae7b11c585eaeb98b3f3 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 7 Oct 2020 21:40:37 +0000 Subject: [PATCH 125/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- .travis.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index b457dd1..9cb4e91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ python: stages: - lint - - moban - test @@ -23,16 +22,6 @@ stages: 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 From b85571599ae9e5a865aebce6b5c1dfbde0d6c062 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 8 Oct 2020 08:29:18 +0100 Subject: [PATCH 126/163] :bug: update license and moban file --- CHANGELOG.rst | 14 ++++++++++++++ LICENSE | 2 +- changelog.yml | 12 ++++++++++++ docs/source/conf.py | 2 +- pyexcel-xls.yml | 4 ++-- setup.py | 6 +++--- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9f16100..fc8392a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,20 @@ Change log ================================================================================ +0.6.0 - 8.10.2020 +-------------------------------------------------------------------------------- + +**Updated** + +#. New style xlsx plugins, promoted by pyexcel-io v0.6.0. + +0.5.9 - 29.08.2020 +-------------------------------------------------------------------------------- + +**Added** + +#. `#35 `_, include tests + 0.5.8 - 22.08.2018 -------------------------------------------------------------------------------- diff --git a/LICENSE b/LICENSE index 3225ede..9c01abd 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-xls' 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/changelog.yml b/changelog.yml index f25f270..27f4d30 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,18 @@ name: pyexcel-xls organisation: pyexcel releases: +- changes: + - action: Updated + details: + - 'New style xlsx plugins, promoted by pyexcel-io v0.6.0.' + date: 8.10.2020 + version: 0.6.0 +- changes: + - action: Added + details: + - "`#35`, include tests" + date: 29.08.2020 + version: 0.5.9 - changes: - action: Added details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 7776da0..d9f5d9d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -28,7 +28,7 @@ author = 'chfw' # The short X.Y version version = '0.6.0' # The full version, including alpha/beta/rc tags -release = '0.5.8' +release = '0.6.0' # -- General configuration --------------------------------------------------- diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 7a4b955..484a09a 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -3,7 +3,7 @@ name: "pyexcel-xls" nick_name: xls version: 0.6.0 current_version: 0.6.0 -release: 0.5.8 +release: 0.6.0 file_type: xls is_on_conda: true dependencies: @@ -13,4 +13,4 @@ dependencies: test_dependencies: - pyexcel description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format -moban_command: false \ No newline at end of file +moban_command: false diff --git a/setup.py b/setup.py index 3aee597..d8cfed2 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ DESCRIPTION = ( "reads xlsx and xlsm format" ) URL = "https://github.com/pyexcel/pyexcel-xls" -DOWNLOAD_URL = "%s/archive/0.5.8.tar.gz" % URL +DOWNLOAD_URL = "%s/archive/0.6.0.tar.gz" % URL FILES = ["README.rst","CONTRIBUTORS.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", @@ -78,8 +78,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-xls v0.5.8 " + - "Find 0.5.8 in changelog for more details") +GS_COMMAND = ("gs pyexcel-xls 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 355779f6fb709270f827098b29eea5e768d5649c Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 8 Oct 2020 10:49:05 +0100 Subject: [PATCH 127/163] :books: update copyright year --- LICENSE | 2 +- docs/source/conf.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 9c01abd..923df6b 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/docs/source/conf.py b/docs/source/conf.py index d9f5d9d..128c99c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,7 @@ DESCRIPTION = ( # -- Project information ----------------------------------------------------- project = 'pyexcel-xls' -copyright = '2015-2019 Onni Software Ltd.' +copyright = '2015-2020 Onni Software Ltd.' author = 'chfw' # The short X.Y version version = '0.6.0' From afca0616a25fa9975e3aa52df2ba4a8005a460df Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 8 Oct 2020 18:35:30 +0100 Subject: [PATCH 128/163] :lipstick: update badges about moban and black --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index fdde2e0..f1cbaab 100644 --- a/README.rst +++ b/README.rst @@ -29,6 +29,11 @@ pyexcel-xls - Let you focus on data, instead of xls 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=模版更新&color=blue&style=flat-square + :target: https://github.com/moremoban/moban + +.. image:: https://img.shields.io/static/v1?label=coding%20style&message=black&color=black&style=flat-square + :target: https://github.com/psf/black **pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. From 52b8fb8166bee4fa6898fbcf0c1e60d7dc461d77 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 8 Oct 2020 18:39:44 +0100 Subject: [PATCH 129/163] :lipstick: update badges about moban --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index f1cbaab..c8731e2 100644 --- a/README.rst +++ b/README.rst @@ -29,7 +29,7 @@ pyexcel-xls - Let you focus on data, instead of xls 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=模版更新&color=blue&style=flat-square +.. 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://github.com/moremoban/moban .. image:: https://img.shields.io/static/v1?label=coding%20style&message=black&color=black&style=flat-square From 03f8e0dd49b939623abc62592b24f4cf7afc314e Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 8 Oct 2020 18:42:18 +0100 Subject: [PATCH 130/163] :lipstick: update continuous templating link --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index c8731e2..aea5b91 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,7 @@ pyexcel-xls - Let you focus on data, instead of xls format :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://github.com/moremoban/moban + :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 From 9cb254e5f25f73aa60ce6a22a8d8de7d54bc63e9 Mon Sep 17 00:00:00 2001 From: jaska Date: Thu, 8 Oct 2020 19:00:46 +0100 Subject: [PATCH 131/163] Update pyexcel-xls.yml --- pyexcel-xls.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 484a09a..2f7a0b3 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -7,7 +7,7 @@ release: 0.6.0 file_type: xls is_on_conda: true dependencies: - - pyexcel-io>=0.5.3 + - pyexcel-io>=0.6.2 - xlrd - xlwt test_dependencies: From cfe90b4616b576053c469ef786ab172ef40dd232 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 8 Oct 2020 18:01:20 +0000 Subject: [PATCH 132/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index cc6ba29..4c06b39 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -pyexcel-io>=0.5.3 +pyexcel-io>=0.6.2 xlrd xlwt diff --git a/setup.py b/setup.py index d8cfed2..8cfc14c 100644 --- a/setup.py +++ b/setup.py @@ -67,7 +67,7 @@ CLASSIFIERS = [ INSTALL_REQUIRES = [ - "pyexcel-io>=0.5.3", + "pyexcel-io>=0.6.2", "xlrd", "xlwt", ] From 14243196ddc41f3a352f686d528f6f9adf7d5161 Mon Sep 17 00:00:00 2001 From: jaska Date: Thu, 8 Oct 2020 19:07:04 +0100 Subject: [PATCH 133/163] Update changelog.yml --- changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.yml b/changelog.yml index 27f4d30..6717663 100644 --- a/changelog.yml +++ b/changelog.yml @@ -4,7 +4,7 @@ releases: - changes: - action: Updated details: - - 'New style xlsx plugins, promoted by pyexcel-io v0.6.0.' + - 'New style xlsx plugins, promoted by pyexcel-io v0.6.2.' date: 8.10.2020 version: 0.6.0 - changes: From cfb7d3ad2c6244d2e9b0d0f58a83b7ee74659000 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 8 Oct 2020 18:07:39 +0000 Subject: [PATCH 134/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fc8392a..f876cbb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,7 +6,7 @@ Change log **Updated** -#. New style xlsx plugins, promoted by pyexcel-io v0.6.0. +#. New style xlsx plugins, promoted by pyexcel-io v0.6.2. 0.5.9 - 29.08.2020 -------------------------------------------------------------------------------- From e849d0d14ecd1ca4cb3e73fc526b55350cc749ba Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 21 Oct 2020 09:35:59 +0100 Subject: [PATCH 135/163] :hammer: update setup.py. https://github.com/pyexcel/pyexcel-xlsx/issues/46 --- CHANGELOG.rst | 8 ++++++++ README.rst | 4 +++- changelog.yml | 6 ++++++ docs/source/conf.py | 6 +++--- lint.sh | 2 +- pyexcel-xls.yml | 8 +++++--- setup.py | 26 ++++++++++++++------------ 7 files changed, 40 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fc8392a..dd11453 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Change log ================================================================================ +0.6.1 - 21.10.2020 +-------------------------------------------------------------------------------- + +**Updated** + +#. Restrict this library to get installed on python 3.6+, because pyexcel-io + 0.6.0+ supports only python 3.6+. + 0.6.0 - 8.10.2020 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index aea5b91..7cbd400 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ pyexcel-xls - Let you focus on data, instead of xls 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-xls.svg?branch=master @@ -65,6 +65,8 @@ Known constraints Fonts, colors and charts are not supported. +Nor to read password protected xls, xlsx and ods files. + Installation ================================================================================ diff --git a/changelog.yml b/changelog.yml index 27f4d30..485ed34 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-xls organisation: pyexcel releases: +- changes: + - action: Updated + details: + - "Restrict this library to get installed on python 3.6+, because pyexcel-io 0.6.0+ supports only python 3.6+." + date: 21.10.2020 + version: 0.6.1 - changes: - action: Updated details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 128c99c..1ed7aba 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -24,11 +24,11 @@ DESCRIPTION = ( project = 'pyexcel-xls' copyright = '2015-2020 Onni Software Ltd.' -author = 'chfw' +author = 'C.W.' # The short X.Y version -version = '0.6.0' +version = '0.6.1' # The full version, including alpha/beta/rc tags -release = '0.6.0' +release = '0.6.1' # -- General configuration --------------------------------------------------- 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/pyexcel-xls.yml b/pyexcel-xls.yml index 484a09a..66e1148 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.6.0 -current_version: 0.6.0 -release: 0.6.0 +version: 0.6.1 +current_version: 0.6.1 +release: 0.6.1 file_type: xls is_on_conda: true dependencies: @@ -14,3 +14,5 @@ test_dependencies: - pyexcel description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format moban_command: false +python_requires: ">=3.6" +min_python_version: "3.6" diff --git a/setup.py b/setup.py index d8cfed2..550fc18 100644 --- a/setup.py +++ b/setup.py @@ -31,8 +31,8 @@ except (ValueError, UnicodeError, locale.Error): locale.setlocale(locale.LC_ALL, "en_US.UTF-8") NAME = "pyexcel-xls" -AUTHOR = "chfw" -VERSION = "0.6.0" +AUTHOR = "C.W." +VERSION = "0.6.1" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" DESCRIPTION = ( @@ -40,7 +40,7 @@ DESCRIPTION = ( "reads xlsx and xlsm format" ) URL = "https://github.com/pyexcel/pyexcel-xls" -DOWNLOAD_URL = "%s/archive/0.6.0.tar.gz" % URL +DOWNLOAD_URL = "%s/archive/0.6.1.tar.gz" % URL FILES = ["README.rst","CONTRIBUTORS.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", @@ -53,11 +53,11 @@ 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", @@ -65,6 +65,7 @@ CLASSIFIERS = [ 'Programming Language :: Python :: Implementation :: PyPy' ] +PYTHON_REQUIRES = ">=3.6" INSTALL_REQUIRES = [ "pyexcel-io>=0.5.3", @@ -78,13 +79,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-xls v0.6.0 " + - "Find 0.6.0 in changelog for more details") +HERE = os.path.abspath(os.path.dirname(__file__)) + +GS_COMMAND = ("gease pyexcel-xls v0.6.1 " + + "Find 0.6.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): @@ -130,7 +132,6 @@ SETUP_COMMANDS.update({ "publish": PublishCommand }) - def has_gease(): """ test if github release command is installed @@ -199,6 +200,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 a31308d8c3a3e6b7e1fe12e782464b1877a78cb6 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 28 Nov 2020 22:31:59 +0000 Subject: [PATCH 136/163] :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/xls_travis.yml.jj2 | 8 ------ .moban.yml | 1 - .travis.yml | 43 -------------------------------- README.rst | 6 ++--- 7 files changed, 55 insertions(+), 56 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/tests.yml delete mode 100644 .moban.d/xls_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..4b5c675 --- /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_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls + - 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/xls_travis.yml.jj2 b/.moban.d/xls_travis.yml.jj2 deleted file mode 100644 index a62287f..0000000 --- a/.moban.d/xls_travis.yml.jj2 +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "travis.yml.jj2" %} -{%block custom_python_versions%} -python: - - 3.8 - - 3.7 - - 3.6 -{%endblock%} - diff --git a/.moban.yml b/.moban.yml index 2af1b28..94ecc3d 100644 --- a/.moban.yml +++ b/.moban.yml @@ -5,7 +5,6 @@ targets: - README.rst: custom_README.rst.jj2 - setup.py: custom_setup.py.jj2 - "docs/source/conf.py": "docs/source/conf.py.jj2" - - .travis.yml: xls_travis.yml.jj2 - .gitignore: gitignore.jj2 - MANIFEST.in: MANIFEST.in.jj2 - "tests/requirements.txt": "tests/custom_requirements.txt.jj2" diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9cb4e91..0000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -sudo: false -dist: xenial -language: python -notifications: - email: false -python: - - 3.8 - - 3.7 - - 3.6 - -stages: - - lint - - test - - -.lint: &lint - git: - submodules: false - python: 3.6 - env: - - MINREQ=0 - stage: lint - script: make lint - -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 7cbd400..9773e5f 100644 --- a/README.rst +++ b/README.rst @@ -8,8 +8,8 @@ pyexcel-xls - Let you focus on data, instead of xls format .. 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-xls.svg?branch=master - :target: http://travis-ci.org/pyexcel/pyexcel-xls +.. image:: https://github.com/pyexcel/pyexcel-xls/workflows/run_tests/badge.svg + :target: http://github.com/pyexcel/pyexcel-xls/actions .. image:: https://codecov.io/gh/pyexcel/pyexcel-xls/branch/master/graph/badge.svg :target: https://codecov.io/gh/pyexcel/pyexcel-xls @@ -21,7 +21,7 @@ pyexcel-xls - Let you focus on data, instead of xls format :target: https://anaconda.org/conda-forge/pyexcel-xls .. image:: https://pepy.tech/badge/pyexcel-xls/month - :target: https://pepy.tech/project/pyexcel-xls/month + :target: https://pepy.tech/project/pyexcel-xls .. image:: https://anaconda.org/conda-forge/pyexcel-xls/badges/downloads.svg :target: https://anaconda.org/conda-forge/pyexcel-xls From ced153d95cfb666085cb0cbb6a95923b716d1294 Mon Sep 17 00:00:00 2001 From: Peter Carnesciali Date: Sat, 12 Dec 2020 11:28:55 -0600 Subject: [PATCH 137/163] Lock down xlrd to restore .xlsx support (#41) * Lock down xlrd to restore .xlsx support * Update requirements.txt --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4c06b39..65ffc34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ pyexcel-io>=0.6.2 -xlrd +xlrd<2 xlwt diff --git a/setup.py b/setup.py index 135f172..f88e4ab 100644 --- a/setup.py +++ b/setup.py @@ -69,7 +69,7 @@ PYTHON_REQUIRES = ">=3.6" INSTALL_REQUIRES = [ "pyexcel-io>=0.6.2", - "xlrd", + "xlrd<2", "xlwt", ] SETUP_COMMANDS = {} From 488dd0289382b3b8b802a93733022ab213566a56 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 12 Dec 2020 17:29:22 +0000 Subject: [PATCH 138/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- .readthedocs.yml | 18 ++++++++++++++++++ CONTRIBUTORS.rst | 3 ++- requirements.txt | 2 +- setup.py | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 .readthedocs.yml diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..a379070 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,18 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/source/conf.py + +# Optionally build your docs in additional formats such as PDF +formats: + - pdf + +# Optionally set the version of Python and requirements required to build your docs +python: + version: 3.7 diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 9265c0f..aa6bd68 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -1,8 +1,9 @@ -1 contributors +2 contributors ================================================================================ In alphabetical order: * `John Vandenberg `_ +* `Peter Carnesciali `_ diff --git a/requirements.txt b/requirements.txt index 65ffc34..4c06b39 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ pyexcel-io>=0.6.2 -xlrd<2 +xlrd xlwt diff --git a/setup.py b/setup.py index f88e4ab..135f172 100644 --- a/setup.py +++ b/setup.py @@ -69,7 +69,7 @@ PYTHON_REQUIRES = ">=3.6" INSTALL_REQUIRES = [ "pyexcel-io>=0.6.2", - "xlrd<2", + "xlrd", "xlwt", ] SETUP_COMMANDS = {} From 19013b685a1f979386301e20cae833cada3a8589 Mon Sep 17 00:00:00 2001 From: jaska Date: Sat, 12 Dec 2020 17:55:33 +0000 Subject: [PATCH 139/163] Prepare 0.6.2 (#42) * :books: the correct place to update dependencies in pyexcel family. relatedt to #41 * :books: and update change log. related to #41 * This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst Co-authored-by: chfw --- CHANGELOG.rst | 8 ++++++++ changelog.yml | 6 ++++++ docs/source/conf.py | 4 ++-- pyexcel-xls.yml | 8 ++++---- setup.py | 8 ++++---- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8cf4785..613b1e5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Change log ================================================================================ +0.6.2 - 12.12.2020 +-------------------------------------------------------------------------------- + +**Updated** + +#. lock down xlrd version less than version 2.0, because 2.0+ does not support + xlsx read + 0.6.1 - 21.10.2020 -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index a1ceb05..d7e01e3 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-xls organisation: pyexcel releases: +- changes: + - action: Updated + details: + - "lock down xlrd version less than version 2.0, because 2.0+ does not support xlsx read" + date: 12.12.2020 + version: 0.6.2 - changes: - action: Updated details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 1ed7aba..5e5b7cd 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,9 +26,9 @@ project = 'pyexcel-xls' copyright = '2015-2020 Onni Software Ltd.' author = 'C.W.' # The short X.Y version -version = '0.6.1' +version = '0.6.2' # The full version, including alpha/beta/rc tags -release = '0.6.1' +release = '0.6.2' # -- General configuration --------------------------------------------------- diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 2e474a2..4b55499 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -1,14 +1,14 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.6.1 -current_version: 0.6.1 -release: 0.6.1 +version: 0.6.2 +current_version: 0.6.2 +release: 0.6.2 file_type: xls is_on_conda: true dependencies: - pyexcel-io>=0.6.2 - - xlrd + - xlrd<2 - xlwt test_dependencies: - pyexcel diff --git a/setup.py b/setup.py index 135f172..fafb4b7 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ except (ValueError, UnicodeError, locale.Error): NAME = "pyexcel-xls" AUTHOR = "C.W." -VERSION = "0.6.1" +VERSION = "0.6.2" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" DESCRIPTION = ( @@ -40,7 +40,7 @@ DESCRIPTION = ( "reads xlsx and xlsm format" ) URL = "https://github.com/pyexcel/pyexcel-xls" -DOWNLOAD_URL = "%s/archive/0.6.1.tar.gz" % URL +DOWNLOAD_URL = "%s/archive/0.6.2.tar.gz" % URL FILES = ["README.rst","CONTRIBUTORS.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", @@ -81,8 +81,8 @@ EXTRAS_REQUIRE = { PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) HERE = os.path.abspath(os.path.dirname(__file__)) -GS_COMMAND = ("gease pyexcel-xls v0.6.1 " + - "Find 0.6.1 in changelog for more details") +GS_COMMAND = ("gease pyexcel-xls v0.6.2 " + + "Find 0.6.2 in changelog for more details") NO_GS_MESSAGE = ("Automatic github release is disabled. " + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( From 084fa8ed57fb35879c9c8e77253e562f5e06a174 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 12 Dec 2020 17:56:04 +0000 Subject: [PATCH 140/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4c06b39..65ffc34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ pyexcel-io>=0.6.2 -xlrd +xlrd<2 xlwt diff --git a/setup.py b/setup.py index fafb4b7..9000415 100644 --- a/setup.py +++ b/setup.py @@ -69,7 +69,7 @@ PYTHON_REQUIRES = ">=3.6" INSTALL_REQUIRES = [ "pyexcel-io>=0.6.2", - "xlrd", + "xlrd<2", "xlwt", ] SETUP_COMMANDS = {} From 26b665c1373e2c254f942f0edd39e9436a575151 Mon Sep 17 00:00:00 2001 From: jaska Date: Sat, 12 Dec 2020 22:25:40 +0000 Subject: [PATCH 141/163] :books: add usage warning (#44) * :books: add usage warning * This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst * :books: update readme * :sparkles: use pat Co-authored-by: chfw --- .github/workflows/moban-update.yml | 1 + .moban.d/custom_README.rst.jj2 | 21 ++++++++++++++++++--- README.rst | 21 ++++++++++++++++++--- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/.github/workflows/moban-update.yml b/.github/workflows/moban-update.yml index 706fd82..7248179 100644 --- a/.github/workflows/moban-update.yml +++ b/.github/workflows/moban-update.yml @@ -8,6 +8,7 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.head_ref }} + token: ${{ secrets.PAT }} - name: Set up Python uses: actions/setup-python@v1 with: diff --git a/.moban.d/custom_README.rst.jj2 b/.moban.d/custom_README.rst.jj2 index e176dd4..661d558 100644 --- a/.moban.d/custom_README.rst.jj2 +++ b/.moban.d/custom_README.rst.jj2 @@ -4,11 +4,26 @@ {% endblock %} {%block description%} -**pyexcel-{{file_type}}** is a tiny wrapper library to read, manipulate and write data in {{file_type}} format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. +**pyexcel-{{file_type}}** is a tiny wrapper library to read, manipulate and +write data in {{file_type}} format and it can read xlsx and xlsm fromat. +You are likely to use it with `pyexcel `_. -New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. +New flag: `detect_merged_cells` allows you to spread the same value among +all merged cells. But be aware that this may slow down its reading +performance. -New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. +New flag: `skip_hidden_row_and_column` allows you to skip hidden rows +and columns and is defaulted to **True**. It may slow down its reading +performance. And it is only valid for 'xls' files. For 'xlsx' files, +please use pyexcel-xlsx. + +Warning +================================================================================ + +xls file cannot contain more than 65,000 rows. You are risking the reputation +of yourself/your company/ +`your country `_ if you keep +using xls and are not aware of its row limit. {%endblock%} diff --git a/README.rst b/README.rst index 9773e5f..2505490 100644 --- a/README.rst +++ b/README.rst @@ -35,11 +35,26 @@ pyexcel-xls - Let you focus on data, instead of xls format .. image:: https://img.shields.io/static/v1?label=coding%20style&message=black&color=black&style=flat-square :target: https://github.com/psf/black -**pyexcel-xls** is a tiny wrapper library to read, manipulate and write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. +**pyexcel-xls** is a tiny wrapper library to read, manipulate and +write data in xls format and it can read xlsx and xlsm fromat. +You are likely to use it with `pyexcel `_. -New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. +New flag: `detect_merged_cells` allows you to spread the same value among +all merged cells. But be aware that this may slow down its reading +performance. -New flag: `skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. +New flag: `skip_hidden_row_and_column` allows you to skip hidden rows +and columns and is defaulted to **True**. It may slow down its reading +performance. And it is only valid for 'xls' files. For 'xlsx' files, +please use pyexcel-xlsx. + +Warning +================================================================================ + +xls file cannot contain more than 65,000 rows. You are risking the reputation +of yourself/your company/ +`your country `_ if you keep +using xls and are not aware of its row limit. Support the project From 473ee14be57f000658e94dde082bda15f7a311f3 Mon Sep 17 00:00:00 2001 From: vinraspa <78381185+vinraspa@users.noreply.github.com> Date: Wed, 15 Sep 2021 18:26:09 +0200 Subject: [PATCH 142/163] Update xlsw.py added 'timedelta' support --- pyexcel_xls/xlsw.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index e348b9a..c07a9b3 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -52,6 +52,14 @@ class XLSheetWriter(ISheetWriter): value = xlrd.xldate.xldate_from_datetime_tuple(tmp_array, 0) style = XFStyle() style.num_format_str = DEFAULT_DATETIME_FORMAT + elif isinstance(value, datetime.timedelta): + hours = value.days * 24 + value.seconds // 3600 + minutes = (value.seconds // 60) % 60 + seconds = value.seconds % 60 + tmp_array = [hours, minutes, seconds] + value = xlrd.xldate.xldate_from_time_tuple(tmp_array) + style = XFStyle() + style.num_format_str = DEFAULT_TIME_FORMAT elif isinstance(value, datetime.date): tmp_array = [value.year, value.month, value.day] value = xlrd.xldate.xldate_from_date_tuple(tmp_array, 0) From e309f9e45acaced2aa3ebe42cc94c60f0ad44dfc Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 26 Sep 2021 08:48:10 +0000 Subject: [PATCH 143/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- .github/workflows/lint.yml | 4 ++-- .github/workflows/tests.yml | 4 ++-- CONTRIBUTORS.rst | 3 ++- LICENSE | 2 +- docs/source/conf.py | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 03122a1..3789494 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,7 +14,7 @@ jobs: python-version: 3.8 - name: lint run: | - pip install flake8 - pip install -r tests/requirements.txt + pip --use-deprecated=legacy-resolver install flake8 + pip --use-deprecated=legacy-resolver 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 index 4b5c675..86ab9f8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,8 +20,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: install run: | - pip install -r requirements.txt - pip install -r tests/requirements.txt + pip --use-deprecated=legacy-resolver install -r requirements.txt + pip --use-deprecated=legacy-resolver install -r tests/requirements.txt - name: test run: | pip freeze diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index aa6bd68..b45268a 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -1,9 +1,10 @@ -2 contributors +3 contributors ================================================================================ In alphabetical order: * `John Vandenberg `_ * `Peter Carnesciali `_ +* `vinraspa `_ diff --git a/LICENSE b/LICENSE index 923df6b..409a51e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2020 by Onni Software Ltd. and its contributors +Copyright (c) 2015-2021 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/docs/source/conf.py b/docs/source/conf.py index 5e5b7cd..550ca04 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,7 @@ DESCRIPTION = ( # -- Project information ----------------------------------------------------- project = 'pyexcel-xls' -copyright = '2015-2020 Onni Software Ltd.' +copyright = '2015-2021 Onni Software Ltd.' author = 'C.W.' # The short X.Y version version = '0.6.2' From 4b774fc1aee54694c2023f638f4bfbdfaae211c8 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 2 Oct 2021 15:01:53 +0100 Subject: [PATCH 144/163] :green_heart: unit test timedelta --- pyexcel_xls/xlsr.py | 4 +--- tests/test_formatters.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 999c023..8e679c7 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -152,9 +152,7 @@ class XLSReader(IReader): def read_sheet(self, index): native_sheet = self.content_array[index] sheet = XLSheet( - native_sheet, - date_mode=self.xls_book.datemode, - **self._keywords + native_sheet, date_mode=self.xls_book.datemode, **self._keywords ) return sheet diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 0dcd74a..e87a017 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -37,6 +37,15 @@ class TestDateFormat: datetime.date(2014, 12, 25), datetime.time(11, 11, 11), datetime.datetime(2014, 12, 25, 11, 11, 11), + datetime.timedelta( + days=50, + seconds=27, + microseconds=10, + milliseconds=29000, + minutes=5, + hours=8, + weeks=2, + ), ] ] pe.save_as(dest_file_name=excel_filename, array=data) @@ -47,6 +56,8 @@ class TestDateFormat: assert r[0, 1].strftime("%H:%M:%S") == "11:11:11" assert isinstance(r[0, 2], datetime.date) is True assert r[0, 2].strftime("%d/%m/%y %H:%M:%S") == "25/12/14 11:11:11" + assert isinstance(r[0, 2], datetime.timedelta) + assert r[0, 1].strftime("%H:%M:%S") == "3:30:20" os.unlink(excel_filename) From 4b9426d2e07cb10906606e82796b9e97de5719f4 Mon Sep 17 00:00:00 2001 From: vinraspa <78381185+vinraspa@users.noreply.github.com> Date: Sat, 2 Oct 2021 22:12:19 +0200 Subject: [PATCH 145/163] Update xlsw.py fix timedelta support --- pyexcel_xls/xlsw.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index c07a9b3..8cdd32b 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -16,6 +16,7 @@ from pyexcel_io.plugin_api import IWriter, ISheetWriter DEFAULT_DATE_FORMAT = "DD/MM/YY" DEFAULT_TIME_FORMAT = "HH:MM:SS" +DEFAULT_LONGTIME_FORMAT = "[HH]:MM:SS" DEFAULT_DATETIME_FORMAT = "%s %s" % (DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT) EMPTY_SHEET_NOT_ALLOWED = "xlwt does not support a book without any sheets" @@ -53,13 +54,9 @@ class XLSheetWriter(ISheetWriter): style = XFStyle() style.num_format_str = DEFAULT_DATETIME_FORMAT elif isinstance(value, datetime.timedelta): - hours = value.days * 24 + value.seconds // 3600 - minutes = (value.seconds // 60) % 60 - seconds = value.seconds % 60 - tmp_array = [hours, minutes, seconds] - value = xlrd.xldate.xldate_from_time_tuple(tmp_array) + value = value.days + value.seconds / 86_400 style = XFStyle() - style.num_format_str = DEFAULT_TIME_FORMAT + style.num_format_str = DEFAULT_LONGTIME_FORMAT elif isinstance(value, datetime.date): tmp_array = [value.year, value.month, value.day] value = xlrd.xldate.xldate_from_date_tuple(tmp_array, 0) From f46b724920c6a227f6a8544c440a7fb853112996 Mon Sep 17 00:00:00 2001 From: vinraspa <78381185+vinraspa@users.noreply.github.com> Date: Sat, 2 Oct 2021 22:25:08 +0200 Subject: [PATCH 146/163] Update xlsw.py W291 trailing whitespace: fixed --- pyexcel_xls/xlsw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 8cdd32b..4822cd3 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -56,7 +56,7 @@ class XLSheetWriter(ISheetWriter): elif isinstance(value, datetime.timedelta): value = value.days + value.seconds / 86_400 style = XFStyle() - style.num_format_str = DEFAULT_LONGTIME_FORMAT + style.num_format_str = DEFAULT_LONGTIME_FORMAT elif isinstance(value, datetime.date): tmp_array = [value.year, value.month, value.day] value = xlrd.xldate.xldate_from_date_tuple(tmp_array, 0) From 9b2275a2da615d900b7cd8820151f0b676b5e045 Mon Sep 17 00:00:00 2001 From: vinraspa <78381185+vinraspa@users.noreply.github.com> Date: Sat, 2 Oct 2021 22:47:42 +0200 Subject: [PATCH 147/163] Update test_formatters.py Bad cell ref [0, 2] -> [0, 3] --- tests/test_formatters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index e87a017..6a0515f 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -56,7 +56,7 @@ class TestDateFormat: assert r[0, 1].strftime("%H:%M:%S") == "11:11:11" assert isinstance(r[0, 2], datetime.date) is True assert r[0, 2].strftime("%d/%m/%y %H:%M:%S") == "25/12/14 11:11:11" - assert isinstance(r[0, 2], datetime.timedelta) + assert isinstance(r[0, 3], datetime.timedelta) assert r[0, 1].strftime("%H:%M:%S") == "3:30:20" os.unlink(excel_filename) From 8f7e6f765c093af16a143416557017b4890ec43d Mon Sep 17 00:00:00 2001 From: vinraspa <78381185+vinraspa@users.noreply.github.com> Date: Sat, 2 Oct 2021 23:04:43 +0200 Subject: [PATCH 148/163] Update test_formatters.py --- tests/test_formatters.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 6a0515f..a3c7518 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -56,8 +56,8 @@ class TestDateFormat: assert r[0, 1].strftime("%H:%M:%S") == "11:11:11" assert isinstance(r[0, 2], datetime.date) is True assert r[0, 2].strftime("%d/%m/%y %H:%M:%S") == "25/12/14 11:11:11" - assert isinstance(r[0, 3], datetime.timedelta) - assert r[0, 1].strftime("%H:%M:%S") == "3:30:20" + assert isinstance(r[0, 3], datetime.datetime) + assert r[0, 3].strftime("%D-%H:%M:%S") == "03/04/00-08:05:56" os.unlink(excel_filename) From 78748634eecf935cb2230a23f860e92a358cf1c9 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 3 Oct 2021 13:25:35 +0100 Subject: [PATCH 149/163] :lipstick: update meta info and format codes. related to #49, #48 --- changelog.yml | 6 ++++++ pyexcel-xls.yml | 4 ++-- pyexcel_xls/xlsw.py | 2 +- tests/test_formatters.py | 14 +++++++------- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/changelog.yml b/changelog.yml index d7e01e3..a755d32 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-xls organisation: pyexcel releases: +- changes: + - action: Updated + details: + - "`#47`: limit support to persist datetime.timedelta. see more details in doc" + date: tbd + version: 0.6.3 - changes: - action: Updated details: diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 4b55499..d8dbfef 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -2,8 +2,8 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls version: 0.6.2 -current_version: 0.6.2 -release: 0.6.2 +current_version: 0.6.3 +release: 0.6.3 file_type: xls is_on_conda: true dependencies: diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index 4822cd3..a127525 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -88,7 +88,7 @@ class XLSWriter(IWriter): _, # file_type not used encoding="ascii", style_compression=2, - **keywords + **keywords, ): self.file_alike_object = file_alike_object self.work_book = Workbook( diff --git a/tests/test_formatters.py b/tests/test_formatters.py index a3c7518..750a60f 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -38,13 +38,13 @@ class TestDateFormat: datetime.time(11, 11, 11), datetime.datetime(2014, 12, 25, 11, 11, 11), datetime.timedelta( - days=50, - seconds=27, - microseconds=10, - milliseconds=29000, - minutes=5, - hours=8, - weeks=2, + days=50, + seconds=27, + microseconds=10, + milliseconds=29000, + minutes=5, + hours=8, + weeks=2, ), ] ] From 2f139848f88591db20467c9617fd5d0c69107060 Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 3 Oct 2021 13:51:26 +0100 Subject: [PATCH 150/163] :fire: remove the pinning on xlrd < 2. fix #46 --- .moban.d/custom_README.rst.jj2 | 12 +++++++++++- changelog.yml | 1 + pyexcel-xls.yml | 2 +- pyexcel_xls/__init__.py | 26 ++++++++++++++++++++++---- tests/test_bug_fixes.py | 4 +++- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/.moban.d/custom_README.rst.jj2 b/.moban.d/custom_README.rst.jj2 index 661d558..700f5c4 100644 --- a/.moban.d/custom_README.rst.jj2 +++ b/.moban.d/custom_README.rst.jj2 @@ -8,6 +8,16 @@ write data in {{file_type}} format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. +Update: + +1. v0.6.3 removed the pin on xlrd < 2. If you have xlrd >= 2, this +library will NOT read 'xlsx' format and you need to install pyexcel-xlsx. Othwise, +this library can use xlrd < 2 to read xlsx format for you. So 'xlsx' support +in this library will vary depending on the installed version of xlrd. + +2. 0.6.3 can write datetime.timedelta. but when the value is read out, +you will get datetime.datetime. so you as the developer decides what to do with it. + New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. @@ -20,7 +30,7 @@ please use pyexcel-xlsx. Warning ================================================================================ -xls file cannot contain more than 65,000 rows. You are risking the reputation +**xls file cannot contain more than 65,000 rows**. You are risking the reputation of yourself/your company/ `your country `_ if you keep using xls and are not aware of its row limit. diff --git a/changelog.yml b/changelog.yml index a755d32..41c68cb 100644 --- a/changelog.yml +++ b/changelog.yml @@ -4,6 +4,7 @@ releases: - changes: - action: Updated details: + - "`#46`: remove the hard pin on xlrd version < 2.0" - "`#47`: limit support to persist datetime.timedelta. see more details in doc" date: tbd version: 0.6.3 diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index d8dbfef..3130bb8 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -8,7 +8,7 @@ file_type: xls is_on_conda: true dependencies: - pyexcel-io>=0.6.2 - - xlrd<2 + - xlrd - xlwt test_dependencies: - pyexcel diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index a688b5b..35c2ed7 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -4,9 +4,10 @@ The lower level xls/xlsx/xlsm file format handler using xlrd/xlwt - :copyright: (c) 2016-2020 by Onni Software Ltd + :copyright: (c) 2016-2021 by Onni Software Ltd :license: New BSD License """ +import xlrd # flake8: noqa from pyexcel_io.io import get_data as read_data @@ -19,20 +20,37 @@ from pyexcel_io.plugins import IOPluginInfoChainV2 __FILE_TYPE__ = "xls" + +def xlrd_version_2_or_greater(): + xlrd_version = getattr(xlrd, "__version__") + + if xlrd_version: + major = int(xlrd_version.split(".")[0]) + if major >= 2: + return True + return False + + +XLRD_VERSION_2_OR_ABOVE = xlrd_version_2_or_greater() +supported_file_formats = [__FILE_TYPE__, "xlsx", "xlsm"] +if XLRD_VERSION_2_OR_ABOVE: + supported_file_formats.remove("xlsx") + + IOPluginInfoChainV2(__name__).add_a_reader( relative_plugin_class_path="xlsr.XLSInFile", locations=["file"], - file_types=[__FILE_TYPE__, "xlsx", "xlsm"], + file_types=supported_file_formats, stream_type="binary", ).add_a_reader( relative_plugin_class_path="xlsr.XLSInMemory", locations=["memory"], - file_types=[__FILE_TYPE__, "xlsx", "xlsm"], + file_types=supported_file_formats, stream_type="binary", ).add_a_reader( relative_plugin_class_path="xlsr.XLSInContent", locations=["content"], - file_types=[__FILE_TYPE__, "xlsx", "xlsm"], + file_types=supported_file_formats, stream_type="binary", ).add_a_writer( relative_plugin_class_path="xlsw.XLSWriter", diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index f38abfc..85a97dd 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -10,7 +10,7 @@ from unittest.mock import MagicMock, patch import pyexcel as pe from _compact import OrderedDict -from pyexcel_xls import save_data +from pyexcel_xls import XLRD_VERSION_2_OR_ABOVE, save_data from pyexcel_xls.xlsr import xldate_to_python_date from pyexcel_xls.xlsw import XLSWriter as Writer @@ -97,6 +97,8 @@ def test_issue_20(): def test_issue_151(): + if XLRD_VERSION_2_OR_ABOVE: + raise SkipTest() s = pe.get_sheet( file_name=get_fixture("pyexcel_issue_151.xlsx"), skip_hidden_row_and_column=False, From 43e14d8704d5361d650748d54fb83e37d89028e9 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 22:01:26 +0100 Subject: [PATCH 151/163] :handshake: update meta data --- .github/workflows/moban-update.yml | 6 ++---- CHANGELOG.rst | 10 ++++++++++ README.rst | 18 ++++++++++++++---- docs/source/conf.py | 2 +- requirements.txt | 2 +- setup.py | 10 +++++----- 6 files changed, 33 insertions(+), 15 deletions(-) diff --git a/.github/workflows/moban-update.yml b/.github/workflows/moban-update.yml index 7248179..73a3aed 100644 --- a/.github/workflows/moban-update.yml +++ b/.github/workflows/moban-update.yml @@ -21,10 +21,8 @@ jobs: git diff --exit-code - name: Auto-commit if: failure() - uses: docker://cdssnc/auto-commit-github-action - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: stefanzweifel/git-auto-commit-action@v4 with: - args: >- + commit_message: >- This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 613b1e5..8c35fa2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,16 @@ Change log ================================================================================ +0.6.3 - tbd +-------------------------------------------------------------------------------- + +**Updated** + +#. `#46 `_: remove the hard + pin on xlrd version < 2.0 +#. `#47 `_: limit support to + persist datetime.timedelta. see more details in doc + 0.6.2 - 12.12.2020 -------------------------------------------------------------------------------- diff --git a/README.rst b/README.rst index 2505490..b4b6546 100644 --- a/README.rst +++ b/README.rst @@ -39,6 +39,16 @@ pyexcel-xls - Let you focus on data, instead of xls format write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. +Update: + +1. v0.6.3 removed the pin on xlrd < 2. If you have xlrd >= 2, this +library will NOT read 'xlsx' format and you need to install pyexcel-xlsx. Othwise, +this library can use xlrd < 2 to read xlsx format for you. So 'xlsx' support +in this library will vary depending on the installed version of xlrd. + +2. 0.6.3 can write datetime.timedelta. but when the value is read out, +you will get datetime.datetime. so you as the developer decides what to do with it. + New flag: `detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. @@ -51,7 +61,7 @@ please use pyexcel-xlsx. Warning ================================================================================ -xls file cannot contain more than 65,000 rows. You are risking the reputation +**xls file cannot contain more than 65,000 rows**. You are risking the reputation of yourself/your company/ `your country `_ if you keep using xls and are not aware of its row limit. @@ -353,7 +363,7 @@ Then install relevant development requirements: #. pip install -r tests/requirements.txt Once you have finished your changes, please provide test case(s), relevant documentation -and update CHANGELOG.rst. +and update changelog.yml .. note:: @@ -372,7 +382,7 @@ On Linux/Unix systems, please launch your tests like this:: $ make -On Windows systems, please issue this command:: +On Windows, please issue this command:: > test.bat @@ -384,7 +394,7 @@ Please run:: $ make format -so as to beautify your code otherwise travis-ci may fail your unit test. +so as to beautify your code otherwise your build may fail your unit test. Known Issues diff --git a/docs/source/conf.py b/docs/source/conf.py index 550ca04..3816479 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -28,7 +28,7 @@ author = 'C.W.' # The short X.Y version version = '0.6.2' # The full version, including alpha/beta/rc tags -release = '0.6.2' +release = '0.6.3' # -- General configuration --------------------------------------------------- diff --git a/requirements.txt b/requirements.txt index 65ffc34..4c06b39 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ pyexcel-io>=0.6.2 -xlrd<2 +xlrd xlwt diff --git a/setup.py b/setup.py index 9000415..663c693 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ except (ValueError, UnicodeError, locale.Error): NAME = "pyexcel-xls" AUTHOR = "C.W." -VERSION = "0.6.2" +VERSION = "0.6.3" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" DESCRIPTION = ( @@ -40,7 +40,7 @@ DESCRIPTION = ( "reads xlsx and xlsm format" ) URL = "https://github.com/pyexcel/pyexcel-xls" -DOWNLOAD_URL = "%s/archive/0.6.2.tar.gz" % URL +DOWNLOAD_URL = "%s/archive/0.6.3.tar.gz" % URL FILES = ["README.rst","CONTRIBUTORS.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", @@ -69,7 +69,7 @@ PYTHON_REQUIRES = ">=3.6" INSTALL_REQUIRES = [ "pyexcel-io>=0.6.2", - "xlrd<2", + "xlrd", "xlwt", ] SETUP_COMMANDS = {} @@ -81,8 +81,8 @@ EXTRAS_REQUIRE = { PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) HERE = os.path.abspath(os.path.dirname(__file__)) -GS_COMMAND = ("gease pyexcel-xls v0.6.2 " + - "Find 0.6.2 in changelog for more details") +GS_COMMAND = ("gease pyexcel-xls v0.6.3 " + + "Find 0.6.3 in changelog for more details") NO_GS_MESSAGE = ("Automatic github release is disabled. " + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( From a7efa57ea8fe49246095a4a21d664bec8d8d47fc Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 22:04:21 +0100 Subject: [PATCH 152/163] :book: update docs --- .moban.d/custom_README.rst.jj2 | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.moban.d/custom_README.rst.jj2 b/.moban.d/custom_README.rst.jj2 index 700f5c4..e839606 100644 --- a/.moban.d/custom_README.rst.jj2 +++ b/.moban.d/custom_README.rst.jj2 @@ -8,21 +8,25 @@ write data in {{file_type}} format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. -Update: +Oct 2021 - Update: +=================== 1. v0.6.3 removed the pin on xlrd < 2. If you have xlrd >= 2, this library will NOT read 'xlsx' format and you need to install pyexcel-xlsx. Othwise, this library can use xlrd < 2 to read xlsx format for you. So 'xlsx' support in this library will vary depending on the installed version of xlrd. -2. 0.6.3 can write datetime.timedelta. but when the value is read out, +2. v0.6.3 can write datetime.timedelta. but when the value is read out, you will get datetime.datetime. so you as the developer decides what to do with it. -New flag: `detect_merged_cells` allows you to spread the same value among +Past news +=========== + +`detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. -New flag: `skip_hidden_row_and_column` allows you to skip hidden rows +`skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. From 7fe88615418a23c0e1271405e38ff3e989e2b088 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 21:04:55 +0000 Subject: [PATCH 153/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- README.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index b4b6546..b1e503b 100644 --- a/README.rst +++ b/README.rst @@ -39,21 +39,25 @@ pyexcel-xls - Let you focus on data, instead of xls format write data in xls format and it can read xlsx and xlsm fromat. You are likely to use it with `pyexcel `_. -Update: +Oct 2021 - Update: +=================== 1. v0.6.3 removed the pin on xlrd < 2. If you have xlrd >= 2, this library will NOT read 'xlsx' format and you need to install pyexcel-xlsx. Othwise, this library can use xlrd < 2 to read xlsx format for you. So 'xlsx' support in this library will vary depending on the installed version of xlrd. -2. 0.6.3 can write datetime.timedelta. but when the value is read out, +2. v0.6.3 can write datetime.timedelta. but when the value is read out, you will get datetime.datetime. so you as the developer decides what to do with it. -New flag: `detect_merged_cells` allows you to spread the same value among +Past news +=========== + +`detect_merged_cells` allows you to spread the same value among all merged cells. But be aware that this may slow down its reading performance. -New flag: `skip_hidden_row_and_column` allows you to skip hidden rows +`skip_hidden_row_and_column` allows you to skip hidden rows and columns and is defaulted to **True**. It may slow down its reading performance. And it is only valid for 'xls' files. For 'xlsx' files, please use pyexcel-xlsx. From d6fcafdb389b51dd18c2afa1d35e71ea7abc8ee2 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 22:41:22 +0100 Subject: [PATCH 154/163] :fire: remove 3.6 tests because macOS lacks of 3.6 support --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 86ab9f8..2c014f4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.7, 3.8, 3.9] os: [macOs-latest, ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} From 8d6cc2de5611f41a6305bbe7d46114459fd6da85 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 21:41:58 +0000 Subject: [PATCH 155/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2c014f4..86ab9f8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.7, 3.8, 3.9] + python-version: [3.6, 3.7, 3.8, 3.9] os: [macOs-latest, ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} From 514f99b616d1f1f2dc34d04a83638bac251391bf Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 22:51:58 +0100 Subject: [PATCH 156/163] :fire: remove 3.6 test on macos because macOS lacks of 3.6 support --- .github/workflows/tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 86ab9f8..ab86c77 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,6 +9,9 @@ jobs: matrix: python-version: [3.6, 3.7, 3.8, 3.9] os: [macOs-latest, ubuntu-latest, windows-latest] + exclude: + - os: macos-latest + python-version: 3.6 runs-on: ${{ matrix.os }} name: run tests From 2efe4f458b72296b50acd558143a9ee80a796f6c Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 23:13:50 +0100 Subject: [PATCH 157/163] :books: get ready for release --- changelog.yml | 2 +- pyexcel-xls.yml | 2 +- pyexcel_xls/xlsr.py | 2 +- pyexcel_xls/xlsw.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/changelog.yml b/changelog.yml index 41c68cb..e1c3215 100644 --- a/changelog.yml +++ b/changelog.yml @@ -6,7 +6,7 @@ releases: details: - "`#46`: remove the hard pin on xlrd version < 2.0" - "`#47`: limit support to persist datetime.timedelta. see more details in doc" - date: tbd + date: 07.10.2021 version: 0.6.3 - changes: - action: Updated diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 3130bb8..53dacfa 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -1,7 +1,7 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.6.2 +version: 0.6.3 current_version: 0.6.3 release: 0.6.3 file_type: xls diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 8e679c7..c9f15e8 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -4,7 +4,7 @@ The lower level xls/xlsm file format handler using xlrd - :copyright: (c) 2016-2020 by Onni Software Ltd + :copyright: (c) 2016-2021 by Onni Software Ltd :license: New BSD License """ import datetime diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index a127525..f70ec64 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -4,7 +4,7 @@ The lower level xls file format handler using xlwt - :copyright: (c) 2016-2020 by Onni Software Ltd + :copyright: (c) 2016-2021 by Onni Software Ltd :license: New BSD License """ import datetime From dcd4571d82f37c2d4e350056945f0ef5834823c7 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 22:14:20 +0000 Subject: [PATCH 158/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- CHANGELOG.rst | 2 +- docs/source/conf.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8c35fa2..33a4bcd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Change log ================================================================================ -0.6.3 - tbd +0.6.3 - 07.10.2021 -------------------------------------------------------------------------------- **Updated** diff --git a/docs/source/conf.py b/docs/source/conf.py index 3816479..17b9ba7 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,7 @@ project = 'pyexcel-xls' copyright = '2015-2021 Onni Software Ltd.' author = 'C.W.' # The short X.Y version -version = '0.6.2' +version = '0.6.3' # The full version, including alpha/beta/rc tags release = '0.6.3' From 77ad65cdda18941bf7e630bc4cccd5d734199e09 Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 23:16:08 +0100 Subject: [PATCH 159/163] :books: pump up the major version number because it has a breaking change --- changelog.yml | 6 ++++-- pyexcel-xls.yml | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/changelog.yml b/changelog.yml index e1c3215..7193acf 100644 --- a/changelog.yml +++ b/changelog.yml @@ -2,12 +2,14 @@ name: pyexcel-xls organisation: pyexcel releases: - changes: - - action: Updated + - action: Removed details: - "`#46`: remove the hard pin on xlrd version < 2.0" + - action: Added + details: - "`#47`: limit support to persist datetime.timedelta. see more details in doc" date: 07.10.2021 - version: 0.6.3 + version: 0.7.0 - changes: - action: Updated details: diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml index 53dacfa..23bc91c 100644 --- a/pyexcel-xls.yml +++ b/pyexcel-xls.yml @@ -1,9 +1,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-xls" nick_name: xls -version: 0.6.3 -current_version: 0.6.3 -release: 0.6.3 +version: 0.7.0 +current_version: 0.7.0 +release: 0.7.0 file_type: xls is_on_conda: true dependencies: From 242dbd757a79749d40ee310c47fc51e3e0e3fa5f Mon Sep 17 00:00:00 2001 From: chfw Date: Wed, 6 Oct 2021 22:16:47 +0000 Subject: [PATCH 160/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- CHANGELOG.rst | 7 +++++-- docs/source/conf.py | 4 ++-- setup.py | 8 ++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 33a4bcd..205f54f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,13 +1,16 @@ Change log ================================================================================ -0.6.3 - 07.10.2021 +0.7.0 - 07.10.2021 -------------------------------------------------------------------------------- -**Updated** +**Removed** #. `#46 `_: remove the hard pin on xlrd version < 2.0 + +**Added** + #. `#47 `_: limit support to persist datetime.timedelta. see more details in doc diff --git a/docs/source/conf.py b/docs/source/conf.py index 17b9ba7..dc7ae98 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,9 +26,9 @@ project = 'pyexcel-xls' copyright = '2015-2021 Onni Software Ltd.' author = 'C.W.' # The short X.Y version -version = '0.6.3' +version = '0.7.0' # The full version, including alpha/beta/rc tags -release = '0.6.3' +release = '0.7.0' # -- General configuration --------------------------------------------------- diff --git a/setup.py b/setup.py index 663c693..0763a62 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ except (ValueError, UnicodeError, locale.Error): NAME = "pyexcel-xls" AUTHOR = "C.W." -VERSION = "0.6.3" +VERSION = "0.7.0" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" DESCRIPTION = ( @@ -40,7 +40,7 @@ DESCRIPTION = ( "reads xlsx and xlsm format" ) URL = "https://github.com/pyexcel/pyexcel-xls" -DOWNLOAD_URL = "%s/archive/0.6.3.tar.gz" % URL +DOWNLOAD_URL = "%s/archive/0.7.0.tar.gz" % URL FILES = ["README.rst","CONTRIBUTORS.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", @@ -81,8 +81,8 @@ EXTRAS_REQUIRE = { PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) HERE = os.path.abspath(os.path.dirname(__file__)) -GS_COMMAND = ("gease pyexcel-xls v0.6.3 " + - "Find 0.6.3 in changelog for more details") +GS_COMMAND = ("gease pyexcel-xls v0.7.0 " + + "Find 0.7.0 in changelog for more details") NO_GS_MESSAGE = ("Automatic github release is disabled. " + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( From ad4aa689dfdbe2e27fc3e9d07dea6ed4eacc3867 Mon Sep 17 00:00:00 2001 From: chfw Date: Thu, 7 Oct 2021 19:56:22 +0100 Subject: [PATCH 161/163] :bug: fix syntax error --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ab86c77..914c82a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,8 +10,8 @@ jobs: python-version: [3.6, 3.7, 3.8, 3.9] os: [macOs-latest, ubuntu-latest, windows-latest] exclude: - - os: macos-latest - python-version: 3.6 + - os: macOs-latest + python-version: 3.6 runs-on: ${{ matrix.os }} name: run tests From b80ea1108223f2d670f692097d30f9ba2ba64b05 Mon Sep 17 00:00:00 2001 From: jaska Date: Fri, 8 Oct 2021 07:44:20 +0100 Subject: [PATCH 162/163] Update custom_README.rst.jj2 --- .moban.d/custom_README.rst.jj2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.moban.d/custom_README.rst.jj2 b/.moban.d/custom_README.rst.jj2 index e839606..719ed79 100644 --- a/.moban.d/custom_README.rst.jj2 +++ b/.moban.d/custom_README.rst.jj2 @@ -11,12 +11,12 @@ You are likely to use it with `pyexcel `_. Oct 2021 - Update: =================== -1. v0.6.3 removed the pin on xlrd < 2. If you have xlrd >= 2, this +1. v0.7.0 removed the pin on xlrd < 2. If you have xlrd >= 2, this library will NOT read 'xlsx' format and you need to install pyexcel-xlsx. Othwise, this library can use xlrd < 2 to read xlsx format for you. So 'xlsx' support in this library will vary depending on the installed version of xlrd. -2. v0.6.3 can write datetime.timedelta. but when the value is read out, +2. v0.7.0 can write datetime.timedelta. but when the value is read out, you will get datetime.datetime. so you as the developer decides what to do with it. Past news From 995cfd273d5360947a528ff3a1ed3f9e52a429ad Mon Sep 17 00:00:00 2001 From: chfw Date: Fri, 8 Oct 2021 06:44:46 +0000 Subject: [PATCH 163/163] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index b1e503b..4dbbeae 100644 --- a/README.rst +++ b/README.rst @@ -42,12 +42,12 @@ You are likely to use it with `pyexcel `_. Oct 2021 - Update: =================== -1. v0.6.3 removed the pin on xlrd < 2. If you have xlrd >= 2, this +1. v0.7.0 removed the pin on xlrd < 2. If you have xlrd >= 2, this library will NOT read 'xlsx' format and you need to install pyexcel-xlsx. Othwise, this library can use xlrd < 2 to read xlsx format for you. So 'xlsx' support in this library will vary depending on the installed version of xlrd. -2. v0.6.3 can write datetime.timedelta. but when the value is read out, +2. v0.7.0 can write datetime.timedelta. but when the value is read out, you will get datetime.datetime. so you as the developer decides what to do with it. Past news