mirror of
https://github.com/kennethreitz/tablib.git
synced 2026-06-05 15:00:19 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f7e39c1ad5 | |||
| aaeb5c8360 | |||
| 7a6c623cca | |||
| 0c31fcb3e4 | |||
| fa7fdb0443 | |||
| 8e19479cea | |||
| 8f39ac5055 | |||
| 8d02934c53 | |||
| d0963c206f |
@@ -9,7 +9,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: [3.5, 3.6, 3.7]
|
||||
python-version: [3.5, 3.6, 3.7, 3.8]
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
@@ -28,6 +28,5 @@ jobs:
|
||||
|
||||
- name: Tox tests
|
||||
shell: bash
|
||||
# Drop the dot: py3.7-tests -> py37-tests
|
||||
run: |
|
||||
tox -e py`echo ${{ matrix.python-version }} | tr -d .`-tests
|
||||
tox -e py
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v1.25.2
|
||||
rev: v1.26.2
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: ["--py3-plus"]
|
||||
@@ -12,7 +12,7 @@ repos:
|
||||
additional_dependencies: [toml]
|
||||
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.4.2
|
||||
rev: v1.4.4
|
||||
hooks:
|
||||
- id: python-check-blanket-noqa
|
||||
- id: rst-backticks
|
||||
|
||||
+14
@@ -1,5 +1,19 @@
|
||||
# History
|
||||
|
||||
## 1.1.0 (2020-02-13)
|
||||
|
||||
### Deprecations
|
||||
|
||||
- Upcoming breaking change in Tablib 2.0.0: the `Row.lpush/rpush` logic is reversed.
|
||||
`lpush` is appending while `rpush` and `append` are prepending. The broken behavior
|
||||
will remain in Tablib 1.x and will be fixed (reversed) in Tablib 2.0.0 (#453). If you
|
||||
count on the broken behavior, please update your code when you upgrade to Tablib 2.x.
|
||||
|
||||
### Improvements
|
||||
|
||||
- Tablib is now able to import CSV content where not all rows have the same
|
||||
length. Missing columns on any line receive the empty string (#226).
|
||||
|
||||
## 1.0.0 (2020-01-13)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
@@ -17,7 +17,7 @@ uninstalled_format_messages = {
|
||||
"df": {"package_name": "pandas package", "extras_name": "pandas"},
|
||||
"html": {"package_name": "MarkupPy package", "extras_name": "html"},
|
||||
"ods": {"package_name": "odfpy package", "extras_name": "ods"},
|
||||
"xls": {"package_name": "odfpy and xlwt packages", "extras_name": "ods"},
|
||||
"xls": {"package_name": "xlrd and xlwt packages", "extras_name": "xls"},
|
||||
"xlsx": {"package_name": "openpyxl package", "extras_name": "xlsx"},
|
||||
"yaml": {"package_name": "pyyaml package", "extras_name": "yaml"},
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ class CSVFormat:
|
||||
if (i == 0) and (headers):
|
||||
dset.headers = row
|
||||
elif row:
|
||||
if i > 0 and len(row) < dset.width:
|
||||
row += [''] * (dset.width - len(row))
|
||||
dset.append(row)
|
||||
|
||||
@classmethod
|
||||
|
||||
+13
-10
@@ -3,12 +3,12 @@
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
import openpyxl
|
||||
import tablib
|
||||
|
||||
Workbook = openpyxl.workbook.Workbook
|
||||
ExcelWriter = openpyxl.writer.excel.ExcelWriter
|
||||
get_column_letter = openpyxl.utils.get_column_letter
|
||||
from openpyxl.reader.excel import ExcelReader, load_workbook
|
||||
from openpyxl.styles import Alignment, Font
|
||||
from openpyxl.utils import get_column_letter
|
||||
from openpyxl.workbook import Workbook
|
||||
from openpyxl.writer.excel import ExcelWriter
|
||||
|
||||
|
||||
class XLSXFormat:
|
||||
@@ -19,7 +19,10 @@ class XLSXFormat:
|
||||
def detect(cls, stream):
|
||||
"""Returns True if given stream is a readable excel file."""
|
||||
try:
|
||||
openpyxl.reader.excel.load_workbook(stream, read_only=True)
|
||||
# No need to fully load the file, it should be enough to be able to
|
||||
# read the manifest.
|
||||
reader = ExcelReader(stream, read_only=False)
|
||||
reader.read_manifest()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
@@ -60,7 +63,7 @@ class XLSXFormat:
|
||||
|
||||
dset.wipe()
|
||||
|
||||
xls_book = openpyxl.reader.excel.load_workbook(in_stream, read_only=True)
|
||||
xls_book = load_workbook(in_stream, read_only=True)
|
||||
sheet = xls_book.active
|
||||
|
||||
dset.title = sheet.title
|
||||
@@ -78,7 +81,7 @@ class XLSXFormat:
|
||||
|
||||
dbook.wipe()
|
||||
|
||||
xls_book = openpyxl.reader.excel.load_workbook(in_stream, read_only=True)
|
||||
xls_book = load_workbook(in_stream, read_only=True)
|
||||
|
||||
for sheet in xls_book.worksheets:
|
||||
data = tablib.Dataset()
|
||||
@@ -102,8 +105,8 @@ class XLSXFormat:
|
||||
_offset = i
|
||||
_package.insert((sep[0] + _offset), (sep[1],))
|
||||
|
||||
bold = openpyxl.styles.Font(bold=True)
|
||||
wrap_text = openpyxl.styles.Alignment(wrap_text=True)
|
||||
bold = Font(bold=True)
|
||||
wrap_text = Alignment(wrap_text=True)
|
||||
|
||||
for i, row in enumerate(_package):
|
||||
row_number = i + 1
|
||||
|
||||
@@ -804,6 +804,25 @@ class CSVTests(BaseTestCase):
|
||||
data.csv = csv_text
|
||||
self.assertEqual(data.width, 7)
|
||||
|
||||
def test_csv_import_set_ragged(self):
|
||||
"""Import CSV set when not all rows have the same length."""
|
||||
csv_text = (
|
||||
"H1,H2,H3\n"
|
||||
"A,B\n"
|
||||
"C,D,E\n"
|
||||
"\n"
|
||||
"F\n"
|
||||
)
|
||||
dataset = tablib.import_set(csv_text, format="csv")
|
||||
self.assertEqual(
|
||||
str(dataset),
|
||||
'H1|H2|H3\n'
|
||||
'--|--|--\n'
|
||||
'A |B | \n'
|
||||
'C |D |E \n'
|
||||
'F | | '
|
||||
)
|
||||
|
||||
def test_csv_export(self):
|
||||
"""Verify exporting dataset object as CSV."""
|
||||
|
||||
|
||||
@@ -8,12 +8,16 @@ envlist =
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
tests: -rtests/requirements.txt
|
||||
docs: sphinx
|
||||
-rtests/requirements.txt
|
||||
extras = pandas
|
||||
commands =
|
||||
tests: pytest {posargs:tests}
|
||||
docs: sphinx-build -b html -d {envtmpdir}/doctrees docs {envtmpdir}/html
|
||||
pytest {posargs:tests}
|
||||
|
||||
[testenv:docs]
|
||||
deps =
|
||||
sphinx
|
||||
commands =
|
||||
sphinx-build -b html -d {envtmpdir}/doctrees docs {envtmpdir}/html
|
||||
|
||||
[testenv:lint]
|
||||
deps =
|
||||
|
||||
Reference in New Issue
Block a user