From aa7222de6124fee9e8707bfe5a1abbf4f7f601e9 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 10 Nov 2018 22:26:43 +0000 Subject: [PATCH 01/38] :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 @@ # 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 @@ # 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 @@ 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 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 @@ 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 02/38] :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 @@ def __init__(self, sheet, auto_detect_int=True, date_mode=0, **keywords): 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 @@ def cell_value(self, row, column): """ 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 @@ def open_content(self, file_content, **keywords): 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 @@ def read_all(self): 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 @@ def write_row(self, array): 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 @@ def test_write_array(self): class PyexcelMultipleSheetBase: - def _write_test_file(self, filename): pyexcel.save_book_as(bookdict=self.content, dest_file_name=filename) @@ -80,7 +83,7 @@ def test_reading_through_sheets(self): 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 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') + 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 @@ def setUp(self): [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 @@ def test_reading_date_format(self): 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 @@ def test_reading_date_format(self): 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 @@ def _write_test_file(self, file): 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 @@ def setUp(self): 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 @@ def setUp(self): 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: +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 03/38] :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 | 113 ++++++++------- 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, 217 insertions(+), 266 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 @@ ' 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 @@ # -- 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 @@ # 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 @@ # 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 @@ # 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 - -NAME = 'pyexcel-xls' -AUTHOR = 'C.W.' -VERSION = '0.6.0' -EMAIL = 'wangc_2011@hotmail.com' -LICENSE = 'New BSD' +PY33 = sys.version_info < (3, 4) + +# 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 @@ 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 @@ def finalize_options(self): 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 @@ def run(self): 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 @@ def filter_out_test_code(file_handle): 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 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 04/38] :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 05/38] :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 06/38] :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 @@ # -- 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 @@ 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 07/38] :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 08/38] :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 09/38] :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 10/38] :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 @@ "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 @@ ] 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 11/38] :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 @@ 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 @@ 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 12/38] 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 13/38] :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 @@ ) 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 14/38] :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 f14d1e2166f19273246603a333bf64af2fd14eb8 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 29 Aug 2020 20:40:38 +0000 Subject: [PATCH 15/38] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst From a07d3ca735756e23fdd20586fad1d0bb2a5dcf81 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 19 Sep 2020 19:34:13 +0100 Subject: [PATCH 16/38] :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 ed37444191c3a59745d63a4bee46b30a04626728 Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 19 Sep 2020 18:34:58 +0000 Subject: [PATCH 17/38] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst From fba69516be9df9e804ae2e282fd4c905396050df Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 19 Sep 2020 21:16:49 +0100 Subject: [PATCH 18/38] :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 2789cb53d160fa40058ae15d29b55d4818584c7a Mon Sep 17 00:00:00 2001 From: chfw Date: Sat, 19 Sep 2020 20:17:46 +0000 Subject: [PATCH 19/38] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst From 2459ede331809e114effddced065bf2300bd438a Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 20 Sep 2020 12:04:22 +0100 Subject: [PATCH 20/38] :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 25647ac3659e4d2a987ba9599ecc78b099bb38cc Mon Sep 17 00:00:00 2001 From: chfw Date: Sun, 20 Sep 2020 11:04:59 +0000 Subject: [PATCH 21/38] This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst From d3b57b434b7a4920dcf02e2be5d054259e42736b Mon Sep 17 00:00:00 2001 From: jaska Date: Tue, 29 Sep 2020 22:26:05 +0100 Subject: [PATCH 22/38] 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 | 134 +++++++++++------------------ pyexcel_xls/xlsw.py | 33 ++++--- rnd_requirements.txt | 2 +- tests/test_bug_fixes.py | 12 ++- tests/test_filter.py | 3 +- tests/test_writer.py | 8 +- 13 files changed, 126 insertions(+), 147 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 @@ # 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 @@ def register_cells(self, registry): 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 @@ def __init__(self, sheet, auto_detect_int=True, date_mode=0, **keywords): 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 - 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() + 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 - data_dict = self.read_sheet(sheet) - result.update(data_dict) - return result + self.content_array.append(sheet) - def read_sheet(self, native_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.name: sheet.to_array()} + return sheet - 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 close(self): + if self._native_book: + self._native_book.release_resources() + self._native_book = None + + def get_xls_book(self, **xlrd_params): xls_book = xlrd.open_workbook(**xlrd_params) return xls_book @@ -226,6 +178,24 @@ def _extract_xlrd_params(self): 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 @@ def write_row(self, array): 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 create_sheet(self, name): + return XLSheetWriter(self.work_book, None, name) + def write(self, incoming_dict): if incoming_dict: - BookWriter.write(self, incoming_dict) + IWriter.write(self, incoming_dict) else: raise NotImplementedError(EMPTY_SHEET_NOT_ALLOWED) - def create_sheet(self, name): - return XLSheetWriter(self.work_book, None, name) - 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.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 @@ def test_write_book(self): "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 23/38] :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 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 @@ def __init__(self, row_low, row_high, column_low, 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): + 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 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 @@ 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 @@ def write_row(self, array): 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 24/38] :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 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 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 25/38] 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 26/38] :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 @@ def __init__(self, sheet, auto_detect_int=True, date_mode=0, **keywords): 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 @@ def cell_value(self, 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) + 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 @@ def __init__(self, file_type, **keywords): 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 @@ def read_sheet(self, index): 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 @@ def __init__( 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 @@ def close(self): """ 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 27/38] :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 @@ def test_write_book(self): 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 28/38] :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 29/38] 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 30/38] :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 @@ # 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 @@ "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 @@ } # 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 31/38] :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 @@ # -- 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 32/38] :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 33/38] :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 34/38] :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 35/38] 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 36/38] 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 @@ 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 37/38] 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 38/38] 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 --------------------------------------------------------------------------------