diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6017f21..8996445 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,6 +4,5 @@ With your PR, here is a check list: - [ ] Has all code lines tested? - [ ] Has `make format` been run? - [ ] Please update CHANGELOG.yml(not CHANGELOG.rst) -- [ ] Passes all Travis CI builds - [ ] Has fair amount of documentation if your change is complex - [ ] Agree on NEW BSD License for your contribution diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..b254739 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,20 @@ +name: lint + +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + name: lint code + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.11 + - name: lint + run: | + pip --use-deprecated=legacy-resolver install flake8 + pip --use-deprecated=legacy-resolver install -r tests/requirements.txt + flake8 --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long . + python setup.py checkdocs diff --git a/.github/workflows/moban-update.yml b/.github/workflows/moban-update.yml index 706fd82..a68ef81 100644 --- a/.github/workflows/moban-update.yml +++ b/.github/workflows/moban-update.yml @@ -8,22 +8,22 @@ jobs: - uses: actions/checkout@v2 with: ref: ${{ github.head_ref }} + token: ${{ secrets.PAT }} - name: Set up Python uses: actions/setup-python@v1 with: - python-version: '3.7' + python-version: '3.11' - name: check changes run: | - pip install moban gitfs2 pypifs moban-jinja2-github moban-ansible + pip install markupsafe==2.0.1 + pip install ruamel.yaml 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 }} + uses: stefanzweifel/git-auto-commit-action@v4 with: - args: >- + commit_message: >- This is an auto-commit, updating project meta data, such as changelog.rst, contributors.rst diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 9e7ec42..4ccaa8d 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -5,9 +5,16 @@ on: types: [created] jobs: - deploy: + pypi-publish: + name: upload release to PyPI runs-on: ubuntu-latest + # Specifying a GitHub environment is optional, but strongly encouraged + environment: pypi + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing + id-token: write steps: + # retrieve your distributions here - uses: actions/checkout@v1 - name: Set up Python uses: actions/setup-python@v1 @@ -16,11 +23,9 @@ jobs: - 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 }} + pip install setuptools wheel + - name: Build run: | python setup.py sdist bdist_wheel - twine upload dist/* + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..3fc8671 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,35 @@ +name: Run unit tests on Windows, Ubuntu and Mac + +on: [push, pull_request] + +jobs: + + test: + name: ${{ matrix.os }} / ${{ matrix.python_version }} + runs-on: ${{ matrix.os }}-latest + strategy: + fail-fast: false + matrix: + os: [Ubuntu] + python_version: ["3.9.16"] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python_version }} + architecture: x64 + + - name: install + run: | + pip --use-deprecated=legacy-resolver install -r requirements.txt + pip --use-deprecated=legacy-resolver install -r tests/requirements.txt + - name: test + run: | + pip freeze + nosetests --verbosity=3 --with-coverage --cover-package pyexcel_xlsx --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xlsx + - name: Upload coverage + uses: codecov/codecov-action@v1 + with: + name: ${{ matrix.os }} Python ${{ matrix.python-version }} \ No newline at end of file diff --git a/.moban.d/custom_travis.yml.jj2 b/.moban.d/custom_travis.yml.jj2 deleted file mode 100644 index ecac24e..0000000 --- a/.moban.d/custom_travis.yml.jj2 +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "travis.yml.jj2" %} - -{%block custom_python_versions%} -python: - - 3.8 - - 3.7 - - 3.6 -{%endblock%} diff --git a/.moban.yml b/.moban.yml index 6ee6b10..39401de 100644 --- a/.moban.yml +++ b/.moban.yml @@ -6,7 +6,6 @@ targets: - README.rst: custom_README.rst.jj2 - setup.py: custom_setup.py.jj2 - "docs/source/conf.py": "docs/source/conf.py.jj2" - - .travis.yml: custom_travis.yml.jj2 - MANIFEST.in: MANIFEST.in.jj2 - .gitignore: gitignore.jj2 - "tests/requirements.txt": "tests/requirements.txt" diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..ffc9465 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,21 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/source/conf.py + +# Optionally build your docs in additional formats such as PDF +formats: + - pdf + +python: diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9cb4e91..0000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -sudo: false -dist: xenial -language: python -notifications: - email: false -python: - - 3.8 - - 3.7 - - 3.6 - -stages: - - lint - - test - - -.lint: &lint - git: - submodules: false - python: 3.6 - env: - - MINREQ=0 - stage: lint - script: make lint - -jobs: - include: - - *moban - - *lint - -stage: test - -before_install: - - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then - mv min_requirements.txt requirements.txt ; - fi - - test ! -f rnd_requirements.txt || - pip install --no-deps -r rnd_requirements.txt - - test ! -f rnd_requirements.txt || pip install -r rnd_requirements.txt ; - - pip install -r tests/requirements.txt -script: - - make test -after_success: - codecov diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fa56192..bc47779 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,13 @@ Change log ================================================================================ +0.6.1 - 10.11.2024 +-------------------------------------------------------------------------------- + +**Updated** + +#. Compatability with openpyxl 3.1.0 and later + 0.6.0 - 10.10.2020 -------------------------------------------------------------------------------- diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 933a4be..f1d8c27 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -1,10 +1,12 @@ -3 contributors +5 contributors ================================================================================ In alphabetical order: * `Benoit Pierre `_ +* `Chun-Sheng, Li `_ +* `Craig Anderson `_ * `John Vandenberg `_ * `Stephen J. Fuhry `_ diff --git a/LICENSE b/LICENSE index 8238af6..ba61862 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2020 by Onni Software Ltd. and its contributors +Copyright (c) 2015-2022 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-xlsx' 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 diff --git a/README.rst b/README.rst index d2160f5..858675d 100644 --- a/README.rst +++ b/README.rst @@ -5,12 +5,9 @@ pyexcel-xlsx - Let you focus on data, instead of xlsx format .. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png :target: https://www.patreon.com/chfw -.. image:: https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg +.. image:: https://raw.githubusercontent.com/pyexcel/pyexcel-mobans/master/images/awesome-badge.svg :target: https://awesome-python.com/#specific-formats-processing -.. image:: https://travis-ci.org/pyexcel/pyexcel-xlsx.svg?branch=master - :target: http://travis-ci.org/pyexcel/pyexcel-xlsx - .. image:: https://codecov.io/gh/pyexcel/pyexcel-xlsx/branch/master/graph/badge.svg :target: https://codecov.io/gh/pyexcel/pyexcel-xlsx @@ -20,8 +17,9 @@ pyexcel-xlsx - Let you focus on data, instead of xlsx format .. image:: https://anaconda.org/conda-forge/pyexcel-xlsx/badges/version.svg :target: https://anaconda.org/conda-forge/pyexcel-xlsx + .. image:: https://pepy.tech/badge/pyexcel-xlsx/month - :target: https://pepy.tech/project/pyexcel-xlsx/month + :target: https://pepy.tech/project/pyexcel-xlsx .. image:: https://anaconda.org/conda-forge/pyexcel-xlsx/badges/downloads.svg :target: https://anaconda.org/conda-forge/pyexcel-xlsx @@ -48,18 +46,11 @@ 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`. +product, please support me on github, or `patreon `_ +maintain the project and develop it further. -With your financial support, I will be able to invest -a little bit more time in coding, documentation and writing interesting posts. +With your financial support, I will be able to invest a little bit more time in coding, +documentation and writing interesting posts. Known constraints @@ -67,6 +58,8 @@ Known constraints Fonts, colors and charts are not supported. +Nor to read password protected xls, xlsx and ods files. + Installation ================================================================================ @@ -338,26 +331,29 @@ Then install relevant development requirements: #. pip install -r tests/requirements.txt Once you have finished your changes, please provide test case(s), relevant documentation -and update CHANGELOG.rst. +and update changelog.yml .. note:: As to rnd_requirements.txt, usually, it is created when a dependent - library is not released. Once the dependecy is installed + library is not released. Once the dependency is installed (will be released), the future version of the dependency in the requirements.txt will be valid. How to test your contribution ------------------------------- +-------------------------------------------------------------------------------- -Although `nose` and `doctest` are both used in code testing, it is adviable that unit tests are put in tests. `doctest` is incorporated only to make sure the code examples in documentation remain valid across different development releases. +Although `nose` and `doctest` are both used in code testing, it is advisable +that unit tests are put in tests. `doctest` is incorporated only to make sure +the code examples in documentation remain valid across different development +releases. On Linux/Unix systems, please launch your tests like this:: $ make -On Windows systems, please issue this command:: +On Windows, please issue this command:: > test.bat @@ -369,7 +365,7 @@ Please run:: $ make format -so as to beautify your code otherwise travis-ci may fail your unit test. +so as to beautify your code otherwise your build may fail your unit test. diff --git a/changelog.yml b/changelog.yml index e29bbef..3a40182 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-xlsx organisation: pyexcel releases: +- changes: + - action: Updated + details: + - 'Compatability with openpyxl 3.1.0 and later' + date: 10.11.2024 + version: 0.6.1 - changes: - action: Updated details: diff --git a/docs/source/conf.py b/docs/source/conf.py index b190c67..8046233 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,12 +23,12 @@ # -- Project information ----------------------------------------------------- project = 'pyexcel-xlsx' -copyright = '2015-2020 Onni Software Ltd.' -author = 'chfw' +copyright = '2015-2022 Onni Software Ltd.' +author = 'C.W.' # The short X.Y version -version = '0.6.0' +version = '0.6.1' # The full version, including alpha/beta/rc tags -release = '0.6.0' +release = '0.6.1' # -- General configuration --------------------------------------------------- @@ -58,7 +58,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = 'sphinx_rtd_theme' # 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, @@ -69,7 +69,8 @@ # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/3/': None} +intersphinx_mapping = {'python': ('https://docs.python.org/3', + 'python-inv.txt')} # TODO: html_theme not configurable upstream html_theme = 'default' diff --git a/lint.sh b/lint.sh index 891aa63..d31eeaa 100644 --- a/lint.sh +++ b/lint.sh @@ -1,2 +1,2 @@ pip install flake8 -flake8 --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long . && python setup.py checkdocs +flake8 --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long . && python setup.py checkdocs \ No newline at end of file diff --git a/pyexcel-xlsx.yml b/pyexcel-xlsx.yml index 50c24d0..bc86c18 100644 --- a/pyexcel-xlsx.yml +++ b/pyexcel-xlsx.yml @@ -2,9 +2,9 @@ overrides: "pyexcel.yaml" name: "pyexcel-xlsx" project: "pyexcel-xlsx" nick_name: xlsx -version: 0.6.0 -current_version: 0.6.0 -release: 0.6.0 +version: 0.6.1 +current_version: 0.6.1 +release: 0.6.1 file_type: xlsx gitignore_language: Python is_on_conda: true @@ -12,6 +12,7 @@ dependencies: - openpyxl>=2.6.1 - pyexcel-io>=0.6.2 test_dependencies: + - xlrd==1.2.0 - pyexcel-xls - pyexcel description: A wrapper library to read, manipulate and write data in xlsx and xlsm format diff --git a/pyexcel_xlsx/__init__.py b/pyexcel_xlsx/__init__.py index 43fbb64..a9b6f67 100644 --- a/pyexcel_xlsx/__init__.py +++ b/pyexcel_xlsx/__init__.py @@ -1,12 +1,13 @@ """ - pyexcel_xlsx - ~~~~~~~~~~~~~~~~~~~ +pyexcel_xlsx +~~~~~~~~~~~~~~~~~~~ - The lower level xlsx file format handler using openpyxl +The lower level xlsx file format handler using openpyxl - :copyright: (c) 2015-2019 by Onni Software Ltd & its contributors - :license: New BSD License +:copyright: (c) 2015-2019 by Onni Software Ltd & its contributors +:license: New BSD License """ + 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 diff --git a/pyexcel_xlsx/xlsxr.py b/pyexcel_xlsx/xlsxr.py index cfa7cee..919572c 100644 --- a/pyexcel_xlsx/xlsxr.py +++ b/pyexcel_xlsx/xlsxr.py @@ -1,12 +1,13 @@ """ - pyexcel_xlsx.xlsxr - ~~~~~~~~~~~~~~~~~~~ +pyexcel_xlsx.xlsxr +~~~~~~~~~~~~~~~~~~~ - Read xlsx file format using openpyxl +Read xlsx file format using openpyxl - :copyright: (c) 2015-2020 by Onni Software Ltd & its contributors - :license: New BSD License +:copyright: (c) 2015-2020 by Onni Software Ltd & its contributors +:license: New BSD License """ + from io import BytesIO import openpyxl @@ -69,7 +70,7 @@ def __init__(self, sheet, **keywords): self.max_column = 0 self.__sheet_max_row = sheet.max_row self.__sheet_max_column = sheet.max_column - for ranges in sheet.merged_cells.ranges[:]: + for ranges in list(sheet.merged_cells.ranges)[:]: merged_cells = MergedCell(ranges) merged_cells.register_cells(self.__merged_cells) if self.max_row < merged_cells.bottom_row(): diff --git a/pyexcel_xlsx/xlsxw.py b/pyexcel_xlsx/xlsxw.py index f9848d5..b41e6f4 100644 --- a/pyexcel_xlsx/xlsxw.py +++ b/pyexcel_xlsx/xlsxw.py @@ -1,12 +1,13 @@ """ - pyexcel_xlsx.xlsxw - ~~~~~~~~~~~~~~~~~~~ +pyexcel_xlsx.xlsxw +~~~~~~~~~~~~~~~~~~~ - Write xlsx file format using openpyxl +Write xlsx file format using openpyxl - :copyright: (c) 2015-2020 by Onni Software Ltd & its contributors - :license: New BSD License +:copyright: (c) 2015-2020 by Onni Software Ltd & its contributors +:license: New BSD License """ + import openpyxl from pyexcel_io import constants from pyexcel_io.plugin_api import IWriter, ISheetWriter diff --git a/setup.py b/setup.py index d49d6ce..377ac61 100644 --- a/setup.py +++ b/setup.py @@ -28,8 +28,8 @@ locale.setlocale(locale.LC_ALL, "en_US.UTF-8") NAME = "pyexcel-xlsx" -AUTHOR = "chfw" -VERSION = "0.6.0" +AUTHOR = "C.W." +VERSION = "0.6.1" EMAIL = "info@pyexcel.org" LICENSE = "New BSD" DESCRIPTION = ( @@ -37,7 +37,7 @@ "format" ) URL = "https://github.com/pyexcel/pyexcel-xlsx" -DOWNLOAD_URL = "%s/archive/0.6.0.tar.gz" % URL +DOWNLOAD_URL = "%s/archive/0.6.1.tar.gz" % URL FILES = ["README.rst", "CHANGELOG.rst"] KEYWORDS = [ "python", @@ -73,13 +73,14 @@ } # 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-xlsx v0.6.0 " + - "Find 0.6.0 in changelog for more details") +HERE = os.path.abspath(os.path.dirname(__file__)) + +GS_COMMAND = ("gease pyexcel-xlsx v0.6.1 " + + "Find 0.6.1 in changelog for more details") NO_GS_MESSAGE = ("Automatic github release is disabled. " + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( 'Upload failed. please run "%s" yourself.' % PUBLISH_COMMAND) -HERE = os.path.abspath(os.path.dirname(__file__)) class PublishCommand(Command): @@ -125,7 +126,6 @@ def run(self): "publish": PublishCommand }) - def has_gease(): """ test if github release command is installed diff --git a/tests/base.py b/tests/base.py index 71474a3..08338bc 100644 --- a/tests/base.py +++ b/tests/base.py @@ -83,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 = [["X", "Y", "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/requirements.txt b/tests/requirements.txt index e3c1dbf..9748342 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -9,5 +9,6 @@ collective.checkdocs pygments moban moban_jinja2_github +xlrd==1.2.0 pyexcel-xls pyexcel diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 0e7dd1d..e2e7c29 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -1,8 +1,9 @@ """ - This file keeps all fixes for issues found +This file keeps all fixes for issues found """ + import os import sys import datetime diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 1885dce..c78378a 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -26,8 +26,8 @@ def test_reading_date_format(self): assert isinstance(r[1, 1], datetime.time) is True assert r[1, 1].strftime("%H:%M:%S") == "11:11:11" value = r[4, 0].isoformat() - eq_(value, "1899-12-30T00:00:00") - eq_(r[4, 1].isoformat(), "1899-12-30T00:00:00") + eq_(value, "00:00:00") + eq_(r[4, 1].isoformat(), "00:00:00") def test_writing_date_format(self): import datetime diff --git a/tests/test_multiple_sheets.py b/tests/test_multiple_sheets.py index 7c5160f..50e2ff9 100644 --- a/tests/test_multiple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -247,6 +247,6 @@ def _produce_ordered_dict(): 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]]} + {"Sheet3": [["X", "Y", "Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]]} ) return data_dict diff --git a/tests/test_reader.py b/tests/test_reader.py index 87a4da7..87dcc8f 100644 --- a/tests/test_reader.py +++ b/tests/test_reader.py @@ -1,17 +1,17 @@ import os -from datetime import datetime, time +from datetime import time, datetime -from nose.tools import eq_ +from pyexcel_xlsx import get_data from pyexcel_io._compact import OrderedDict -from pyexcel_xlsx import get_data +from nose.tools import eq_ def test_reading(): data = get_data( os.path.join("tests", "fixtures", "date_field.xlsx"), library="pyexcel-xlsx", - skip_hidden_row_and_column=False + skip_hidden_row_and_column=False, ) expected = OrderedDict() expected.update( @@ -30,10 +30,7 @@ def test_reading(): datetime(2015, 1, 1, 0, 0), time(hour=13, minute=13, second=13), ], - [ - datetime(year=1899, month=12, day=30), - datetime(1899, 12, 30, 0, 0), - ], + [time(0, 0), time(0, 0)], ] } ) diff --git a/tests/test_writer.py b/tests/test_writer.py index b54d556..8575f63 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -10,7 +10,7 @@ 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": [["X", "Y", "Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]], } self.testfile = "writer.xlsx" writer = Writer(self.testfile, "xlsx")