mirror of
https://github.com/kennethreitz/tablib.git
synced 2026-06-05 15:00:19 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8f54811c7 | |||
| e8774043ed | |||
| dc1729fc6f | |||
| 3dc62685f8 | |||
| 22c88de90d | |||
| 615e308559 | |||
| 8c5404591b | |||
| 5fa4496f9d | |||
| bc8438bda4 | |||
| ce79e44d14 |
@@ -2,23 +2,39 @@ name: Docs and lint
|
|||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
FORCE_COLOR: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.8]
|
|
||||||
env:
|
env:
|
||||||
- TOXENV: docs
|
- TOXENV: docs
|
||||||
- TOXENV: lint
|
- TOXENV: lint
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: 3.9
|
||||||
|
|
||||||
|
- name: Get pip cache dir
|
||||||
|
id: pip-cache
|
||||||
|
run: |
|
||||||
|
echo "::set-output name=dir::$(pip cache dir)"
|
||||||
|
|
||||||
|
- name: Cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ steps.pip-cache.outputs.dir }}
|
||||||
|
key:
|
||||||
|
${{ matrix.os }}-${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.py') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ matrix.os }}-${{ matrix.python-version }}-v1-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
if: github.repository == 'jazzband/tablib'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.8
|
||||||
|
|
||||||
|
- name: Get pip cache dir
|
||||||
|
id: pip-cache
|
||||||
|
run: |
|
||||||
|
echo "::set-output name=dir::$(pip cache dir)"
|
||||||
|
|
||||||
|
- name: Cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ steps.pip-cache.outputs.dir }}
|
||||||
|
key: release-${{ hashFiles('**/setup.py') }}
|
||||||
|
restore-keys: |
|
||||||
|
release-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install -U pip
|
||||||
|
python -m pip install -U setuptools twine wheel
|
||||||
|
|
||||||
|
- name: Build package
|
||||||
|
run: |
|
||||||
|
python setup.py --version
|
||||||
|
python setup.py sdist --format=gztar bdist_wheel
|
||||||
|
twine check dist/*
|
||||||
|
|
||||||
|
- name: Upload packages to Jazzband
|
||||||
|
if: github.event.action == 'published'
|
||||||
|
uses: pypa/gh-action-pypi-publish@master
|
||||||
|
with:
|
||||||
|
user: jazzband
|
||||||
|
password: ${{ secrets.JAZZBAND_RELEASE_KEY }}
|
||||||
|
repository_url: https://jazzband.co/projects/tablib/upload
|
||||||
@@ -2,24 +2,40 @@ name: Test
|
|||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
FORCE_COLOR: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.5, 3.6, 3.7, 3.8]
|
python-version: [3.6, 3.7, 3.8, 3.9]
|
||||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
- name: Get pip cache dir
|
||||||
|
id: pip-cache
|
||||||
|
run: |
|
||||||
|
echo "::set-output name=dir::$(pip cache dir)"
|
||||||
|
|
||||||
|
- name: Cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ steps.pip-cache.outputs.dir }}
|
||||||
|
key:
|
||||||
|
${{ matrix.os }}-${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.py') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ matrix.os }}-${{ matrix.python-version }}-v1-
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
@@ -30,3 +46,8 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
tox -e py
|
tox -e py
|
||||||
|
|
||||||
|
- name: Upload coverage
|
||||||
|
uses: codecov/codecov-action@v1
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.os }} Python ${{ matrix.python-version }}
|
||||||
|
|||||||
@@ -38,3 +38,6 @@ htmlcov
|
|||||||
# setuptools noise
|
# setuptools noise
|
||||||
.eggs
|
.eggs
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
|
||||||
|
# generated by setuptools-scm
|
||||||
|
/src/tablib/_version.py
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v1.26.2
|
rev: v2.7.3
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: ["--py3-plus"]
|
args: ["--py36-plus"]
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-isort
|
- repo: https://github.com/PyCQA/isort
|
||||||
rev: v4.3.21
|
rev: 5.6.4
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
additional_dependencies: [toml]
|
additional_dependencies: [toml]
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||||
rev: v1.4.4
|
rev: v1.7.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: python-check-blanket-noqa
|
- id: python-check-blanket-noqa
|
||||||
- id: rst-backticks
|
- id: rst-backticks
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v2.4.0
|
rev: v3.3.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-merge-conflict
|
- id: check-merge-conflict
|
||||||
- id: check-toml
|
- id: check-toml
|
||||||
|
|||||||
-38
@@ -1,38 +0,0 @@
|
|||||||
language: python
|
|
||||||
cache:
|
|
||||||
pip: true
|
|
||||||
directories:
|
|
||||||
- $HOME/.cache/pre-commit
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
include:
|
|
||||||
- python: 3.8
|
|
||||||
env: TOXENV=docs
|
|
||||||
- python: 3.8
|
|
||||||
env: TOXENV=lint
|
|
||||||
- python: 3.8
|
|
||||||
- python: 3.7
|
|
||||||
- python: 3.6
|
|
||||||
|
|
||||||
install: travis_retry pip install tox-travis
|
|
||||||
|
|
||||||
script: tox
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- |
|
|
||||||
if [[ "$TOXENV" != "docs" && "$TOXENV" != "lint" ]]; then
|
|
||||||
bash <(curl -s https://codecov.io/bash)
|
|
||||||
fi
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
provider: pypi
|
|
||||||
user: jazzband
|
|
||||||
server: https://jazzband.co/projects/tablib/upload
|
|
||||||
distributions: sdist bdist_wheel
|
|
||||||
password:
|
|
||||||
secure: svV4fYtodwW+iTyFOm5ISEfhVwcA+6vTskD3x6peznc40TdMV9Ek8nT3Q/NB4lCbXoUw2qR4H6uhLCjesnv/VvVk/qbitCyD8ySlgwOV5n7NzJs8lC8EYaHSjGQjatTwJAokfGVYkPawkI7HXDqtDggLUQBK+Ag8HDW+XBSbQIU=
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
repo: jazzband/tablib
|
|
||||||
python: 3.7
|
|
||||||
+15
@@ -1,5 +1,20 @@
|
|||||||
# History
|
# History
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
- Dropped Python 3.5 support
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
- Added Python 3.9 support
|
||||||
|
- Added read_only option to xlsx file reader (#482).
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- Prevented crash in rst export with only-space strings (#469).
|
||||||
|
|
||||||
## 2.0.0 (2020-05-16)
|
## 2.0.0 (2020-05-16)
|
||||||
|
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
[](https://pypi.org/project/tablib/)
|
[](https://pypi.org/project/tablib/)
|
||||||
[](https://pypi.org/project/tablib/)
|
[](https://pypi.org/project/tablib/)
|
||||||
[](https://pypistats.org/packages/tablib)
|
[](https://pypistats.org/packages/tablib)
|
||||||
[](https://travis-ci.org/jazzband/tablib)
|
|
||||||
[](https://github.com/jazzband/tablib/actions)
|
[](https://github.com/jazzband/tablib/actions)
|
||||||
[](https://codecov.io/gh/jazzband/tablib)
|
[](https://codecov.io/gh/jazzband/tablib)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|||||||
+3
-3
@@ -3,9 +3,9 @@
|
|||||||
Jazzband guidelines: https://jazzband.co/about/releases
|
Jazzband guidelines: https://jazzband.co/about/releases
|
||||||
|
|
||||||
* [ ] Get master to the appropriate code release state.
|
* [ ] Get master to the appropriate code release state.
|
||||||
[Travis CI](https://travis-ci.org/jazzband/tablib)
|
[GitHub Actions](https://github.com/jazzband/tablib/actions)
|
||||||
should pass on master.
|
should pass on master.
|
||||||
[](https://travis-ci.org/jazzband/tablib)
|
[](https://github.com/jazzband/tablib/actions)
|
||||||
|
|
||||||
* [ ] Check [HISTORY.md](https://github.com/jazzband/tablib/blob/master/HISTORY.md),
|
* [ ] Check [HISTORY.md](https://github.com/jazzband/tablib/blob/master/HISTORY.md),
|
||||||
update version number and release date
|
update version number and release date
|
||||||
@@ -16,7 +16,7 @@ git tag -a v0.14.0 -m v0.14.0
|
|||||||
git push --tags
|
git push --tags
|
||||||
```
|
```
|
||||||
|
|
||||||
* [ ] Once Travis CI has built and uploaded distributions, check files at
|
* [ ] Once GitHub Actions has built and uploaded distributions, check files at
|
||||||
[Jazzband](https://jazzband.co/projects/tablib) and release to
|
[Jazzband](https://jazzband.co/projects/tablib) and release to
|
||||||
[PyPI](https://pypi.org/pypi/tablib)
|
[PyPI](https://pypi.org/pypi/tablib)
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
@@ -8,4 +8,5 @@
|
|||||||
<li><a href="https://pypi.org/project/tablib">Tablib @ PyPI</a></li>
|
<li><a href="https://pypi.org/project/tablib">Tablib @ PyPI</a></li>
|
||||||
<li><a href="https://github.com/jazzband/tablib">Tablib @ GitHub</a></li>
|
<li><a href="https://github.com/jazzband/tablib">Tablib @ GitHub</a></li>
|
||||||
<li><a href="https://github.com/jazzband/tablib/issues">Issue Tracker</a></li>
|
<li><a href="https://github.com/jazzband/tablib/issues">Issue Tracker</a></li>
|
||||||
|
<li><a href="https://github.com/jazzband/tablib/blob/master/HISTORY.md">Changelog</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
+3
-3
@@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
# All configuration values have a default; values that are commented out
|
# All configuration values have a default; values that are commented out
|
||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
from pkg_resources import get_distribution
|
import tablib
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
@@ -49,9 +49,9 @@ copyright = '2019 Jazzband'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = get_distribution('tablib').version
|
release = tablib.__version__
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '.'.join(release.split('.')[:2])
|
version = '.'.join(tablib.__version__.split('.')[:2])
|
||||||
# for example take major/minor
|
# for example take major/minor
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
|||||||
@@ -163,16 +163,16 @@ the easiest way to test your changes for potential issues is to simply run the t
|
|||||||
Continuous Integration
|
Continuous Integration
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Every pull request is automatically tested and inspected upon receipt with `Travis CI`_.
|
Every pull request is automatically tested and inspected upon receipt with `GitHub Actions`_.
|
||||||
If you broke the build, you will receive an email accordingly.
|
If you broke the build, you will receive an email accordingly.
|
||||||
|
|
||||||
Anyone may view the build status and history at any time.
|
Anyone may view the build status and history at any time.
|
||||||
|
|
||||||
https://travis-ci.org/jazzband/tablib
|
https://github.com/jazzband/tablib/actions
|
||||||
|
|
||||||
Additional reports will also be included here in the future, including :pep:`8` checks and stress reports for extremely large datasets.
|
Additional reports will also be included here in the future, including :pep:`8` checks and stress reports for extremely large datasets.
|
||||||
|
|
||||||
.. _`Travis CI`: https://travis-ci.org/
|
.. _`GitHub Actions`: https://github.com/jazzband/tablib/actions
|
||||||
|
|
||||||
|
|
||||||
.. _docs:
|
.. _docs:
|
||||||
|
|||||||
+16
-7
@@ -27,7 +27,7 @@ For example::
|
|||||||
dataset.export("cli", tablefmt="github")
|
dataset.export("cli", tablefmt="github")
|
||||||
dataset.export("cli", tablefmt="grid")
|
dataset.export("cli", tablefmt="grid")
|
||||||
|
|
||||||
This format is optional, install Tablib with ``pip install tablib[cli]`` to
|
This format is optional, install Tablib with ``pip install "tablib[cli]"`` to
|
||||||
make the format available.
|
make the format available.
|
||||||
|
|
||||||
csv
|
csv
|
||||||
@@ -83,7 +83,7 @@ df (DataFrame)
|
|||||||
==============
|
==============
|
||||||
|
|
||||||
Import/export using the pandas_ DataFrame format. This format is optional,
|
Import/export using the pandas_ DataFrame format. This format is optional,
|
||||||
install Tablib with ``pip install tablib[pandas]`` to make the format available.
|
install Tablib with ``pip install "tablib[pandas]"`` to make the format available.
|
||||||
|
|
||||||
.. _pandas: https://pandas.pydata.org/
|
.. _pandas: https://pandas.pydata.org/
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ The ``html`` format is currently export-only. The exports produce an HTML page
|
|||||||
with the data in a ``<table>``. If headers have been set, they will be used as
|
with the data in a ``<table>``. If headers have been set, they will be used as
|
||||||
table headers.
|
table headers.
|
||||||
|
|
||||||
This format is optional, install Tablib with ``pip install tablib[html]`` to
|
This format is optional, install Tablib with ``pip install "tablib[html]"`` to
|
||||||
make the format available.
|
make the format available.
|
||||||
|
|
||||||
jira
|
jira
|
||||||
@@ -132,7 +132,7 @@ ods
|
|||||||
Export data in OpenDocument Spreadsheet format. The ``ods`` format is currently
|
Export data in OpenDocument Spreadsheet format. The ``ods`` format is currently
|
||||||
export-only.
|
export-only.
|
||||||
|
|
||||||
This format is optional, install Tablib with ``pip install tablib[ods]`` to
|
This format is optional, install Tablib with ``pip install "tablib[ods]"`` to
|
||||||
make the format available.
|
make the format available.
|
||||||
|
|
||||||
.. admonition:: Binary Warning
|
.. admonition:: Binary Warning
|
||||||
@@ -183,7 +183,7 @@ xls
|
|||||||
|
|
||||||
Import/export data in Legacy Excel Spreadsheet representation.
|
Import/export data in Legacy Excel Spreadsheet representation.
|
||||||
|
|
||||||
This format is optional, install Tablib with ``pip install tablib[xls]`` to
|
This format is optional, install Tablib with ``pip install "tablib[xls]"`` to
|
||||||
make the format available.
|
make the format available.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -203,9 +203,18 @@ xlsx
|
|||||||
|
|
||||||
Import/export data in Excel 07+ Spreadsheet representation.
|
Import/export data in Excel 07+ Spreadsheet representation.
|
||||||
|
|
||||||
This format is optional, install Tablib with ``pip install tablib[xlsx]`` to
|
This format is optional, install Tablib with ``pip install "tablib[xlsx]"`` to
|
||||||
make the format available.
|
make the format available.
|
||||||
|
|
||||||
|
The ``import_set()`` and ``import_book()`` methods accept keyword
|
||||||
|
argument ``read_only``. If its value is ``True`` (the default), the
|
||||||
|
XLSX data source is read lazily. Lazy reading generally reduces time
|
||||||
|
and memory consumption, especially for large spreadsheets. However,
|
||||||
|
it relies on the XLSX data source declaring correct dimensions. Some
|
||||||
|
programs generate XLSX files with incorrect dimensions. Such files
|
||||||
|
may need to be loaded with this optimization turned off by passing
|
||||||
|
``read_only=False``.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
When reading an ``xlsx`` file containing formulas in its cells, Tablib will
|
When reading an ``xlsx`` file containing formulas in its cells, Tablib will
|
||||||
@@ -232,7 +241,7 @@ returned instead.
|
|||||||
|
|
||||||
Import assumes (for now) that headers exist.
|
Import assumes (for now) that headers exist.
|
||||||
|
|
||||||
This format is optional, install Tablib with ``pip install tablib[yaml]`` to
|
This format is optional, install Tablib with ``pip install "tablib[yaml]"`` to
|
||||||
make the format available.
|
make the format available.
|
||||||
|
|
||||||
.. _YAML: https://yaml.org
|
.. _YAML: https://yaml.org
|
||||||
|
|||||||
+3
-3
@@ -26,19 +26,19 @@ formats available:
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ pip install tablib[xlsx]
|
$ pip install "tablib[xlsx]"
|
||||||
|
|
||||||
Or all possible formats:
|
Or all possible formats:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ pip install tablib[all]
|
$ pip install "tablib[all]"
|
||||||
|
|
||||||
which is equivalent to:
|
which is equivalent to:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ pip install tablib[html, pandas, ods, xls, xlsx, yaml]
|
$ pip install "tablib[html, pandas, ods, xls, xlsx, yaml]"
|
||||||
|
|
||||||
-------------------
|
-------------------
|
||||||
Download the Source
|
Download the Source
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ THE SOFTWARE.
|
|||||||
Pythons Supported
|
Pythons Supported
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Python 3.5+ is officially supported.
|
Python 3.6+ is officially supported.
|
||||||
|
|
||||||
Now, go :ref:`install Tablib <install>`.
|
Now, go :ref:`install Tablib <install>`.
|
||||||
|
|
||||||
|
|||||||
+1
-6
@@ -1,7 +1,2 @@
|
|||||||
[tool.isort]
|
[tool.isort]
|
||||||
force_grid_wrap = 0
|
profile = "black"
|
||||||
include_trailing_comma = true
|
|
||||||
known_third_party = ["MarkupPy", "odf", "openpyxl", "pkg_resources", "setuptools", "tablib", "xlrd", "xlwt", "yaml"]
|
|
||||||
line_length = 88
|
|
||||||
multi_line_output = 3
|
|
||||||
use_parentheses = true
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
[pytest]
|
[pytest]
|
||||||
norecursedirs = .git .*
|
norecursedirs = .git .*
|
||||||
addopts = -rsxX --showlocals --tb=native --cov=tablib --cov=tests --cov-report xml --cov-report term --cov-report html
|
addopts = -rsxX --showlocals --tb=native --cov=tablib --cov=tests --cov-report xml --cov-report term --cov-report html
|
||||||
python_paths = .
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ from setuptools import find_packages, setup
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='tablib',
|
name='tablib',
|
||||||
use_scm_version=True,
|
use_scm_version={
|
||||||
|
'write_to': 'src/tablib/_version.py',
|
||||||
|
},
|
||||||
setup_requires=['setuptools_scm'],
|
setup_requires=['setuptools_scm'],
|
||||||
description='Format agnostic tabular data library (XLS, JSON, YAML, CSV)',
|
description='Format agnostic tabular data library (XLS, JSON, YAML, CSV)',
|
||||||
long_description=(
|
long_description=(
|
||||||
@@ -31,12 +33,12 @@ setup(
|
|||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 3 :: Only',
|
'Programming Language :: Python :: 3 :: Only',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.5',
|
|
||||||
'Programming Language :: Python :: 3.6',
|
'Programming Language :: Python :: 3.6',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
|
'Programming Language :: Python :: 3.9',
|
||||||
],
|
],
|
||||||
python_requires='>=3.5',
|
python_requires='>=3.6',
|
||||||
extras_require={
|
extras_require={
|
||||||
'all': ['markuppy', 'odfpy', 'openpyxl>=2.6.0', 'pandas', 'pyyaml', 'tabulate', 'xlrd', 'xlwt'],
|
'all': ['markuppy', 'odfpy', 'openpyxl>=2.6.0', 'pandas', 'pyyaml', 'tabulate', 'xlrd', 'xlwt'],
|
||||||
'cli': ['tabulate'],
|
'cli': ['tabulate'],
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
""" Tablib. """
|
""" Tablib. """
|
||||||
from pkg_resources import DistributionNotFound, get_distribution
|
try:
|
||||||
|
# Generated by setuptools-scm.
|
||||||
|
from ._version import version as __version__
|
||||||
|
except ImportError:
|
||||||
|
# Some broken installation.
|
||||||
|
__version__ = None
|
||||||
|
|
||||||
|
|
||||||
from tablib.core import ( # noqa: F401
|
from tablib.core import ( # noqa: F401
|
||||||
Databook,
|
Databook,
|
||||||
Dataset,
|
Dataset,
|
||||||
@@ -10,9 +17,3 @@ from tablib.core import ( # noqa: F401
|
|||||||
import_book,
|
import_book,
|
||||||
import_set,
|
import_set,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
|
||||||
__version__ = get_distribution(__name__).version
|
|
||||||
except DistributionNotFound:
|
|
||||||
# package is not installed
|
|
||||||
__version__ = None
|
|
||||||
|
|||||||
+22
-30
@@ -57,18 +57,10 @@ class Row:
|
|||||||
del self._row[i]
|
del self._row[i]
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
|
return self._row, self.tags
|
||||||
slots = dict()
|
|
||||||
|
|
||||||
for slot in self.__slots__:
|
|
||||||
attribute = getattr(self, slot)
|
|
||||||
slots[slot] = attribute
|
|
||||||
|
|
||||||
return slots
|
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state):
|
||||||
for (k, v) in list(state.items()):
|
self._row, self.tags = state
|
||||||
setattr(self, k, v)
|
|
||||||
|
|
||||||
def rpush(self, value):
|
def rpush(self, value):
|
||||||
self.insert(len(self._row), value)
|
self.insert(len(self._row), value)
|
||||||
@@ -147,9 +139,9 @@ class Dataset:
|
|||||||
|
|
||||||
.. admonition:: Format Attributes Definition
|
.. admonition:: Format Attributes Definition
|
||||||
|
|
||||||
If you look at the code, the various output/import formats are not
|
If you look at the code, the various output/import formats are not
|
||||||
defined within the :class:`Dataset` object. To add support for a new format, see
|
defined within the :class:`Dataset` object. To add support for a new format, see
|
||||||
:ref:`Adding New Formats <newformats>`.
|
:ref:`Adding New Formats <newformats>`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -299,7 +291,7 @@ class Dataset:
|
|||||||
def _get_headers(self):
|
def _get_headers(self):
|
||||||
"""An *optional* list of strings to be used for header rows and attribute names.
|
"""An *optional* list of strings to be used for header rows and attribute names.
|
||||||
|
|
||||||
This must be set manually. The given list length must equal :class:`Dataset.width`.
|
This must be set manually. The given list length must equal :attr:`Dataset.width`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return self.__headers
|
return self.__headers
|
||||||
@@ -335,7 +327,7 @@ class Dataset:
|
|||||||
set, a list of Python dictionaries will be returned. If no headers have been
|
set, a list of Python dictionaries will be returned. If no headers have been
|
||||||
set, a list of tuples (rows) will be returned instead.
|
set, a list of tuples (rows) will be returned instead.
|
||||||
|
|
||||||
A dataset object can also be imported by setting the :class:`Dataset.dict` attribute. ::
|
A dataset object can also be imported by setting the :attr:`Dataset.dict` attribute. ::
|
||||||
|
|
||||||
data = tablib.Dataset()
|
data = tablib.Dataset()
|
||||||
data.dict = [{'age': 90, 'first_name': 'Kenneth', 'last_name': 'Reitz'}]
|
data.dict = [{'age': 90, 'first_name': 'Kenneth', 'last_name': 'Reitz'}]
|
||||||
@@ -414,10 +406,10 @@ class Dataset:
|
|||||||
|
|
||||||
fmt = registry.get_format(format)
|
fmt = registry.get_format(format)
|
||||||
if not hasattr(fmt, 'import_set'):
|
if not hasattr(fmt, 'import_set'):
|
||||||
raise UnsupportedFormat('Format {} cannot be imported.'.format(format))
|
raise UnsupportedFormat(f'Format {format} cannot be imported.')
|
||||||
|
|
||||||
if not import_set:
|
if not import_set:
|
||||||
raise UnsupportedFormat('Format {} cannot be imported.'.format(format))
|
raise UnsupportedFormat(f'Format {format} cannot be imported.')
|
||||||
|
|
||||||
fmt.import_set(self, stream, **kwargs)
|
fmt.import_set(self, stream, **kwargs)
|
||||||
return self
|
return self
|
||||||
@@ -430,7 +422,7 @@ class Dataset:
|
|||||||
"""
|
"""
|
||||||
fmt = registry.get_format(format)
|
fmt = registry.get_format(format)
|
||||||
if not hasattr(fmt, 'export_set'):
|
if not hasattr(fmt, 'export_set'):
|
||||||
raise UnsupportedFormat('Format {} cannot be exported.'.format(format))
|
raise UnsupportedFormat(f'Format {format} cannot be exported.')
|
||||||
|
|
||||||
return fmt.export_set(self, **kwargs)
|
return fmt.export_set(self, **kwargs)
|
||||||
|
|
||||||
@@ -452,28 +444,28 @@ class Dataset:
|
|||||||
|
|
||||||
def rpush(self, row, tags=list()):
|
def rpush(self, row, tags=list()):
|
||||||
"""Adds a row to the end of the :class:`Dataset`.
|
"""Adds a row to the end of the :class:`Dataset`.
|
||||||
See :class:`Dataset.insert` for additional documentation.
|
See :method:`Dataset.insert` for additional documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.insert(self.height, row=row, tags=tags)
|
self.insert(self.height, row=row, tags=tags)
|
||||||
|
|
||||||
def lpush(self, row, tags=list()):
|
def lpush(self, row, tags=list()):
|
||||||
"""Adds a row to the top of the :class:`Dataset`.
|
"""Adds a row to the top of the :class:`Dataset`.
|
||||||
See :class:`Dataset.insert` for additional documentation.
|
See :method:`Dataset.insert` for additional documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.insert(0, row=row, tags=tags)
|
self.insert(0, row=row, tags=tags)
|
||||||
|
|
||||||
def append(self, row, tags=list()):
|
def append(self, row, tags=list()):
|
||||||
"""Adds a row to the :class:`Dataset`.
|
"""Adds a row to the :class:`Dataset`.
|
||||||
See :class:`Dataset.insert` for additional documentation.
|
See :method:`Dataset.insert` for additional documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.rpush(row, tags)
|
self.rpush(row, tags)
|
||||||
|
|
||||||
def extend(self, rows, tags=list()):
|
def extend(self, rows, tags=list()):
|
||||||
"""Adds a list of rows to the :class:`Dataset` using
|
"""Adds a list of rows to the :class:`Dataset` using
|
||||||
:class:`Dataset.append`
|
:method:`Dataset.append`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
@@ -515,20 +507,20 @@ class Dataset:
|
|||||||
|
|
||||||
data.append_col(col=random.randint)
|
data.append_col(col=random.randint)
|
||||||
|
|
||||||
If inserting a column, and :class:`Dataset.headers` is set, the
|
If inserting a column, and :attr:`Dataset.headers` is set, the
|
||||||
header attribute must be set, and will be considered the header for
|
header attribute must be set, and will be considered the header for
|
||||||
that row.
|
that row.
|
||||||
|
|
||||||
See :ref:`dyncols` for an in-depth example.
|
See :ref:`dyncols` for an in-depth example.
|
||||||
|
|
||||||
.. versionchanged:: 0.9.0
|
.. versionchanged:: 0.9.0
|
||||||
If inserting a column, and :class:`Dataset.headers` is set, the
|
If inserting a column, and :attr:`Dataset.headers` is set, the
|
||||||
header attribute must be set, and will be considered the header for
|
header attribute must be set, and will be considered the header for
|
||||||
that row.
|
that row.
|
||||||
|
|
||||||
.. versionadded:: 0.9.0
|
.. versionadded:: 0.9.0
|
||||||
If inserting a row, you can add :ref:`tags <tags>` to the row you are inserting.
|
If inserting a row, you can add :ref:`tags <tags>` to the row you are inserting.
|
||||||
This gives you the ability to :class:`filter <Dataset.filter>` your
|
This gives you the ability to :method:`filter <Dataset.filter>` your
|
||||||
:class:`Dataset` later.
|
:class:`Dataset` later.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -565,14 +557,14 @@ class Dataset:
|
|||||||
|
|
||||||
def rpush_col(self, col, header=None):
|
def rpush_col(self, col, header=None):
|
||||||
"""Adds a column to the end of the :class:`Dataset`.
|
"""Adds a column to the end of the :class:`Dataset`.
|
||||||
See :class:`Dataset.insert` for additional documentation.
|
See :method:`Dataset.insert` for additional documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.insert_col(self.width, col, header=header)
|
self.insert_col(self.width, col, header=header)
|
||||||
|
|
||||||
def lpush_col(self, col, header=None):
|
def lpush_col(self, col, header=None):
|
||||||
"""Adds a column to the top of the :class:`Dataset`.
|
"""Adds a column to the top of the :class:`Dataset`.
|
||||||
See :class:`Dataset.insert` for additional documentation.
|
See :method:`Dataset.insert` for additional documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.insert_col(0, col, header=header)
|
self.insert_col(0, col, header=header)
|
||||||
@@ -596,7 +588,7 @@ class Dataset:
|
|||||||
|
|
||||||
def append_col(self, col, header=None):
|
def append_col(self, col, header=None):
|
||||||
"""Adds a column to the :class:`Dataset`.
|
"""Adds a column to the :class:`Dataset`.
|
||||||
See :class:`Dataset.insert_col` for additional documentation.
|
See :method:`Dataset.insert_col` for additional documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.rpush_col(col, header)
|
self.rpush_col(col, header)
|
||||||
@@ -875,7 +867,7 @@ class Databook:
|
|||||||
|
|
||||||
fmt = registry.get_format(format)
|
fmt = registry.get_format(format)
|
||||||
if not hasattr(fmt, 'import_book'):
|
if not hasattr(fmt, 'import_book'):
|
||||||
raise UnsupportedFormat('Format {} cannot be loaded.'.format(format))
|
raise UnsupportedFormat(f'Format {format} cannot be loaded.')
|
||||||
|
|
||||||
fmt.import_book(self, stream, **kwargs)
|
fmt.import_book(self, stream, **kwargs)
|
||||||
return self
|
return self
|
||||||
@@ -888,7 +880,7 @@ class Databook:
|
|||||||
"""
|
"""
|
||||||
fmt = registry.get_format(format)
|
fmt = registry.get_format(format)
|
||||||
if not hasattr(fmt, 'export_book'):
|
if not hasattr(fmt, 'export_book'):
|
||||||
raise UnsupportedFormat('Format {} cannot be exported.'.format(format))
|
raise UnsupportedFormat(f'Format {format} cannot be exported.')
|
||||||
|
|
||||||
return fmt.export_book(self, **kwargs)
|
return fmt.export_book(self, **kwargs)
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ def load_format_class(dotted_path):
|
|||||||
module_path, class_name = dotted_path.rsplit('.', 1)
|
module_path, class_name = dotted_path.rsplit('.', 1)
|
||||||
return getattr(import_module(module_path), class_name)
|
return getattr(import_module(module_path), class_name)
|
||||||
except (ValueError, AttributeError) as err:
|
except (ValueError, AttributeError) as err:
|
||||||
raise ImportError("Unable to load format class '{}' ({})".format(dotted_path, err))
|
raise ImportError(f"Unable to load format class '{dotted_path}' ({err})")
|
||||||
|
|
||||||
|
|
||||||
class FormatDescriptorBase:
|
class FormatDescriptorBase:
|
||||||
@@ -122,7 +122,7 @@ class Registry:
|
|||||||
if key in uninstalled_format_messages:
|
if key in uninstalled_format_messages:
|
||||||
raise UnsupportedFormat(
|
raise UnsupportedFormat(
|
||||||
"The '{key}' format is not available. You may want to install the "
|
"The '{key}' format is not available. You may want to install the "
|
||||||
"{package_name} (or `pip install tablib[{extras_name}]`).".format(
|
"{package_name} (or `pip install \"tablib[{extras_name}]\"`).".format(
|
||||||
**uninstalled_format_messages[key], key=key
|
**uninstalled_format_messages[key], key=key
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class DataFrameFormat:
|
|||||||
if DataFrame is None:
|
if DataFrame is None:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
'DataFrame Format requires `pandas` to be installed.'
|
'DataFrame Format requires `pandas` to be installed.'
|
||||||
' Try `pip install tablib[pandas]`.')
|
' Try `pip install "tablib[pandas]"`.')
|
||||||
dataframe = DataFrame(dset.dict, columns=dset.headers)
|
dataframe = DataFrame(dset.dict, columns=dset.headers)
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class HTMLFormat:
|
|||||||
|
|
||||||
for i, dset in enumerate(databook._datasets):
|
for i, dset in enumerate(databook._datasets):
|
||||||
title = (dset.title if dset.title else 'Set %s' % (i))
|
title = (dset.title if dset.title else 'Set %s' % (i))
|
||||||
wrapper.write('<{}>{}</{}>\n'.format(cls.BOOK_ENDINGS, title, cls.BOOK_ENDINGS))
|
wrapper.write(f'<{cls.BOOK_ENDINGS}>{title}</{cls.BOOK_ENDINGS}>\n')
|
||||||
wrapper.write(dset.html)
|
wrapper.write(dset.html)
|
||||||
wrapper.write('\n')
|
wrapper.write('\n')
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class JIRAFormat:
|
|||||||
|
|
||||||
header = cls._get_header(dataset.headers) if dataset.headers else ''
|
header = cls._get_header(dataset.headers) if dataset.headers else ''
|
||||||
body = cls._get_body(dataset)
|
body = cls._get_body(dataset)
|
||||||
return '{}\n{}'.format(header, body) if header else body
|
return f'{header}\n{body}' if header else body
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_body(cls, dataset):
|
def _get_body(cls, dataset):
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ def _max_word_len(text):
|
|||||||
>>> _max_word_len('Python Module for Tabular Datasets')
|
>>> _max_word_len('Python Module for Tabular Datasets')
|
||||||
8
|
8
|
||||||
"""
|
"""
|
||||||
return max(len(word) for word in text.split()) if text else 0
|
return max([len(word) for word in text.split()], default=0) if text else 0
|
||||||
|
|
||||||
|
|
||||||
class ReSTFormat:
|
class ReSTFormat:
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
import tablib
|
|
||||||
import xlrd
|
import xlrd
|
||||||
import xlwt
|
import xlwt
|
||||||
from xlrd.xldate import xldate_as_datetime
|
from xlrd.xldate import xldate_as_datetime
|
||||||
|
|
||||||
|
import tablib
|
||||||
|
|
||||||
# special styles
|
# special styles
|
||||||
wrap = xlwt.easyxf("alignment: wrap on")
|
wrap = xlwt.easyxf("alignment: wrap on")
|
||||||
bold = xlwt.easyxf("font: bold on")
|
bold = xlwt.easyxf("font: bold on")
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
import tablib
|
|
||||||
from openpyxl.reader.excel import ExcelReader, load_workbook
|
from openpyxl.reader.excel import ExcelReader, load_workbook
|
||||||
from openpyxl.styles import Alignment, Font
|
from openpyxl.styles import Alignment, Font
|
||||||
from openpyxl.utils import get_column_letter
|
from openpyxl.utils import get_column_letter
|
||||||
from openpyxl.workbook import Workbook
|
from openpyxl.workbook import Workbook
|
||||||
from openpyxl.writer.excel import ExcelWriter
|
from openpyxl.writer.excel import ExcelWriter
|
||||||
|
|
||||||
|
import tablib
|
||||||
|
|
||||||
|
|
||||||
class XLSXFormat:
|
class XLSXFormat:
|
||||||
title = 'xlsx'
|
title = 'xlsx'
|
||||||
@@ -58,12 +59,12 @@ class XLSXFormat:
|
|||||||
return stream.getvalue()
|
return stream.getvalue()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_set(cls, dset, in_stream, headers=True):
|
def import_set(cls, dset, in_stream, headers=True, read_only=True):
|
||||||
"""Returns databook from XLS stream."""
|
"""Returns databook from XLS stream."""
|
||||||
|
|
||||||
dset.wipe()
|
dset.wipe()
|
||||||
|
|
||||||
xls_book = load_workbook(in_stream, read_only=True, data_only=True)
|
xls_book = load_workbook(in_stream, read_only=read_only, data_only=True)
|
||||||
sheet = xls_book.active
|
sheet = xls_book.active
|
||||||
|
|
||||||
dset.title = sheet.title
|
dset.title = sheet.title
|
||||||
@@ -76,12 +77,12 @@ class XLSXFormat:
|
|||||||
dset.append(row_vals)
|
dset.append(row_vals)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_book(cls, dbook, in_stream, headers=True):
|
def import_book(cls, dbook, in_stream, headers=True, read_only=True):
|
||||||
"""Returns databook from XLS stream."""
|
"""Returns databook from XLS stream."""
|
||||||
|
|
||||||
dbook.wipe()
|
dbook.wipe()
|
||||||
|
|
||||||
xls_book = load_workbook(in_stream, read_only=True, data_only=True)
|
xls_book = load_workbook(in_stream, read_only=read_only, data_only=True)
|
||||||
|
|
||||||
for sheet in xls_book.worksheets:
|
for sheet in xls_book.worksheets:
|
||||||
data = tablib.Dataset()
|
data = tablib.Dataset()
|
||||||
@@ -114,7 +115,7 @@ class XLSXFormat:
|
|||||||
row_number = i + 1
|
row_number = i + 1
|
||||||
for j, col in enumerate(row):
|
for j, col in enumerate(row):
|
||||||
col_idx = get_column_letter(j + 1)
|
col_idx = get_column_letter(j + 1)
|
||||||
cell = ws['{}{}'.format(col_idx, row_number)]
|
cell = ws[f'{col_idx}{row_number}']
|
||||||
|
|
||||||
# bold headers
|
# bold headers
|
||||||
if (row_number == 1) and dataset.headers:
|
if (row_number == 1) and dataset.headers:
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
""" Tablib - YAML Support.
|
""" Tablib - YAML Support.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import tablib
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
import tablib
|
||||||
|
|
||||||
|
|
||||||
class YAMLFormat:
|
class YAMLFormat:
|
||||||
title = 'yaml'
|
title = 'yaml'
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ class DbfLogicalFieldDef(DbfFieldDef):
|
|||||||
return False
|
return False
|
||||||
if value in "YyTt":
|
if value in "YyTt":
|
||||||
return True
|
return True
|
||||||
raise ValueError("[{}] Invalid logical value {!r}".format(self.name, value))
|
raise ValueError(f"[{self.name}] Invalid logical value {value!r}")
|
||||||
|
|
||||||
def encodeValue(self, value):
|
def encodeValue(self, value):
|
||||||
"""Return a character from the "TF?" set.
|
"""Return a character from the "TF?" set.
|
||||||
|
|||||||
Binary file not shown.
+12
-2
@@ -11,8 +11,9 @@ from io import BytesIO, StringIO
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
import tablib
|
|
||||||
from MarkupPy import markup
|
from MarkupPy import markup
|
||||||
|
|
||||||
|
import tablib
|
||||||
from tablib.core import Row, detect_format
|
from tablib.core import Row, detect_format
|
||||||
from tablib.exceptions import UnsupportedFormat
|
from tablib.exceptions import UnsupportedFormat
|
||||||
from tablib.formats import registry
|
from tablib.formats import registry
|
||||||
@@ -57,7 +58,7 @@ class TablibTestCase(BaseTestCase):
|
|||||||
# A known format but uninstalled
|
# A known format but uninstalled
|
||||||
del registry._formats['ods']
|
del registry._formats['ods']
|
||||||
msg = (r"The 'ods' format is not available. You may want to install the "
|
msg = (r"The 'ods' format is not available. You may want to install the "
|
||||||
"odfpy package \\(or `pip install tablib\\[ods\\]`\\).")
|
"odfpy package \\(or `pip install \"tablib\\[ods\\]\"`\\).")
|
||||||
with self.assertRaisesRegex(UnsupportedFormat, msg):
|
with self.assertRaisesRegex(UnsupportedFormat, msg):
|
||||||
data.export('ods')
|
data.export('ods')
|
||||||
|
|
||||||
@@ -659,6 +660,7 @@ class RSTTests(BaseTestCase):
|
|||||||
data.headers = self.headers
|
data.headers = self.headers
|
||||||
data.append(self.john)
|
data.append(self.john)
|
||||||
data.append(('Wendy', '', 43))
|
data.append(('Wendy', '', 43))
|
||||||
|
data.append(('Esther', ' ', 31))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
data.export('rst'),
|
data.export('rst'),
|
||||||
'========== ========= ===\n'
|
'========== ========= ===\n'
|
||||||
@@ -666,6 +668,7 @@ class RSTTests(BaseTestCase):
|
|||||||
'========== ========= ===\n'
|
'========== ========= ===\n'
|
||||||
'John Adams 90 \n'
|
'John Adams 90 \n'
|
||||||
'Wendy 43 \n'
|
'Wendy 43 \n'
|
||||||
|
'Esther 31 \n'
|
||||||
'========== ========= ==='
|
'========== ========= ==='
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1037,6 +1040,13 @@ class XLSXTests(BaseTestCase):
|
|||||||
data = tablib.Dataset().load(fh)
|
data = tablib.Dataset().load(fh)
|
||||||
self.assertEqual(data.headers[0], 'Hello World')
|
self.assertEqual(data.headers[0], 'Hello World')
|
||||||
|
|
||||||
|
def test_xlsx_bad_dimensions(self):
|
||||||
|
"""Test loading file with bad dimension. Must be done with
|
||||||
|
read_only=False."""
|
||||||
|
xls_source = Path(__file__).parent / 'files' / 'bad_dimensions.xlsx'
|
||||||
|
with xls_source.open('rb') as fh:
|
||||||
|
data = tablib.Dataset().load(fh, read_only=False)
|
||||||
|
self.assertEqual(data.height, 3)
|
||||||
|
|
||||||
class JSONTests(BaseTestCase):
|
class JSONTests(BaseTestCase):
|
||||||
def test_json_format_detect(self):
|
def test_json_format_detect(self):
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ minversion = 2.4
|
|||||||
envlist =
|
envlist =
|
||||||
docs
|
docs
|
||||||
lint
|
lint
|
||||||
py{35,36,37,38}
|
py{36,37,38,39}
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps =
|
deps =
|
||||||
-rtests/requirements.txt
|
-rtests/requirements.txt
|
||||||
extras = pandas
|
extras = pandas
|
||||||
|
passenv =
|
||||||
|
FORCE_COLOR
|
||||||
commands =
|
commands =
|
||||||
pytest {posargs:tests}
|
pytest {posargs:tests}
|
||||||
|
|
||||||
@@ -35,4 +37,3 @@ skip_install = true
|
|||||||
[flake8]
|
[flake8]
|
||||||
exclude =
|
exclude =
|
||||||
.tox
|
.tox
|
||||||
ignore=E501,E127,E128,E124
|
|
||||||
|
|||||||
Reference in New Issue
Block a user