Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2017-08-28 20:26:38 +0200
committerArthur de Jong <arthur@arthurdejong.org>2017-08-28 20:26:38 +0200
commit8f6fa7db038a29941b70862386ae4120499637d2 (patch)
tree077cf3bb788174dbd52e630e04887a859fe80e0f
parentfbc92f8400d4565a86b81329053a1302ce21c2f8 (diff)
Ensure 100% branch coverage
This ensures that the tests fail if 100% branch coverage is not achieved. It also adds some pragma statements for code that cannot be covered or is Python version dependent. Furthermore, the get_module_list() function was removed from stdnum.util and more tests were made from stdnum.util and stdnum.numdb. The functionality to call format() in a country-specific IBAN implementation was also dropped because it was not used.
-rw-r--r--setup.cfg1
-rw-r--r--stdnum/iban.py3
-rw-r--r--stdnum/ismn.py4
-rw-r--r--stdnum/meid.py7
-rw-r--r--stdnum/numdb.py7
-rw-r--r--stdnum/util.py15
-rw-r--r--tests/numdb-test.dat1
-rw-r--r--tests/test_util.doctest50
8 files changed, 64 insertions, 24 deletions
diff --git a/setup.cfg b/setup.cfg
index 501bdbc..c37a5d4 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -13,6 +13,7 @@ cover-inclusive=true
cover-erase=true
cover-html=true
cover-html-dir=coverage
+cover-min-percentage=100
[build_sphinx]
all_files = 1
diff --git a/stdnum/iban.py b/stdnum/iban.py
index a9c56b3..5908a71 100644
--- a/stdnum/iban.py
+++ b/stdnum/iban.py
@@ -129,7 +129,4 @@ def is_valid(number, check_country=True):
def format(number, separator=' '):
"""Reformat the passed number to the space-separated format."""
number = compact(number)
- module = _get_cc_module(number[:2])
- if module and hasattr(module, 'format') and module.format != format:
- return module.format(number, separator=separator)
return separator.join(number[i:i + 4] for i in range(0, len(number), 4))
diff --git a/stdnum/ismn.py b/stdnum/ismn.py
index b04c763..d7337f0 100644
--- a/stdnum/ismn.py
+++ b/stdnum/ismn.py
@@ -121,8 +121,8 @@ def split(number):
6 digits) and a check digit."""
# clean up number
number = to_ismn13(compact(number))
- # rind the correct range and split the number
- for length, low, high in _ranges:
+ # find the correct range and split the number
+ for length, low, high in _ranges: # pragma: no branch (all ranges covered)
if low <= number[4:4 + length] <= high:
return (number[:3], number[3], number[4:4 + length],
number[4 + length:-1], number[-1])
diff --git a/stdnum/meid.py b/stdnum/meid.py
index 3077753..db43866 100644
--- a/stdnum/meid.py
+++ b/stdnum/meid.py
@@ -107,10 +107,11 @@ def compact(number, strip_check_digit=True):
def _bit_length(n):
"""Number of bits necessary to represent the number in binary."""
- if hasattr(n, 'bit_length'):
+ try:
return n.bit_length()
- import math
- return int(math.log(n, 2)) + 1
+ except AttributeError: # pragma: no cover (Python 2.6 only)
+ import math
+ return int(math.log(n, 2)) + 1
def validate(number, strip_check_digit=True):
diff --git a/stdnum/numdb.py b/stdnum/numdb.py
index ea3c3b9..e3e48e2 100644
--- a/stdnum/numdb.py
+++ b/stdnum/numdb.py
@@ -1,6 +1,6 @@
# numdb.py - module for handling hierarchically organised numbers
#
-# Copyright (C) 2010, 2011, 2012, 2013 Arthur de Jong
+# Copyright (C) 2010-2017 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -76,7 +76,7 @@ True
True
>>> dbfile.info('633322') == [
... ('6', {'prop1': 'boo'}),
-... ('333', {'prop2': 'bar', 'prop3': 'baz'}),
+... ('333', {'prop2': 'bar', 'prop3': 'baz', 'prop4': 'bla'}),
... ('22', {}),
... ]
True
@@ -187,8 +187,7 @@ def read(fp):
for indent, length, low, high, props in _parse(fp):
if indent > last_indent:
# populate the children field of the last indent
- if stack[last_indent][-1][4] is None:
- stack[last_indent][-1][4] = []
+ stack[last_indent][-1][4] = []
stack[indent] = stack[last_indent][-1][4]
stack[indent].append([length, low, high, props, None])
last_indent = indent
diff --git a/stdnum/util.py b/stdnum/util.py
index 111f5af..3d4b04f 100644
--- a/stdnum/util.py
+++ b/stdnum/util.py
@@ -120,7 +120,7 @@ def clean(number, deletechars=''):
number = ''.join(x for x in number)
except Exception:
raise InvalidFormat()
- if sys.version < '3' and isinstance(number, str): # pragma: no cover (Python 2/3 specific code)
+ if sys.version < '3' and isinstance(number, str): # pragma: no cover (Python 2 specific code)
try:
number = _clean_chars(number.decode()).encode()
except UnicodeError:
@@ -128,7 +128,7 @@ def clean(number, deletechars=''):
number = _clean_chars(number.decode('utf-8')).encode('utf-8')
except UnicodeError:
pass
- else: # pragma: no cover (Python 2/3 specific code)
+ else: # pragma: no cover (Python 3 specific code)
number = _clean_chars(number)
return ''.join(x for x in number if x not in deletechars)
@@ -138,8 +138,7 @@ def get_number_modules(base='stdnum'):
__import__(base)
module = sys.modules[base]
for loader, name, is_pkg in pkgutil.walk_packages(
- module.__path__, module.__name__ + '.',
- onerror=lambda x: None):
+ module.__path__, module.__name__ + '.'):
__import__(name)
module = sys.modules[name]
if hasattr(module, 'validate'):
@@ -158,14 +157,6 @@ def get_module_description(module):
return _strip_doctest_re.sub('', doc).strip()
-def get_module_list():
- for module in get_number_modules():
- yield ' * %s: %s' % (
- module.__name__.replace('stdnum.', ''),
- get_module_name(module),
- )
-
-
def get_cc_module(cc, name):
"""Find the country-specific named module."""
cc = cc.lower()
diff --git a/tests/numdb-test.dat b/tests/numdb-test.dat
index 2dfad4e..6b25454 100644
--- a/tests/numdb-test.dat
+++ b/tests/numdb-test.dat
@@ -3,6 +3,7 @@
100-999 prop2="bar"
200,300-399 prop3="baz"
6 prop1="boo"
+ 333 prop4="bla"
90-99 prop1="booz"
00-89 prop2="foo"
900-999 prop2="fooz"
diff --git a/tests/test_util.doctest b/tests/test_util.doctest
new file mode 100644
index 0000000..28674b7
--- /dev/null
+++ b/tests/test_util.doctest
@@ -0,0 +1,50 @@
+test_util.doctest - more detailed doctests for the stdnum.util package
+
+Copyright (C) 2017 Arthur de Jong
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA
+
+
+This file contains more detailed doctests for the stdnum.util package. It
+tries to test more corner cases and detailed functionality. This module is
+meant for internal use by stdnum modules and is not guaranteed to remain
+stable and as such not part of the public API of stdnum.
+
+>>> from stdnum.util import (
+... get_number_modules, get_module_name, get_module_description)
+
+
+The get_module_name() function is used in the example WSGI application and
+release scripts to get the number's name. It should not end in a dot (even
+though the docstring subject should).
+
+>>> from stdnum import isbn
+>>> get_module_name(isbn)
+'ISBN (International Standard Book Number)'
+>>> any(get_module_name(mod).endswith('.') for mod in get_number_modules())
+False
+
+
+The get_module_description() function is used in the example WSGI application
+to extract the extended description of the number for presentation purposes.
+The doctests should not be present in the descriptions.
+
+>>> from stdnum import isbn
+>>> get_module_description(isbn).startswith(
+... 'The ISBN is the International Standard Book Number')
+True
+>>> any('>>>' in get_module_description(mod) for mod in get_number_modules())
+False