Add support for Python 3.9, drop EOL 3.5 (#477)

This commit is contained in:
Hugo van Kemenade
2020-10-30 19:01:48 +02:00
committed by GitHub
parent 5fa4496f9d
commit 8c5404591b
18 changed files with 81 additions and 40 deletions
+21 -5
View File
@@ -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: |
+20 -4
View File
@@ -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
+6 -6
View File
@@ -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
+1
View File
@@ -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
+8
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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:
+1 -1
View File
@@ -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')
+1 -1
View File
@@ -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):
+2 -1
View File
@@ -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 -2
View File
@@ -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:
+2 -1
View File
@@ -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'
+1 -1
View File
@@ -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.
+2 -1
View File
@@ -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
+3 -2
View File
@@ -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