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..6017f21 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +With your PR, here is a check list: + +- [ ] 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 +- [ ] 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..706fd82 --- /dev/null +++ b/.github/workflows/moban-update.yml @@ -0,0 +1,29 @@ +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-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/.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/.gitignore b/.gitignore index d09b336..e8b12f9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ parts/ sdist/ var/ wheels/ +share/python-wheels/ *.egg-info/ .installed.cfg *.egg @@ -43,14 +44,17 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ +.nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover +*.py,cover .hypothesis/ .pytest_cache/ +cover/ # Translations *.mo @@ -60,6 +64,7 @@ coverage.xml *.log local_settings.py db.sqlite3 +db.sqlite3-journal # Flask stuff: instance/ @@ -72,16 +77,34 @@ instance/ docs/_build/ # PyBuilder +.pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints +# IPython +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 +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ -# celery beat schedule file +# Celery stuff celerybeat-schedule +celerybeat.pid # SageMath parsed files *.sage.py @@ -107,6 +130,17 @@ venv.bak/ # mypy .mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ # VirtualEnv rules # Virtualenv @@ -140,6 +174,7 @@ pip-selfcheck.json # Windows rules # Windows thumbnail cache files Thumbs.db +Thumbs.db:encryptable ehthumbs.db ehthumbs_vista.db @@ -238,9 +273,14 @@ flycheck_*.el # directory configuration .dir-locals.el +# network security +/network-security.data + + # 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] @@ -248,6 +288,7 @@ flycheck_*.el # Session Session.vim +Sessionx.vim # Temporary .netrwhist @@ -258,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 @@ -268,6 +309,9 @@ tags .idea/**/dictionaries .idea/**/shelf +# Generated files +.idea/**/contentModel.xml + # Sensitive or high-churn files .idea/**/dataSources/ .idea/**/dataSources.ids @@ -281,6 +325,19 @@ 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/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + # CMake cmake-build-*/ @@ -311,6 +368,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 @@ -326,6 +386,7 @@ fabric.properties # SFTP configuration file sftp-config.json +sftp-config-alt*.json # Package control specific files Package Control.last-run @@ -363,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 @@ -389,8 +454,10 @@ DerivedData/ *.perspectivev3 !default.perspectivev3 -# Eclipse rules +## Gcc Patch +/*.gcno +# Eclipse rules .metadata bin/ tmp/ @@ -441,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 @@ -468,3 +540,7 @@ cscope.files cscope.out cscope.in.out cscope.po.out + + +# remove moban hash dictionary +.moban.hashes diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..9d0ef8b --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,10 @@ +[settings] +line_length=79 +known_first_party=lml, pyexcel_io, odf +known_third_party=nose +indent=' ' +multi_line_output=3 +length_sort=1 +default_section=FIRSTPARTY +no_lines_before=LOCALFOLDER +sections=FUTURE,STDLIB,FIRSTPARTY,THIRDPARTY,LOCALFOLDER diff --git a/.moban.d/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/custom_travis.yml.jj2 b/.moban.d/custom_travis.yml.jj2 new file mode 100644 index 0000000..d330a08 --- /dev/null +++ b/.moban.d/custom_travis.yml.jj2 @@ -0,0 +1,13 @@ +{% extends "travis.yml.jj2" %} +{%block extra_matrix %} +env: + - MINREQ=1 +{%endblock%} +{%block custom_python_versions%} +python: + - 3.8 + - 3.7 + - 3.6 +{%endblock%} +{%block pypi_deployment%} +{%endblock %} diff --git a/.moban.d/travis.yml b/.moban.d/travis.yml deleted file mode 100644 index a94a221..0000000 --- a/.moban.d/travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "travis.yml.jj2" %} - -{%block custom_python_versions%} -python: - - 3.8-dev - - 3.7 - - 3.6 - - 3.5 - - 2.7 -{%endblock%} - diff --git a/.moban.yml b/.moban.yml index 3f061c1..4f49247 100644 --- a/.moban.yml +++ b/.moban.yml @@ -1,33 +1,10 @@ -requires: - - type: git - url: https://github.com/moremoban/pypi-mobans - submodule: true - - https://github.com/pyexcel/pyexcel-mobans +overrides: "git://github.com/pyexcel/pyexcel-mobans!/mobanfile.yaml" configuration: - configuration_dir: "pyexcel-mobans:config" - template_dir: - - "pyexcel-mobans:templates" - - "pypi-mobans:templates" - - ".moban.d" configuration: pyexcel-ods.yml targets: - - README.rst: README.rst - - setup.py: setup.py + - README.rst: custom_README.rst.jj2 + - setup.py: custom_setup.py.jj2 - "docs/source/conf.py": "docs/source/conf.py.jj2" - - .travis.yml: travis.yml + - .travis.yml: custom_travis.yml.jj2 - .gitignore: gitignore.jj2 - - requirements.txt: requirements.txt - - LICENSE: NEW_BSD_LICENSE.jj2 - MANIFEST.in: MANIFEST.in.jj2 - - "tests/requirements.txt": "tests/requirements.txt" - - test.sh: test.script.jj2 - - test.bat: test.script.jj2 - - "tests/test_filter.py": "tests/test_filter.py.jj2" - - "tests/test_formatters.py": "tests/test_formatters.py" - - "tests/test_stringio.py": "tests/test_stringio.py.jj2" - - "tests/test_writer.py": "tests/test_writer.py.jj2" - - "tests/base.py": "tests/base.py.jj2" - - output: CHANGELOG.rst - configuration: changelog.yml - template: CHANGELOG.rst.jj2 - - lint.sh: lint.script.jj2 diff --git a/.travis.yml b/.travis.yml index 324d79f..8718cdd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,43 +4,50 @@ language: python notifications: email: false python: - - 3.8-dev + - 3.8 - 3.7 - 3.6 - - 3.5 - - 2.7 +env: + - MINREQ=1 stages: - - test - lint + - moban + - test -.disable_global: &disable_global - before_install: false - install: true - before_script: false - after_success: false - after_failure: false .lint: &lint - <<: *disable_global + git: + submodules: false python: 3.6 + env: + - MINREQ=0 stage: lint - install: pip install flake8 script: make lint +.moban: &moban + python: 3.6 + env: + - MINREQ=0 + stage: moban + install: pip install moban gitfs2 pypifs moban-jinja2-github moban-ansible + script: + - moban + - git diff --exit-code + jobs: include: + - *moban - *lint stage: test -script: make test - before_install: - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then mv min_requirements.txt requirements.txt ; fi - - test ! -f rnd_requirements.txt || pip install --no-deps -r rnd_requirements.txt + - test ! -f rnd_requirements.txt || + pip install --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 7fb00f1..c2249ed 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,11 +1,17 @@ Change log ================================================================================ +0.6.0 - 9.10.2020 +-------------------------------------------------------------------------------- + +**added** + +#. new style reader and writer plugins. works with pyexcel-io v0.6.2 + 0.5.6 - 19.03.2019 -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `#32 `_, fix odfpy pinning #. `#33 `_, fix @@ -14,16 +20,14 @@ added 0.5.5 - 16.03.2019 -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `#32 `_, fix odfpy pinning 0.5.4 - 27.11.2018 -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `#30 `_, long type will not be written in ods. please use string type. And if the integer is equal or @@ -33,8 +37,7 @@ added 0.5.3 - unreleased -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `#24 `_, ignore comments() in cell @@ -45,8 +48,7 @@ added 0.5.2 - 23.10.2017 -------------------------------------------------------------------------------- -updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**updated** #. pyexcel `pyexcel#105 `_, remove gease from setup_requires, introduced by 0.5.1. @@ -55,8 +57,7 @@ updated 0.5.1 - 20.10.2017 -------------------------------------------------------------------------------- -added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**added** #. `pyexcel#103 `_, include LICENSE file in MANIFEST.in, meaning LICENSE file will appear in the released @@ -65,22 +66,19 @@ added 0.5.0 - 30.08.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. put dependency on pyexcel-io 0.5.0, which uses cStringIO instead of StringIO. Hence, there will be performance boost in handling files in memory. -Relocated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Relocated** #. All ods type conversion code lives in pyexcel_io.service module 0.4.1 - 25.08.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `pyexcel#23 `_, handle unseekable stream given by http response @@ -90,8 +88,7 @@ Updated 0.4.0 - 19.06.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. `pyexcel#14 `_, close file handle @@ -101,8 +98,7 @@ Updated 0.3.3 - 07.05.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. issue `pyexcel#19 `_, not all texts in a multi-node cell were extracted. @@ -110,8 +106,7 @@ Updated 0.3.2 - 13.04.2017 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. issue `pyexcel#17 `_, empty new line is ignored @@ -121,24 +116,21 @@ Updated 0.3.1 - 02.02.2017 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. Recognize currency type 0.3.0 - 22.12.2016 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Code refactoring with pyexcel-io v 0.3.0 0.2.2 - 24.10.2016 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. issue `pyexcel#14 `_, index error when reading a ods file that has non-uniform columns repeated property. @@ -146,8 +138,7 @@ Updated 0.2.1 - 31.08.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. support pagination. two pairs: start_row, row_limit and start_column, column_limit help you deal with large files. @@ -156,24 +147,21 @@ Added 0.2.0 - 01.06.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. By default, `float` will be converted to `int` where fits. `auto_detect_int`, a flag to switch off the autoatic conversion from `float` to `int`. #. 'library=pyexcel-ods' was added so as to inform pyexcel to use it instead of other libraries, in the situation where multiple plugins were installed. -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. support the auto-import feature of pyexcel-io 0.2.0 0.1.1 - 30.01.2016 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. 'streaming' is an extra option given to get_data. Only when 'streaming' is explicitly set to True, the data will be consisted of generators, hence will @@ -182,64 +170,56 @@ Added #. support multi-line text cell #5 #. feature migration from pyexcel-ods3 pyexcel/pyexcel-ods3#5 -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. compatibility with pyexcel-io 0.1.1 0.0.12 - 10.10.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Bug fix: excessive trailing columns with empty values 0.0.11 - 26.09.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Complete fix for libreoffice datetime field 0.0.10 - 15.09.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Bug fix: date field could have datetime from libreoffice 0.0.9 - 21.08.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Bug fix: utf-8 string throw unicode exceptions 0.0.8 - 28.06.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Pin dependency odfpy 0.9.6 to avoid buggy odfpy 1.3.0 0.0.7 - 28.05.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. Bug fix: "number-columns-repeated" is now respected 0.0.6 - 21.05.2015 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. get_data and save_data are seen across pyexcel-* extensions. remember them once and use them across all extensions. @@ -247,8 +227,7 @@ Updated 0.0.5 - 22.02.2015 -------------------------------------------------------------------------------- -Added -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Added** #. Loads only one sheet from a multiple sheet book #. Use New BSD License @@ -256,8 +235,7 @@ Added 0.0.4 - 14.12.2014 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. IO interface update as pyexcel-io introduced keywords. #. initial release @@ -265,8 +243,7 @@ Updated 0.0.3 - 08.12.2014 -------------------------------------------------------------------------------- -Updated -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Updated** #. IO interface update as pyexcel-io introduced keywords. #. initial release diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst new file mode 100644 index 0000000..ccdfc96 --- /dev/null +++ b/CONTRIBUTORS.rst @@ -0,0 +1,10 @@ + + +3 contributors +================================================================================ + +In alphabetical order: + +* `Azamat H. Hackimov `_ +* `John Vandenberg `_ +* `Mateusz Konieczny `_ diff --git a/LICENSE b/LICENSE index 0f53832..a0a4488 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 @@ -13,7 +13,7 @@ that the following conditions are met: and/or other materials provided with the distribution. * Neither the name of 'pyexcel-ods' nor the names of the contributors - may be used to endorse or promote products derived from this software + may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND diff --git a/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/Makefile b/Makefile index d3587b4..3e0ee51 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,16 @@ all: test -test: +test: lint bash test.sh -format: - isort -y $(find pyexcel_ods -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) - black -l 79 pyexcel_ods - black -l 79 tests +install_test: + pip install -r tests/requirements.txt lint: bash lint.sh + +format: + bash format.sh + +git-diff-check: + git diff --exit-code diff --git a/README.rst b/README.rst index 5c9bfc8..abbced9 100644 --- a/README.rst +++ b/README.rst @@ -3,10 +3,10 @@ pyexcel-ods - Let you focus on data, instead of ods format ================================================================================ .. image:: https://raw.githubusercontent.com/pyexcel/pyexcel.github.io/master/images/patreon.png - :target: https://www.patreon.com/pyexcel + :target: https://www.patreon.com/chfw -.. image:: https://api.bountysource.com/badge/team?team_id=288537 - :target: https://salt.bountysource.com/teams/chfw-pyexcel +.. image:: https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg + :target: https://awesome-python.com/#specific-formats-processing .. image:: https://travis-ci.org/pyexcel/pyexcel-ods.svg?branch=master :target: http://travis-ci.org/pyexcel/pyexcel-ods @@ -14,9 +14,22 @@ pyexcel-ods - Let you focus on data, instead of ods format .. image:: https://codecov.io/gh/pyexcel/pyexcel-ods/branch/master/graph/badge.svg :target: https://codecov.io/gh/pyexcel/pyexcel-ods +.. image:: https://badge.fury.io/py/pyexcel-ods.svg + :target: https://pypi.org/project/pyexcel-ods + + +.. image:: https://pepy.tech/badge/pyexcel-ods/month + :target: https://pepy.tech/project/pyexcel-ods/month + + .. image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg :target: https://gitter.im/pyexcel/Lobby +.. image:: https://img.shields.io/static/v1?label=continuous%20templating&message=%E6%A8%A1%E7%89%88%E6%9B%B4%E6%96%B0&color=blue&style=flat-square + :target: https://moban.readthedocs.io/en/latest/#at-scale-continous-templating-for-open-source-projects + +.. image:: https://img.shields.io/static/v1?label=coding%20style&message=black&color=black&style=flat-square + :target: https://github.com/psf/black **pyexcel-ods** is a tiny wrapper library to read, manipulate and write data in ods format using python 2.6 and python 2.7. You are likely to use it with @@ -25,6 +38,24 @@ ods format using python 2.6 and python 2.7. You are likely to use it with depends on ezodf and lxml. `pyexcel-odsr `_ is the other sister library that has no external dependency but do ods reading only +Support the project +================================================================================ + +If your company has embedded pyexcel and its components into a revenue generating +product, please support me on github, `patreon `_ +or `bounty source `_ to maintain +the project and develop it further. + +If you are an individual, you are welcome to support me too and for however long +you feel like. As my backer, you will receive +`early access to pyexcel related contents `_. + +And your issues will get prioritized if you would like to become my patreon as `pyexcel pro user`. + +With your financial support, I will be able to invest +a little bit more time in coding, documentation and writing interesting posts. + + Known constraints ================== @@ -49,24 +80,6 @@ or clone it and install it: $ cd pyexcel-ods $ python setup.py install -Support the project -================================================================================ - -If your company has embedded pyexcel and its components into a revenue generating -product, please support me on `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 ================================================================================ @@ -348,37 +361,16 @@ On Windows systems, please issue this command:: > test.bat -How to update test environment and update documentation ---------------------------------------------------------- - -Additional steps are required: - -#. pip install moban -#. git clone https://github.com/moremoban/setupmobans.git # generic setup -#. git clone https://github.com/pyexcel/pyexcel-commons.git commons -#. make your changes in `.moban.d` directory, then issue command `moban` -What is pyexcel-commons ---------------------------------- - -Many information that are shared across pyexcel projects, such as: this developer guide, license info, etc. are stored in `pyexcel-commons` project. +Before you commit +------------------------------ -What is .moban.d ---------------------------------- +Please run:: -`.moban.d` stores the specific meta data for the library. + $ make format -Acceptance criteria -------------------- +so as to beautify your code otherwise travis-ci may fail your unit test. -#. Has Test cases written -#. Has all code lines tested -#. Passes all Travis CI builds -#. Has fair amount of documentation if your change is complex -#. run 'make format' so as to confirm the pyexcel organisation's coding style -#. Please update CHANGELOG.rst -#. Please add yourself to CONTRIBUTORS.rst -#. Agree on NEW BSD License for your contribution Credits ================================================================================ diff --git a/changelog.yml b/changelog.yml index d15f3f6..1692c01 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-ods organisation: pyexcel releases: +- changes: + - action: added + details: + - 'new style reader and writer plugins. works with pyexcel-io v0.6.2' + date: 9.10.2020 + version: 0.6.0 - changes: - action: added details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 9603cb6..5a459b0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -7,7 +7,7 @@ # # This file only contains a selection of the most common options. For a full # list see the documentation: -# http://www.sphinx-doc.org/en/master/config +# https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- @@ -21,13 +21,13 @@ # -- Project information ----------------------------------------------------- -project = 'pyexcel' -copyright = 'copyright 2015-2019 Onni Software Ltd.' -author = 'Onni Software Ltd.' +project = 'pyexcel-ods' +copyright = '2015-2020 Onni Software Ltd.' +author = 'chfw' # The short X.Y version -version = '0.5.6' +version = '0.6.0' # The full version, including alpha/beta/rc tags -release = '0.5.6' +release = '0.6.0' # -- General configuration --------------------------------------------------- @@ -68,7 +68,7 @@ # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {'https://docs.python.org/3/': None} # TODO: html_theme not configurable upstream html_theme = 'default' @@ -83,3 +83,4 @@ intersphinx_mapping.update({ 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), }) +master_doc = "index" diff --git a/format.sh b/format.sh new file mode 100644 index 0000000..3a0ecb9 --- /dev/null +++ b/format.sh @@ -0,0 +1,3 @@ +isort $(find pyexcel_ods -name "*.py"|xargs echo) $(find tests -name "*.py"|xargs echo) +black -l 79 pyexcel_ods +black -l 79 tests diff --git a/lint.sh b/lint.sh index 12183c3..891aa63 100644 --- a/lint.sh +++ b/lint.sh @@ -1 +1,2 @@ -flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long \ No newline at end of file +pip install flake8 +flake8 --exclude=.moban.d,docs,setup.py --builtins=unicode,xrange,long . && python setup.py checkdocs diff --git a/pyexcel-ods.yml b/pyexcel-ods.yml index 1201ffe..5eefaa6 100644 --- a/pyexcel-ods.yml +++ b/pyexcel-ods.yml @@ -1,12 +1,18 @@ overrides: "pyexcel.yaml" name: "pyexcel-ods" nick_name: ods -version: 0.5.6 -current_version: 0.5.6 -release: 0.5.6 -copyright_year: 2015-2019 +version: 0.6.0 +current_version: 0.6.0 +release: 0.6.0 +copyright_year: 2015-2020 file_type: ods dependencies: - - pyexcel-io>=0.5.16 + - pyexcel-io>=0.6.2 - odfpy>=1.3.5 +test_dependencies: + - pyexcel + - psutil + - pyexcel-xls description: A wrapper library to read, manipulate and write data in ods format +python_requires: ">=3.6" +min_python_version: "3.6" diff --git a/pyexcel_ods/__init__.py b/pyexcel_ods/__init__.py index 60fd4f2..63b02a0 100644 --- a/pyexcel_ods/__init__.py +++ b/pyexcel_ods/__init__.py @@ -2,7 +2,7 @@ pyexcel_ods ~~~~~~~~~~~~~~~~~~~ The lower level ods file format handler using odfpy - :copyright: (c) 2015-2017 by Onni Software Ltd & its contributors + :copyright: (c) 2015-2020 by Onni Software Ltd & its contributors :license: New BSD License """ @@ -13,15 +13,23 @@ # this line has to be place above all else # because of dynamic import -from pyexcel_io.plugins import IOPluginInfoChain +from pyexcel_io.plugins import IOPluginInfoChain, IOPluginInfoChainV2 __FILE_TYPE__ = "ods" -IOPluginInfoChain(__name__).add_a_reader( +IOPluginInfoChain(__name__) +IOPluginInfoChainV2(__name__).add_a_reader( relative_plugin_class_path="odsr.ODSBook", + locations=["file", "memory"], + file_types=[__FILE_TYPE__], + stream_type="binary", +).add_a_reader( + relative_plugin_class_path="odsr.ODSBookInContent", + locations=["content"], file_types=[__FILE_TYPE__], stream_type="binary", ).add_a_writer( relative_plugin_class_path="odsw.ODSWriter", + locations=["file", "memory"], file_types=[__FILE_TYPE__], stream_type="binary", ) diff --git a/pyexcel_ods/odsr.py b/pyexcel_ods/odsr.py index 3af37fe..178fd4d 100644 --- a/pyexcel_ods/odsr.py +++ b/pyexcel_ods/odsr.py @@ -4,7 +4,7 @@ ods reader - :copyright: (c) 2014-2017 by Onni Software Ltd. + :copyright: (c) 2014-2020 by Onni Software Ltd. :license: New BSD License, see LICENSE for more details """ # Copyright 2011 Marco Conti @@ -20,26 +20,25 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from io import BytesIO import pyexcel_io.service as service -from pyexcel_io._compact import OrderedDict -from pyexcel_io.book import BookReader -from pyexcel_io.sheet import SheetReader - -from odf.namespaces import OFFICENS -from odf.opendocument import load -from odf.table import Table, TableCell, TableRow +from odf.text import P +from odf.table import Table, TableRow, TableCell # Thanks to grt for the fixes from odf.teletype import extractText -from odf.text import P +from odf.namespaces import OFFICENS +from odf.opendocument import load +from pyexcel_io.plugin_api import ISheet, IReader, NamedContent -class ODSSheet(SheetReader): +class ODSSheet(ISheet): """native ods sheet""" def __init__(self, sheet, auto_detect_int=True, **keywords): - SheetReader.__init__(self, sheet, **keywords) + self._native_sheet = sheet + self._keywords = keywords self.__auto_detect_int = auto_detect_int @property @@ -100,62 +99,32 @@ def __read_text_cell(self, cell): return "\n".join(text_content) -class ODSBook(BookReader): +class ODSBook(IReader): """read ods book""" - def open(self, file_name, **keywords): - """open ods file""" - BookReader.open(self, file_name, **keywords) - self._load_from_file() - - def open_stream(self, file_stream, **keywords): - """open ods file stream""" - BookReader.open_stream(self, file_stream, **keywords) - self._load_from_memory() - - def read_sheet_by_name(self, sheet_name): - """read a named sheet""" - tables = self._native_book.spreadsheet.getElementsByType(Table) - rets = [ - table - for table in tables - if table.getAttribute("name") == sheet_name + def __init__(self, file_alike_object, _, **keywords): + self._native_book = load(file_alike_object) + self._keywords = keywords + self.content_array = [ + NamedContent(table.getAttribute("name"), table) + for table in self._native_book.spreadsheet.getElementsByType(Table) ] - if len(rets) == 0: - raise ValueError("%s cannot be found" % sheet_name) - else: - return self.read_sheet(rets[0]) - def read_sheet_by_index(self, sheet_index): + def read_sheet(self, sheet_index): """read a sheet at a specified index""" - tables = self._native_book.spreadsheet.getElementsByType(Table) - length = len(tables) - if sheet_index < length: - return self.read_sheet(tables[sheet_index]) - else: - raise IndexError( - "Index %d of out bound %d" % (sheet_index, length) - ) - - def read_all(self): - """read all sheets""" - result = OrderedDict() - for sheet in self._native_book.spreadsheet.getElementsByType(Table): - ods_sheet = ODSSheet(sheet, **self._keywords) - result[ods_sheet.name] = ods_sheet.to_array() - - return result - - def read_sheet(self, native_sheet): - """read one native sheet""" - sheet = ODSSheet(native_sheet, **self._keywords) - return {sheet.name: sheet.to_array()} + table = self.content_array[sheet_index].payload + sheet = ODSSheet(table, **self._keywords) + return sheet def close(self): self._native_book = None - def _load_from_memory(self): - self._native_book = load(self._file_stream) - def _load_from_file(self): - self._native_book = load(self._file_name) +class ODSBookInContent(ODSBook): + """ + Open xlsx as read only mode + """ + + def __init__(self, file_content, file_type, **keywords): + io = BytesIO(file_content) + super().__init__(io, file_type, **keywords) diff --git a/pyexcel_ods/odsw.py b/pyexcel_ods/odsw.py index 3f1bdd3..1cb9762 100644 --- a/pyexcel_ods/odsw.py +++ b/pyexcel_ods/odsw.py @@ -4,37 +4,25 @@ ods writer - :copyright: (c) 2014-2017 by Onni Software Ltd. + :copyright: (c) 2014-2020 by Onni Software Ltd. :license: New BSD License, see LICENSE for more details """ -import sys - import pyexcel_io.service as converter -from pyexcel_io.book import BookWriter -from pyexcel_io.sheet import SheetWriter - +from odf.text import P +from odf.table import Table, TableRow, TableCell from odf.namespaces import OFFICENS from odf.opendocument import OpenDocumentSpreadsheet -from odf.table import Table, TableCell, TableRow -from odf.text import P +from pyexcel_io.plugin_api import IWriter, ISheetWriter -PY2 = sys.version_info[0] == 2 -PY27_BELOW = PY2 and sys.version_info[1] < 7 - - -class ODSSheetWriter(SheetWriter): +class ODSSheetWriter(ISheetWriter): """ ODS sheet writer """ - def set_sheet_name(self, name): - """initialize the native table""" - self._native_sheet = Table(name=name) - - def set_size(self, size): - """not used in this class but used in ods3""" - pass + def __init__(self, ods_book, sheet_name): + self._native_book = ods_book + self._native_sheet = Table(name=sheet_name) def write_cell(self, row, cell): """write a native cell""" @@ -78,26 +66,26 @@ def close(self): self._native_book.spreadsheet.addElement(self._native_sheet) -class ODSWriter(BookWriter): +class ODSWriter(IWriter): """ open document spreadsheet writer """ - def __init__(self): - BookWriter.__init__(self) + def __init__(self, file_alike_object, file_type, **_): + self.file_alike_object = file_alike_object self._native_book = OpenDocumentSpreadsheet() def create_sheet(self, name): """ write a row into the file """ - return ODSSheetWriter(self._native_book, None, name) + return ODSSheetWriter(self._native_book, name) def close(self): """ This call writes file """ - self._native_book.write(self._file_alike_object) + self._native_book.write(self.file_alike_object) self._native_book = None diff --git a/requirements.txt b/requirements.txt index a6599ba..10c1e1d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyexcel-io>=0.5.16 +pyexcel-io>=0.6.2 odfpy>=1.3.5 diff --git a/rnd_requirements.txt b/rnd_requirements.txt new file mode 100644 index 0000000..a4748b0 --- /dev/null +++ b/rnd_requirements.txt @@ -0,0 +1 @@ +https://github.com/pyexcel/pyexcel-io/archive/dev.zip diff --git a/setup.py b/setup.py index 42a26c3..e4a3e42 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,18 @@ #!/usr/bin/env python3 +""" +Template by pypi-mobans +""" + +import os +import sys import codecs import locale -# Template by pypi-mobans -import os import platform -import sys from shutil import rmtree -from setuptools import Command, find_packages, setup +from setuptools import Command, setup, find_packages + # Work around mbcs bug in distutils. # http://bugs.python.org/issue10945 @@ -18,55 +22,58 @@ try: lc = locale.getlocale() pf = platform.system() - if pf != 'Windows' and lc == (None, None): - locale.setlocale(locale.LC_ALL, 'C.UTF-8') + if pf != "Windows" and lc == (None, None): + locale.setlocale(locale.LC_ALL, "C.UTF-8") except (ValueError, UnicodeError, locale.Error): - locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') + locale.setlocale(locale.LC_ALL, "en_US.UTF-8") -NAME = 'pyexcel-ods' -AUTHOR = 'C.W.' -VERSION = '0.5.6' -EMAIL = 'wangc_2011@hotmail.com' -LICENSE = 'New BSD' +NAME = "pyexcel-ods" +AUTHOR = "chfw" +VERSION = "0.6.0" +EMAIL = "info@pyexcel.org" +LICENSE = "New BSD" DESCRIPTION = ( - 'A wrapper library to read, manipulate and write data in ods format' + "A wrapper library to read, manipulate and write data in ods format" ) -URL = 'https://github.com/pyexcel/pyexcel-ods' -DOWNLOAD_URL = '%s/archive/0.5.6.tar.gz' % URL -FILES = ['README.rst', 'CHANGELOG.rst'] +URL = "https://github.com/pyexcel/pyexcel-ods" +DOWNLOAD_URL = "%s/archive/0.6.0.tar.gz" % URL +FILES = ["README.rst", "CHANGELOG.rst"] KEYWORDS = [ - 'python', + "python", ] CLASSIFIERS = [ - 'Topic :: Software Development :: Libraries', - 'Programming Language :: Python', - 'Intended Audience :: Developers', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', + "Topic :: Software Development :: Libraries", + "Programming Language :: Python", + "Intended Audience :: Developers", + + "Programming Language :: Python :: 3 :: Only", + + + + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + ] +PYTHON_REQUIRES = ">=3.6" + INSTALL_REQUIRES = [ - 'pyexcel-io>=0.5.16', - 'odfpy>=1.3.5', + "pyexcel-io>=0.6.2", + "odfpy>=1.3.5", ] SETUP_COMMANDS = {} - -PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests']) +PACKAGES = find_packages(exclude=["ez_setup", "examples", "tests", "tests.*"]) EXTRAS_REQUIRE = { } # You do not need to read beyond this line -PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format( - sys.executable) -GS_COMMAND = ('gs pyexcel-ods v0.5.6 ' + - "Find 0.5.6 in changelog for more details") -NO_GS_MESSAGE = ('Automatic github release is disabled. ' + - 'Please install gease to enable it.') +PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable) +GS_COMMAND = ("gs pyexcel-ods v0.6.0 " + + "Find 0.6.0 in changelog for more details") +NO_GS_MESSAGE = ("Automatic github release is disabled. " + + "Please install gease to enable it.") UPLOAD_FAILED_MSG = ( 'Upload failed. please run "%s" yourself.' % PUBLISH_COMMAND) HERE = os.path.abspath(os.path.dirname(__file__)) @@ -75,13 +82,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 @@ -91,14 +98,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_ods.egg-info')) + self.status("Removing previous builds...") + rmtree(os.path.join(HERE, "dist")) + rmtree(os.path.join(HERE, "build")) + rmtree(os.path.join(HERE, "pyexcel_ods.egg-info")) except OSError: pass - self.status('Building Source and Wheel (universal) distribution...') + self.status("Building Source and Wheel (universal) distribution...") run_status = True if has_gease(): run_status = os.system(GS_COMMAND) == 0 @@ -106,13 +113,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 }) @@ -141,7 +148,7 @@ def read_files(*files): def read(afile): """Read a file into setup""" the_relative_file = os.path.join(HERE, afile) - with codecs.open(the_relative_file, 'r', 'utf-8') as opened_file: + with codecs.open(the_relative_file, "r", "utf-8") as opened_file: content = filter_out_test_code(opened_file) content = "".join(list(content)) return content @@ -150,11 +157,11 @@ def read(afile): def filter_out_test_code(file_handle): found_test_code = False for line in file_handle.readlines(): - if line.startswith('.. testcode:'): + if line.startswith(".. testcode:"): found_test_code = True continue if found_test_code is True: - if line.startswith(' '): + if line.startswith(" "): continue else: empty_line = line.strip() @@ -164,14 +171,14 @@ def filter_out_test_code(file_handle): found_test_code = False yield line else: - for keyword in ['|version|', '|today|']: + for keyword in ["|version|", "|today|"]: if keyword in line: break else: yield line -if __name__ == '__main__': +if __name__ == "__main__": setup( test_suite="tests", name=NAME, @@ -184,8 +191,9 @@ def filter_out_test_code(file_handle): long_description=read_files(*FILES), license=LICENSE, keywords=KEYWORDS, + python_requires=PYTHON_REQUIRES, extras_require=EXTRAS_REQUIRE, - tests_require=['nose'], + tests_require=["nose"], install_requires=INSTALL_REQUIRES, packages=PACKAGES, include_package_data=True, diff --git a/test.sh b/test.sh index ecba1ba..dacfc93 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,3 @@ +#/bin/bash pip freeze nosetests --with-coverage --cover-package pyexcel_ods --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_ods diff --git a/tests/base.py b/tests/base.py index c312a6a..3d40097 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,7 +1,8 @@ -import datetime # noqa import os # noqa +import datetime # noqa import pyexcel + from nose.tools import eq_, raises # noqa diff --git a/tests/requirements.txt b/tests/requirements.txt index 7a755ef..ae03e89 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,9 +3,12 @@ mock;python_version<"3" codecov coverage flake8 +black +isort +collective.checkdocs +pygments moban -black;python_version>="3.6" -isort;python_version>="3.6" -psutil +moban_jinja2_github pyexcel +psutil pyexcel-xls diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 128934a..c644529 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -4,11 +4,11 @@ import psutil import pyexcel as pe -from nose import SkipTest -from nose.tools import eq_, raises +from pyexcel_ods import get_data, save_data from pyexcel_io.exceptions import IntegerAccuracyLossError -from pyexcel_ods import get_data, save_data +from nose import SkipTest +from nose.tools import eq_, raises IN_TRAVIS = "TRAVIS" in os.environ diff --git a/tests/test_filter.py b/tests/test_filter.py index 67d8876..029e04b 100644 --- a/tests/test_filter.py +++ b/tests/test_filter.py @@ -1,8 +1,9 @@ import os -from nose.tools import eq_ from pyexcel_io import get_data, save_data +from nose.tools import eq_ + class TestFilter: def setUp(self): diff --git a/tests/test_formatters.py b/tests/test_formatters.py index ba78ec2..ae1e6e8 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -2,6 +2,7 @@ from textwrap import dedent import pyexcel as pe + from nose.tools import eq_ diff --git a/tests/test_multiple_sheets.py b/tests/test_multiple_sheets.py index 6360be6..f82b212 100644 --- a/tests/test_multiple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -2,10 +2,10 @@ import sys import pyexcel -from nose.tools import raises - from base import PyexcelMultipleSheetBase +from nose.tools import raises + if sys.version_info[0] == 2 and sys.version_info[1] < 7: from ordereddict import OrderedDict else: diff --git a/tests/test_ods_reader.py b/tests/test_ods_reader.py index 69bb030..f236bf5 100644 --- a/tests/test_ods_reader.py +++ b/tests/test_ods_reader.py @@ -3,11 +3,13 @@ from base import ODSCellTypes from pyexcel_ods.odsr import ODSBook from pyexcel_ods.odsw import ODSWriter +from pyexcel_io.reader import Reader class TestODSReader(ODSCellTypes): def setUp(self): - r = ODSBook() + r = Reader("ods") + r.reader_class = ODSBook r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) self.data = r.read_all() for key in self.data.keys(): @@ -17,17 +19,17 @@ def setUp(self): class TestODSWriter(ODSCellTypes): def setUp(self): - r = ODSBook() + r = Reader("ods") + r.reader_class = ODSBook r.open(os.path.join("tests", "fixtures", "ods_formats.ods")) + r.close() self.data1 = r.read_all() self.testfile = "odswriter.ods" - w = ODSWriter() - w.open(self.testfile) + w = ODSWriter(self.testfile, "ods") w.write(self.data1) w.close() - r2 = ODSBook() - r2.open(self.testfile) - self.data = r2.read_all() + r.open(self.testfile) + self.data = r.read_all() for key in self.data.keys(): self.data[key] = list(self.data[key]) diff --git a/tests/test_stringio.py b/tests/test_stringio.py index 442a464..45e0ec8 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -1,10 +1,10 @@ import os import pyexcel -from nose.tools import eq_ - from base import create_sample_file1 +from nose.tools import eq_ + class TestStringIO: def test_ods_stringio(self): diff --git a/tests/test_writer.py b/tests/test_writer.py index ab5a976..1402ce5 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -1,7 +1,7 @@ import os -from base import PyexcelHatWriterBase, PyexcelWriterBase -from pyexcel_ods.odsr import ODSBook as Reader +from base import PyexcelWriterBase, PyexcelHatWriterBase +from pyexcel_io import get_data from pyexcel_ods.odsw import ODSWriter as Writer @@ -13,17 +13,11 @@ def test_write_book(self): "Sheet3": [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]], } self.testfile = "writer.ods" - writer = Writer() - writer.open(self.testfile) + writer = Writer(self.testfile, "ods") writer.write(self.content) writer.close() - reader = Reader() - reader.open(self.testfile) - content = reader.read_all() - for key in content.keys(): - content[key] = list(content[key]) + content = get_data(self.testfile, library="pyexcel-ods") assert content == self.content - reader.close() def tearDown(self): if os.path.exists(self.testfile):