mirror of
https://github.com/kennethreitz/tablib.git
synced 2026-06-05 06:56:13 +00:00
Add support for Python 3.9, drop EOL 3.5 (#477)
This commit is contained in:
committed by
GitHub
parent
5fa4496f9d
commit
8c5404591b
@@ -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: |
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ matrix:
|
|||||||
env: TOXENV=docs
|
env: TOXENV=docs
|
||||||
- python: 3.8
|
- python: 3.8
|
||||||
env: TOXENV=lint
|
env: TOXENV=lint
|
||||||
|
- python: 3.9
|
||||||
- python: 3.8
|
- python: 3.8
|
||||||
- python: 3.7
|
- python: 3.7
|
||||||
- python: 3.6
|
- python: 3.6
|
||||||
|
|||||||
@@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
- Dropped Python 3.5 support
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
- Added Python 3.9 support
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
- Prevented crash in rst export with only-space strings (#469).
|
- Prevented crash in rst export with only-space strings (#469).
|
||||||
|
|||||||
+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", "setuptools", "tablib", "xlrd", "xlwt", "yaml"]
|
|
||||||
line_length = 88
|
|
||||||
multi_line_output = 3
|
|
||||||
use_parentheses = true
|
|
||||||
|
|||||||
@@ -33,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'],
|
||||||
|
|||||||
+5
-5
@@ -414,10 +414,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 +430,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)
|
||||||
|
|
||||||
@@ -875,7 +875,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 +888,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:
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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'
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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