summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo van Kemenade <hugovk@users.noreply.github.com>2019-10-20 12:58:52 +0300
committerGitHub <noreply@github.com>2019-10-20 12:58:52 +0300
commit7879fef65a152f34238a6a415d998e6480e163c4 (patch)
treed7795065d14600e927f86fe4fb67edbf592baf73
parent825de0193ba049c6cfd06b32dfa01a4873bfd381 (diff)
parentb8bff1190e97184f475f7c9834123274599bcca4 (diff)
downloadtablib-7879fef65a152f34238a6a415d998e6480e163c4.tar.gz
Remove Python 2 code (#410)
Remove Python 2 code
-rw-r--r--docs/conf.py13
-rw-r--r--docs/intro.rst2
-rw-r--r--pytest.ini2
-rw-r--r--src/tablib/core.py13
-rw-r--r--src/tablib/formats/_html.py2
-rw-r--r--src/tablib/formats/_jira.py8
-rw-r--r--src/tablib/formats/_rst.py2
-rw-r--r--src/tablib/formats/_xlsx.py2
-rw-r--r--src/tablib/packages/dbfpy/dbfnew.py2
-rw-r--r--src/tablib/packages/dbfpy/fields.py8
-rw-r--r--src/tablib/packages/dbfpy/utils.py3
-rwxr-xr-xtests/test_tablib.py88
-rw-r--r--tests/test_tablib_dbfpy_packages_utils.py170
13 files changed, 278 insertions, 37 deletions
diff --git a/docs/conf.py b/docs/conf.py
index 5c56c66..8df446e 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Tablib documentation build configuration file, created by
# sphinx-quickstart on Tue Oct 5 15:25:21 2010.
@@ -38,8 +37,8 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
-project = u'Tablib'
-copyright = u'2019 Jazzband'
+project = 'Tablib'
+copyright = '2019 Jazzband'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -181,8 +180,8 @@ htmlhelp_basename = 'Tablibdoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
- ('index', 'Tablib.tex', u'Tablib Documentation',
- u'Jazzband', 'manual'),
+ ('index', 'Tablib.tex', 'Tablib Documentation',
+ 'Jazzband', 'manual'),
]
latex_use_modindex = False
@@ -222,6 +221,6 @@ latex_use_parts = True
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
- ('index', 'tablib', u'Tablib Documentation',
- [u'Jazzband'], 1)
+ ('index', 'tablib', 'Tablib Documentation',
+ ['Jazzband'], 1)
]
diff --git a/docs/intro.rst b/docs/intro.rst
index 00562c1..064e5ad 100644
--- a/docs/intro.rst
+++ b/docs/intro.rst
@@ -74,7 +74,7 @@ THE SOFTWARE.
Pythons Supported
-----------------
-Python 3.5+ are officially supported.
+Python 3.5+ is officially supported.
Now, go :ref:`install Tablib <install>`.
diff --git a/pytest.ini b/pytest.ini
index f69d336..2288651 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -1,4 +1,4 @@
[pytest]
norecursedirs = .git .*
-addopts = -rsxX --showlocals --tb=native --cov=tablib --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 = .
diff --git a/src/tablib/core.py b/src/tablib/core.py
index 23903eb..61c7a50 100644
--- a/src/tablib/core.py
+++ b/src/tablib/core.py
@@ -40,9 +40,6 @@ class Row:
def __repr__(self):
return repr(self._row)
- def __getslice__(self, i, j):
- return self._row[i:j]
-
def __getitem__(self, i):
return self._row[i]
@@ -264,7 +261,7 @@ class Dataset:
else:
is_valid = (len(col) == self.height) if self.height else True
else:
- is_valid = all((len(x) == self.width for x in self._data))
+ is_valid = all(len(x) == self.width for x in self._data)
if is_valid:
return True
@@ -423,7 +420,7 @@ class Dataset:
export_set, import_set = self._formats.get(format, (None, None))
if not import_set:
- raise UnsupportedFormat('Format {0} cannot be imported.'.format(format))
+ raise UnsupportedFormat('Format {} cannot be imported.'.format(format))
import_set(self, in_stream, **kwargs)
return self
@@ -436,7 +433,7 @@ class Dataset:
"""
export_set, import_set = self._formats.get(format, (None, None))
if not export_set:
- raise UnsupportedFormat('Format {0} cannot be exported.'.format(format))
+ raise UnsupportedFormat('Format {} cannot be exported.'.format(format))
return export_set(self, **kwargs)
@@ -1095,7 +1092,7 @@ class Databook:
export_book, import_book = self._formats.get(format, (None, None))
if not import_book:
- raise UnsupportedFormat('Format {0} cannot be loaded.'.format(format))
+ raise UnsupportedFormat('Format {} cannot be loaded.'.format(format))
import_book(self, in_stream, **kwargs)
return self
@@ -1108,7 +1105,7 @@ class Databook:
"""
export_book, import_book = self._formats.get(format, (None, None))
if not export_book:
- raise UnsupportedFormat('Format {0} cannot be exported.'.format(format))
+ raise UnsupportedFormat('Format {} cannot be exported.'.format(format))
return export_book(self, **kwargs)
diff --git a/src/tablib/formats/_html.py b/src/tablib/formats/_html.py
index bb31128..edf0c0a 100644
--- a/src/tablib/formats/_html.py
+++ b/src/tablib/formats/_html.py
@@ -53,7 +53,7 @@ def export_book(databook):
for i, dset in enumerate(databook._datasets):
title = (dset.title if dset.title else 'Set %s' % (i))
- wrapper.write('<%s>%s</%s>\n' % (BOOK_ENDINGS, title, BOOK_ENDINGS))
+ wrapper.write('<{}>{}</{}>\n'.format(BOOK_ENDINGS, title, BOOK_ENDINGS))
wrapper.write(dset.html)
wrapper.write('\n')
diff --git a/src/tablib/formats/_jira.py b/src/tablib/formats/_jira.py
index 99dbf3e..96efcf7 100644
--- a/src/tablib/formats/_jira.py
+++ b/src/tablib/formats/_jira.py
@@ -19,7 +19,7 @@ def export_set(dataset):
header = _get_header(dataset.headers) if dataset.headers else ''
body = _get_body(dataset)
- return '%s\n%s' % (header, body) if header else body
+ return '{}\n{}'.format(header, body) if header else body
def _get_body(dataset):
@@ -31,6 +31,6 @@ def _get_header(headers):
def _serialize_row(row, delimiter='|'):
- return '%s%s%s' % (delimiter,
- delimiter.join([str(item) if item else ' ' for item in row]),
- delimiter)
+ return '{}{}{}'.format(delimiter,
+ delimiter.join([str(item) if item else ' ' for item in row]),
+ delimiter)
diff --git a/src/tablib/formats/_rst.py b/src/tablib/formats/_rst.py
index 8b5cfa0..8067f73 100644
--- a/src/tablib/formats/_rst.py
+++ b/src/tablib/formats/_rst.py
@@ -34,7 +34,7 @@ def _max_word_len(text):
8
"""
- return max((len(word) for word in text.split())) if text else 0
+ return max(len(word) for word in text.split()) if text else 0
def _get_column_string_lengths(dataset):
diff --git a/src/tablib/formats/_xlsx.py b/src/tablib/formats/_xlsx.py
index 0a947b8..6ac46b9 100644
--- a/src/tablib/formats/_xlsx.py
+++ b/src/tablib/formats/_xlsx.py
@@ -112,7 +112,7 @@ def dset_sheet(dataset, ws, freeze_panes=True):
row_number = i + 1
for j, col in enumerate(row):
col_idx = get_column_letter(j + 1)
- cell = ws['%s%s' % (col_idx, row_number)]
+ cell = ws['{}{}'.format(col_idx, row_number)]
# bold headers
if (row_number == 1) and dataset.headers:
diff --git a/src/tablib/packages/dbfpy/dbfnew.py b/src/tablib/packages/dbfpy/dbfnew.py
index 29c09a1..1562021 100644
--- a/src/tablib/packages/dbfpy/dbfnew.py
+++ b/src/tablib/packages/dbfpy/dbfnew.py
@@ -176,7 +176,7 @@ if __name__ == '__main__':
for i1 in range(len(dbft)):
rec = dbft[i1]
for fldName in dbft.fieldNames:
- print('%s:\t %s' % (fldName, rec[fldName]))
+ print('{}:\t {}'.format(fldName, rec[fldName]))
print()
dbft.close()
diff --git a/src/tablib/packages/dbfpy/fields.py b/src/tablib/packages/dbfpy/fields.py
index c763e1e..d6ee84e 100644
--- a/src/tablib/packages/dbfpy/fields.py
+++ b/src/tablib/packages/dbfpy/fields.py
@@ -134,11 +134,7 @@ class DbfFieldDef:
definition of this field.
"""
- if sys.version_info < (2, 4):
- # earlier versions did not support padding character
- _name = self.name[:11] + "\0" * (11 - len(self.name))
- else:
- _name = self.name.ljust(11, '\0')
+ _name = self.name.ljust(11, '\0')
return (
_name +
self.typeCode +
@@ -311,7 +307,7 @@ class DbfLogicalFieldDef(DbfFieldDef):
return False
if value in "YyTt":
return True
- raise ValueError("[%s] Invalid logical value %r" % (self.name, value))
+ raise ValueError("[{}] Invalid logical value {!r}".format(self.name, value))
def encodeValue(self, value):
"""Return a character from the "TF?" set.
diff --git a/src/tablib/packages/dbfpy/utils.py b/src/tablib/packages/dbfpy/utils.py
index b3388a7..284d3ee 100644
--- a/src/tablib/packages/dbfpy/utils.py
+++ b/src/tablib/packages/dbfpy/utils.py
@@ -158,9 +158,6 @@ class _InvalidValue:
def __str__(self):
return ""
- def __unicode__(self):
- return ""
-
def __repr__(self):
return "<INVALID>"
diff --git a/tests/test_tablib.py b/tests/test_tablib.py
index 77f2ef6..5464a8d 100755
--- a/tests/test_tablib.py
+++ b/tests/test_tablib.py
@@ -4,6 +4,7 @@
import datetime
import doctest
import json
+import pickle
import unittest
from uuid import uuid4
@@ -202,7 +203,7 @@ class TablibTestCase(BaseTestCase):
self.assertEqual(self.founders[2:], [self.tom])
def test_row_slicing(self):
- """Verify Row's __getslice__ method. Issue #184."""
+ """Verify Row slicing. Issue #184."""
john = Row(self.john)
@@ -486,6 +487,87 @@ class TablibTestCase(BaseTestCase):
self.founders.append(('First\nSecond', 'Name', 42))
self.founders.export('xlsx')
+ def test_row_repr(self):
+ """Row repr."""
+ # Arrange
+ john = Row(self.john)
+
+ # Act
+ output = str(john)
+
+ # Assert
+ self.assertEqual(output, "['John', 'Adams', 90]")
+
+ def test_row_pickle_unpickle(self):
+ """Row __setstate__ and __getstate__."""
+ # Arrange
+ before_pickle = Row(self.john)
+
+ # Act
+ output = pickle.loads(pickle.dumps(before_pickle))
+
+ # Assert
+ self.assertEqual(output[0], before_pickle[0])
+ self.assertEqual(output[1], before_pickle[1])
+ self.assertEqual(output[2], before_pickle[2])
+
+ def test_row_lpush(self):
+ """Row lpush."""
+ # Arrange
+ john = Row(self.john)
+ george = Row(self.george)
+
+ # Act
+ john.lpush(george)
+
+ # Assert
+ self.assertEqual(john[-1], george)
+
+ def test_row_append(self):
+ """Row append."""
+ # Arrange
+ john = Row(self.john)
+ george = Row(self.george)
+
+ # Act
+ john.append(george)
+
+ # Assert
+ self.assertEqual(john[0], george)
+
+ def test_row_contains(self):
+ """Row __contains__."""
+ # Arrange
+ john = Row(self.john)
+
+ # Act / Assert
+ self.assertIn("John", john)
+
+ def test_row_no_tag(self):
+ """Row has_tag."""
+ # Arrange
+ john = Row(self.john)
+
+ # Act / Assert
+ self.assertFalse(john.has_tag("not found"))
+ self.assertFalse(john.has_tag(None))
+
+ def test_row_has_tag(self):
+ """Row has_tag."""
+ # Arrange
+ john = Row(self.john, tags=["tag1"])
+
+ # Act / Assert
+ self.assertTrue(john.has_tag("tag1"))
+
+ def test_row_has_tags(self):
+ """Row has_tag."""
+ # Arrange
+ john = Row(self.john, tags=["tag1", "tag2"])
+
+ # Act / Assert
+ self.assertTrue(john.has_tag(["tag2", "tag1"]))
+
class HTMLTests(BaseTestCase):
def test_html_export(self):
@@ -1012,7 +1094,7 @@ class DBFTests(BaseTestCase):
for reg_char, data_char in zip(_dbf, data.dbf):
so_far += chr(data_char)
if reg_char != data_char and index not in [1, 2, 3]:
- raise AssertionError('Failing at char %s: %s vs %s %s' % (
+ raise AssertionError('Failing at char {}: {} vs {} {}'.format(
index, reg_char, data_char, so_far))
index += 1
@@ -1055,7 +1137,7 @@ class DBFTests(BaseTestCase):
# found_so_far += chr(data_char)
if reg_char != data_char and index not in [1, 2, 3]:
raise AssertionError(
- 'Failing at char %s: %s vs %s (found %s)' % (
+ 'Failing at char {}: {} vs {} (found {})'.format(
index, reg_char, data_char, found_so_far))
index += 1
diff --git a/tests/test_tablib_dbfpy_packages_utils.py b/tests/test_tablib_dbfpy_packages_utils.py
new file mode 100644
index 0000000..9288916
--- /dev/null
+++ b/tests/test_tablib_dbfpy_packages_utils.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+"""Tests for tablib.packages.dbfpy."""
+
+import datetime
+import unittest
+
+from tablib.packages.dbfpy import utils
+
+
+class UtilsUnzfillTestCase(unittest.TestCase):
+ """dbfpy.utils.unzfill test cases."""
+
+ def test_unzfill_with_nul(self):
+ # Arrange
+ text = b"abc\0xyz"
+
+ # Act
+ output = utils.unzfill(text)
+
+ # Assert
+ self.assertEqual(output, b"abc")
+
+ def test_unzfill_without_nul(self):
+ # Arrange
+ text = b"abcxyz"
+
+ # Act
+ output = utils.unzfill(text)
+
+ # Assert
+ self.assertEqual(output, b"abcxyz")
+
+
+class UtilsGetDateTestCase(unittest.TestCase):
+ """dbfpy.utils.getDate test cases."""
+
+ def test_getDate_none(self):
+ # Arrange
+ value = None
+
+ # Act
+ output = utils.getDate(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.date)
+
+ def test_getDate_datetime_date(self):
+ # Arrange
+ value = datetime.date(2019, 10, 19)
+
+ # Act
+ output = utils.getDate(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.date)
+ self.assertEqual(output, value)
+
+ def test_getDate_datetime_datetime(self):
+ # Arrange
+ value = datetime.datetime(2019, 10, 19, 12, 00, 00)
+
+ # Act
+ output = utils.getDate(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.date)
+ self.assertEqual(output, value)
+
+ def test_getDate_datetime_timestamp(self):
+ # Arrange
+ value = 1571515306
+
+ # Act
+ output = utils.getDate(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.date)
+ self.assertEqual(output, datetime.date(2019, 10, 19))
+
+ def test_getDate_datetime_string_yyyy_mm_dd(self):
+ # Arrange
+ value = "20191019"
+
+ # Act
+ output = utils.getDate(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.date)
+ self.assertEqual(output, datetime.date(2019, 10, 19))
+
+ def test_getDate_datetime_string_yymmdd(self):
+ # Arrange
+ value = "191019"
+
+ # Act
+ output = utils.getDate(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.date)
+ self.assertEqual(output, datetime.date(2019, 10, 19))
+
+
+class UtilsGetDateTimeTestCase(unittest.TestCase):
+ """dbfpy.utils.getDateTime test cases."""
+
+ def test_getDateTime_none(self):
+ # Arrange
+ value = None
+
+ # Act
+ output = utils.getDateTime(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.datetime)
+
+ def test_getDateTime_datetime_datetime(self):
+ # Arrange
+ value = datetime.datetime(2019, 10, 19, 12, 00, 00)
+
+ # Act
+ output = utils.getDateTime(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.date)
+ self.assertEqual(output, value)
+
+ def test_getDateTime_datetime_date(self):
+ # Arrange
+ value = datetime.date(2019, 10, 19)
+
+ # Act
+ output = utils.getDateTime(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.date)
+ self.assertEqual(output, datetime.datetime(2019, 10, 19, 00, 00))
+
+ def test_getDateTime_datetime_timestamp(self):
+ # Arrange
+ value = 1571515306
+
+ # Act
+ output = utils.getDateTime(value)
+
+ # Assert
+ self.assertIsInstance(output, datetime.datetime)
+
+ def test_getDateTime_datetime_string(self):
+ # Arrange
+ value = "20191019"
+
+ # Act / Assert
+ with self.assertRaises(NotImplementedError):
+ output = utils.getDateTime(value)
+
+
+class InvalidValueTestCase(unittest.TestCase):
+ """dbfpy.utils._InvalidValue test cases."""
+
+ def test_sanity(self):
+ # Arrange
+ INVALID_VALUE = utils.INVALID_VALUE
+
+ # Act / Assert
+ self.assertEqual(INVALID_VALUE, INVALID_VALUE)
+ self.assertNotEqual(INVALID_VALUE, 123)
+ self.assertEqual(int(INVALID_VALUE), 0)
+ self.assertEqual(float(INVALID_VALUE), 0.0)
+ self.assertEqual(str(INVALID_VALUE), "")
+ self.assertEqual(repr(INVALID_VALUE), "<INVALID>")