SHA256
1
0
forked from pool/i18nspector
i18nspector/switch-to-pytest.patch
2021-11-22 23:05:17 +00:00

4673 lines
146 KiB
Diff

From b84035ee74cc646ddbabbb99d565e50973fe7b1d Mon Sep 17 00:00:00 2001
From: Stuart Prescott <stuart@debian.org>
Date: Thu, 28 Oct 2021 16:39:36 +1100
Subject: [PATCH 01/10] Change tests from nose to pytest
Some of the 'yield' tests are easy to refactor into parameterised tests
while others would take a fair amount of rethinking and/or additional
helper functions. At this stage, the relevant functions are simply decorated
with a 'collect_yielded' decorator that collects all the yield tests at
collection time and sets them up as a parameterised test to be run later.
---
pytest.ini | 4 +
tests/conftest.py | 21 ++
tests/run-tests | 21 +-
tests/test_changelog.py | 33 +-
tests/test_domains.py | 23 +-
tests/test_encodings.py | 117 +++---
tests/test_gettext.py | 134 ++++---
tests/test_iconv.py | 11 +-
tests/test_ling.py | 566 +++++++++++++++---------------
tests/test_misc.py | 49 ++-
tests/test_moparser.py | 21 +-
tests/test_polib4us.py | 14 +-
tests/test_strformat_c.py | 404 +++++++++++----------
tests/test_strformat_perlbrace.py | 19 +-
tests/test_strformat_pybrace.py | 99 +++---
tests/test_strformat_python.py | 198 ++++++-----
tests/test_tags.py | 27 +-
tests/test_terminal.py | 8 +-
tests/test_version.py | 8 +-
tests/test_xml.py | 12 +-
tests/tools.py | 41 ++-
21 files changed, 935 insertions(+), 895 deletions(-)
create mode 100644 pytest.ini
create mode 100644 tests/conftest.py
Index: i18nspector-0.26/pytest.ini
===================================================================
--- /dev/null
+++ i18nspector-0.26/pytest.ini
@@ -0,0 +1,4 @@
+[pytest]
+testpaths = tests
+python_classes = test_*
+python_functions = test *_test test_*
Index: i18nspector-0.26/tests/conftest.py
===================================================================
--- /dev/null
+++ i18nspector-0.26/tests/conftest.py
@@ -0,0 +1,19 @@
+
+import os
+import tempfile
+
+
+def pytest_sessionstart(session):
+ envvar = 'XDG_CACHE_HOME'
+ old_xdg_cache_home = os.environ.get(envvar, None)
+ xdg_temp_dir = tempfile.TemporaryDirectory(prefix='i18nspector.tests.') # pylint: disable=consider-using-with
+ os.environ[envvar] = xdg_temp_dir.name
+
+ def cleanup():
+ xdg_temp_dir.cleanup()
+ if old_xdg_cache_home is None:
+ del os.environ[envvar]
+ else:
+ os.environ[envvar] = old_xdg_cache_home
+
+ session.config.add_cleanup(cleanup)
Index: i18nspector-0.26/tests/run-tests
===================================================================
--- i18nspector-0.26.orig/tests/run-tests
+++ i18nspector-0.26/tests/run-tests
@@ -1,6 +1,6 @@
-#!/usr/bin/env python3
+#!/bin/bash
-# Copyright © 2013-2016 Jakub Wilk <jwilk@jwilk.net>
+# Copyright © 2021 Stuart Prescott <stuart@debian.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the “Software”), to deal
@@ -20,19 +20,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-import os
-import sys
-import tempfile
+set -e
-import nose
-
-sys.path[0] += '/..'
-
-from tests import blackbox_tests
-
-if __name__ == '__main__':
- with tempfile.TemporaryDirectory(prefix='i18nspector.tests.') as tmpdir:
- os.environ['XDG_CACHE_HOME'] = tmpdir
- nose.main(addplugins=[blackbox_tests.Plugin()])
-
-# vim:ts=4 sts=4 sw=4 et
+pytest -rsx "$@"
Index: i18nspector-0.26/tests/test_changelog.py
===================================================================
--- i18nspector-0.26.orig/tests/test_changelog.py
+++ i18nspector-0.26/tests/test_changelog.py
@@ -21,11 +21,9 @@
import os
import re
-from nose.tools import (
- assert_not_equal,
-)
-
import lib.tags
+from . import tools
+
here = os.path.dirname(__file__)
docdir = os.path.join(here, os.pardir, 'doc')
@@ -52,32 +50,39 @@ rename_re = re.compile(
r'([\w-]+) [(]from ([\w-]+)[)]'
)
-def test_tags():
- path = os.path.join(docdir, 'changelog')
- with open(path, 'rt', encoding='UTF-8') as file:
- changelog = file.read()
- summaries = summary_re.findall(changelog)
- changelog_tags = set()
+
+@tools.collect_yielded
+def test_tag_paramerisation():
def add(info, tag):
del info
if tag in changelog_tags:
raise AssertionError('changelog adds tag twice: ' + tag)
changelog_tags.add(tag)
+
def remove(info, tag):
del info
if tag not in changelog_tags:
raise AssertionError('changelog removes non-existent tag: ' + tag)
changelog_tags.remove(tag)
+
def rename(info, removed_tag, added_tag):
- assert_not_equal(removed_tag, added_tag)
+ assert removed_tag != added_tag
remove(info, removed_tag)
add(info, added_tag)
+
def check(info, tag):
del info
if tag not in changelog_tags:
raise AssertionError('tag not in changelog: ' + tag)
if tag not in data_tags:
raise AssertionError('changelog adds unknown tag: ' + tag)
+
+ path = os.path.join(docdir, 'changelog')
+ with open(path, 'rt', encoding='UTF-8') as file:
+ changelog = file.read()
+ summaries = summary_re.findall(changelog)
+ changelog_tags = set()
+
for summary in reversed(summaries):
match = summary_details_re.match(summary)
for key, lines in match.groupdict().items():
@@ -86,16 +91,17 @@ def test_tags():
lines = [l[8:] for l in lines.splitlines()]
if key == 'added':
for tag in lines:
- yield add, 'add', tag
+ yield add, ('add', tag)
elif key == 'renamed':
for line in lines:
added_tag, removed_tag = rename_re.match(line).groups()
- yield rename, 'rename', removed_tag, added_tag
+ yield rename, ('rename', removed_tag, added_tag)
else:
assert False
data_tags = frozenset(tag.name for tag in lib.tags.iter_tags())
for tag in sorted(changelog_tags | data_tags):
- yield check, 'check', tag
+ yield check, ('check', tag)
+
def test_trailing_whitespace():
path = os.path.join(docdir, 'changelog')
Index: i18nspector-0.26/tests/test_domains.py
===================================================================
--- i18nspector-0.26.orig/tests/test_domains.py
+++ i18nspector-0.26/tests/test_domains.py
@@ -18,12 +18,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-from nose.tools import (
- assert_false,
- assert_is,
- assert_raises,
- assert_true,
-)
+import pytest
import lib.domains as M
@@ -32,9 +27,9 @@ class test_special_domains:
def t(self, domain, special=True):
result = M.is_special_domain(domain)
if special:
- assert_true(result)
+ assert result
else:
- assert_false(result)
+ assert not result
def test_ok(self):
self.t('test.jwilk.net', False)
@@ -68,9 +63,9 @@ class test_special_domain_emails:
def t(self, email, special=True):
result = M.is_email_in_special_domain(email)
if special:
- assert_true(result)
+ assert result
else:
- assert_false(result)
+ assert not result
def test_valid(self):
self.t('jwilk@test.jwilk.net', False)
@@ -79,14 +74,14 @@ class test_special_domain_emails:
self.t('jwilk@example.net')
def test_no_at(self):
- with assert_raises(ValueError):
+ with pytest.raises(ValueError):
self.t('jwilk%jwilk.net')
class test_dotless_domains:
def t(self, domain, dotless=True):
result = M.is_dotless_domain(domain)
- assert_is(result, dotless)
+ assert result is dotless
def test_dotless(self):
self.t('net')
@@ -99,7 +94,7 @@ class test_dotless_emails:
def t(self, email, dotless=True):
result = M.is_email_in_dotless_domain(email)
- assert_is(result, dotless)
+ assert result is dotless
def test_dotless(self):
self.t('jwilk@net')
@@ -108,7 +103,7 @@ class test_dotless_emails:
self.t('jwilk@example.net', False)
def test_no_at(self):
- with assert_raises(ValueError):
+ with pytest.raises(ValueError):
self.t('jwilk%jwilk.net')
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_encodings.py
===================================================================
--- i18nspector-0.26.orig/tests/test_encodings.py
+++ i18nspector-0.26/tests/test_encodings.py
@@ -20,79 +20,85 @@
import curses.ascii
import sys
+import unittest
-import nose
-from nose.tools import (
- assert_equal,
- assert_false,
- assert_is_none,
- assert_not_in,
- assert_raises,
- assert_true,
-)
+import pytest
import lib.encodings as E
from . import tools
+
+# methods using the tools.collect_yielded decorator don't have a 'self'
+# since they end up being run before 'self' exists. pylint doesn't
+# understand this unusual situation
+# pylint: disable=no-method-argument
+
+
class test_is_portable_encoding:
def test_found(self):
- assert_true(E.is_portable_encoding('ISO-8859-2'))
+ assert E.is_portable_encoding('ISO-8859-2')
def test_found_(self):
- assert_true(E.is_portable_encoding('ISO_8859-2'))
+ assert E.is_portable_encoding('ISO_8859-2')
def test_found_nonpython(self):
- assert_false(E.is_portable_encoding('KOI8-T'))
- assert_true(E.is_portable_encoding('KOI8-T', python=False))
+ assert not E.is_portable_encoding('KOI8-T')
+ assert E.is_portable_encoding('KOI8-T', python=False)
def test_notfound(self):
- assert_false(E.is_portable_encoding('ISO-8859-16'))
- assert_false(E.is_portable_encoding('ISO-8859-16', python=False))
+ assert not E.is_portable_encoding('ISO-8859-16')
+ assert not E.is_portable_encoding('ISO-8859-16', python=False)
class test_propose_portable_encoding:
def test_identity(self):
encoding = 'ISO-8859-2'
portable_encoding = E.propose_portable_encoding(encoding)
- assert_equal(portable_encoding, encoding)
+ assert portable_encoding == encoding
- def test_found(self):
+ @tools.collect_yielded
+ def test_found():
def t(encoding, expected_portable_encoding):
portable_encoding = E.propose_portable_encoding(encoding)
- assert_equal(portable_encoding, expected_portable_encoding)
- yield t, 'ISO8859-2', 'ISO-8859-2'
- yield t, 'ISO_8859-2', 'ISO-8859-2'
- yield t, 'Windows-1250', 'CP1250'
+ assert portable_encoding == expected_portable_encoding
+ yield t, ('ISO8859-2', 'ISO-8859-2')
+ yield t, ('ISO_8859-2', 'ISO-8859-2')
+ yield t, ('Windows-1250', 'CP1250')
def test_notfound(self):
portable_encoding = E.propose_portable_encoding('ISO-8859-16')
- assert_is_none(portable_encoding)
+ assert portable_encoding is None
+
+
+def _test_missing(encoding):
+ assert not E.is_ascii_compatible_encoding(encoding)
+ with pytest.raises(E.EncodingLookupError):
+ E.is_ascii_compatible_encoding(encoding, missing_ok=False)
+
class test_ascii_compatibility:
- def test_portable(self):
+ @tools.collect_yielded
+ def test_portable():
def t(encoding):
- assert_true(E.is_ascii_compatible_encoding(encoding))
- assert_true(E.is_ascii_compatible_encoding(encoding, missing_ok=False))
+ assert E.is_ascii_compatible_encoding(encoding)
+ assert E.is_ascii_compatible_encoding(encoding, missing_ok=False)
for encoding in E.get_portable_encodings():
yield t, encoding
- def test_incompatible(self):
+ @tools.collect_yielded
+ def test_incompatible():
def t(encoding):
- assert_false(E.is_ascii_compatible_encoding(encoding))
- assert_false(E.is_ascii_compatible_encoding(encoding, missing_ok=False))
+ assert not E.is_ascii_compatible_encoding(encoding)
+ assert not E.is_ascii_compatible_encoding(encoding, missing_ok=False)
yield t, 'UTF-7'
yield t, 'UTF-16'
- def _test_missing(self, encoding):
- assert_false(E.is_ascii_compatible_encoding(encoding))
- with assert_raises(E.EncodingLookupError):
- E.is_ascii_compatible_encoding(encoding, missing_ok=False)
-
- def test_non_text(self):
- t = self._test_missing
+ @tools.collect_yielded
+ def test_non_text():
+ t = _test_missing
yield t, 'base64_codec'
yield t, 'bz2_codec'
yield t, 'hex_codec'
@@ -102,7 +108,8 @@ class test_ascii_compatibility:
yield t, 'zlib_codec'
def test_missing(self):
- self._test_missing('eggs')
+ _test_missing('eggs')
+
class test_get_character_name:
@@ -110,44 +117,44 @@ class test_get_character_name:
for i in range(ord('a'), ord('z')):
u = chr(i)
name = E.get_character_name(u)
- assert_equal(name, 'LATIN SMALL LETTER ' + u.upper())
+ assert name == 'LATIN SMALL LETTER ' + u.upper()
u = chr(i).upper()
name = E.get_character_name(u)
- assert_equal(name, 'LATIN CAPITAL LETTER ' + u)
+ assert name == 'LATIN CAPITAL LETTER ' + u
def test_c0(self):
for i, curses_name in zip(range(0, 0x20), curses.ascii.controlnames):
u = chr(i)
name = E.get_character_name(u)
expected_name = 'control character ' + curses_name
- assert_equal(name, expected_name)
+ assert name == expected_name
def test_del(self):
name = E.get_character_name('\x7F')
- assert_equal(name, 'control character DEL')
+ assert name == 'control character DEL'
def test_c1(self):
for i in range(0x80, 0xA0):
u = chr(i)
name = E.get_character_name(u)
- assert_true(name.startswith('control character '))
+ assert name.startswith('control character ')
def test_uniqueness(self):
names = set()
for i in range(0, 0x100):
u = chr(i)
name = E.get_character_name(u)
- assert_not_in(name, names)
+ assert name not in names
names.add(name)
def test_non_character(self):
name = E.get_character_name('\uFFFE')
- assert_equal(name, 'non-character')
+ assert name == 'non-character'
name = E.get_character_name('\uFFFF')
- assert_equal(name, 'non-character')
+ assert name == 'non-character'
def test_lookup_error(self):
- with assert_raises(ValueError):
+ with pytest.raises(ValueError):
E.get_character_name('\uE000')
class test_extra_encoding:
@@ -164,13 +171,13 @@ class test_extra_encoding:
except LookupError:
pass
else:
- raise nose.SkipTest(
+ raise unittest.SkipTest(
'python{ver[0]}.{ver[1]} supports the {enc} encoding'.format(
ver=sys.version_info,
enc=encoding
)
)
- with assert_raises(LookupError):
+ with pytest.raises(LookupError):
dec()
E.install_extra_encodings()
enc()
@@ -181,7 +188,7 @@ class test_extra_encoding:
E.install_extra_encodings()
encoding = '8859-2'
portable_encoding = E.propose_portable_encoding(encoding)
- assert_equal('ISO-' + encoding, portable_encoding)
+ assert 'ISO-' + encoding == portable_encoding
@tools.fork_isolation
def test_not_allowed(self):
@@ -193,14 +200,14 @@ class test_extra_encoding:
except LookupError:
pass
else:
- raise nose.SkipTest(
+ raise unittest.SkipTest(
'python{ver[0]}.{ver[1]} supports the {enc} encoding'.format(
ver=sys.version_info,
enc=encoding
)
)
E.install_extra_encodings()
- with assert_raises(LookupError):
+ with pytest.raises(LookupError):
enc()
_viscii_unicode = 'Ti\u1EBFng Vi\u1EC7t'
@@ -211,13 +218,13 @@ class test_extra_encoding:
E.install_extra_encodings()
u = self._viscii_unicode
b = u.encode('VISCII')
- assert_equal(b, self._viscii_bytes)
+ assert b == self._viscii_bytes
@tools.fork_isolation
def test_8b_encode_error(self):
E.install_extra_encodings()
u = self._viscii_unicode
- with assert_raises(UnicodeEncodeError):
+ with pytest.raises(UnicodeEncodeError):
u.encode('KOI8-RU')
@tools.fork_isolation
@@ -225,13 +232,13 @@ class test_extra_encoding:
E.install_extra_encodings()
b = self._viscii_bytes
u = b.decode('VISCII')
- assert_equal(u, self._viscii_unicode)
+ assert u == self._viscii_unicode
@tools.fork_isolation
def test_8b_decode_error(self):
E.install_extra_encodings()
b = self._viscii_bytes
- with assert_raises(UnicodeDecodeError):
+ with pytest.raises(UnicodeDecodeError):
b.decode('KOI8-T')
_euc_tw_unicode = '\u4E2D\u6587'
@@ -242,13 +249,13 @@ class test_extra_encoding:
E.install_extra_encodings()
u = self._euc_tw_unicode
b = u.encode('EUC-TW')
- assert_equal(b, self._euc_tw_bytes)
+ assert b == self._euc_tw_bytes
@tools.fork_isolation
def test_mb_encode_error(self):
E.install_extra_encodings()
u = self._viscii_unicode
- with assert_raises(UnicodeEncodeError):
+ with pytest.raises(UnicodeEncodeError):
u.encode('EUC-TW')
@tools.fork_isolation
@@ -256,13 +263,13 @@ class test_extra_encoding:
E.install_extra_encodings()
b = self._euc_tw_bytes
u = b.decode('EUC-TW')
- assert_equal(u, self._euc_tw_unicode)
+ assert u == self._euc_tw_unicode
@tools.fork_isolation
def test_mb_decode_error(self):
E.install_extra_encodings()
b = self._viscii_bytes
- with assert_raises(UnicodeDecodeError):
+ with pytest.raises(UnicodeDecodeError):
b.decode('EUC-TW')
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_gettext.py
===================================================================
--- i18nspector-0.26.orig/tests/test_gettext.py
+++ i18nspector-0.26/tests/test_gettext.py
@@ -20,16 +20,7 @@
import datetime
-from nose.tools import (
- assert_equal,
- assert_false,
- assert_is_instance,
- assert_is_none,
- assert_is_not_none,
- assert_less,
- assert_raises,
- assert_true,
-)
+import pytest
import lib.gettext as M
@@ -38,21 +29,21 @@ class test_header_fields:
def test_nonempty(self):
# XXX Update this number after editing data/header-fields:
expected = 12
- assert_equal(len(M.header_fields), expected)
+ assert len(M.header_fields) == expected
def test_no_x(self):
for field in M.header_fields:
- assert_false(field.startswith('X-'))
+ assert not field.startswith('X-')
def test_valid(self):
for field in M.header_fields:
- assert_true(M.is_valid_field_name(field))
+ assert M.is_valid_field_name(field)
class test_header_parser:
def t(self, message, expected):
parsed = list(M.parse_header(message))
- assert_equal(parsed, expected)
+ assert parsed == expected
def test_ok(self):
self.t(
@@ -91,8 +82,8 @@ class test_plural_exp:
def t(self, s, n=None, fn=None):
f = M.parse_plural_expression(s)
if n is not None:
- assert_is_not_none(fn)
- assert_equal(f(n), fn)
+ assert fn is not None
+ assert f(n) == fn
def test_const(self):
n = 42
@@ -101,7 +92,7 @@ class test_plural_exp:
def test_const_overflow(self):
m = (1 << 32) - 1
self.t(str(m), m, m)
- with assert_raises(OverflowError):
+ with pytest.raises(OverflowError):
self.t(str(m + 1), m + 1, False)
self.t(str(m + 1), m + 42, False)
@@ -112,7 +103,7 @@ class test_plural_exp:
def test_var_overflow(self):
m = (1 << 32) - 1
self.t('n', m, m)
- with assert_raises(OverflowError):
+ with pytest.raises(OverflowError):
self.t('n', m + 1, False)
self.t('42', m + 1, 42)
@@ -122,7 +113,7 @@ class test_plural_exp:
def test_add_overflow(self):
m = (1 << 32) - 1
self.t('n + 42', m - 42, m)
- with assert_raises(OverflowError):
+ with pytest.raises(OverflowError):
self.t('n + 42', m - 41, False)
self.t('n + 42', m - 23, False)
@@ -130,7 +121,7 @@ class test_plural_exp:
self.t('n - 23', 37, 14)
def test_sub_overflow(self):
- with assert_raises(OverflowError):
+ with pytest.raises(OverflowError):
self.t('n - 23', 6, False)
def test_mul(self):
@@ -140,7 +131,7 @@ class test_plural_exp:
m = (1 << 32) - 1
assert m % 17 == 0
self.t('n * 17', m / 17, m)
- with assert_raises(OverflowError):
+ with pytest.raises(OverflowError):
self.t('n * 17', (m / 17) + 1, False)
self.t('n * 2', (m + 1) / 2, False)
@@ -148,14 +139,14 @@ class test_plural_exp:
self.t('105 / n', 17, 6)
def test_div_by_0(self):
- with assert_raises(ZeroDivisionError):
+ with pytest.raises(ZeroDivisionError):
self.t('105 / n', 0, False)
def test_mod(self):
self.t('105 % n', 17, 3)
def test_mod_by_0(self):
- with assert_raises(ZeroDivisionError):
+ with pytest.raises(ZeroDivisionError):
self.t('105 % n', 0, False)
def test_and(self):
@@ -228,75 +219,75 @@ class test_plural_exp:
self.t('(2 ? 3 : 7) ? 23 : 37')
def test_badly_nested_conditional(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('2 ? (3 : 7 ? ) : 23')
def test_unary_minus(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('-37')
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('23 + (-37)')
def test_unary_plus(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('+42')
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('23 + (+37)')
def test_func_call(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('n(42)')
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('42(n)')
def test_unbalanced_parentheses(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('(6 * 7')
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6 * 7)')
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6) * (7')
def test_dangling_binop(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6 +')
def test_junk_token(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6 # 7')
def test_shift(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6 << 7')
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6 >> 7')
def test_pow(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6 ** 7')
def test_floor_div(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6 // 7')
def test_tuple(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('()')
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('(6, 7)')
def test_starred(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('*42')
def test_exotic_whitespace(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('6 *\xA07')
def test_empty(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('')
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t(' ')
class test_codomain:
@@ -308,9 +299,9 @@ class test_codomain:
cd = f.codomain()
if min_ is None:
assert max_ is None
- assert_is_none(cd)
+ assert cd is None
else:
- assert_equal(cd, (min_, max_))
+ assert cd == (min_, max_)
def test_num(self):
self.t('0', 0, 0)
@@ -530,9 +521,9 @@ class test_period:
op = f.period()
if offset is None:
assert period is None
- assert_is_none(op)
+ assert op is None
else:
- assert_equal(op, (offset, period))
+ assert op == (offset, period)
def test_num(self):
self.t('42', 0, 1)
@@ -619,20 +610,20 @@ class test_plural_forms:
def t(self, s, *, n, ljunk='', rjunk=''):
if ljunk or rjunk:
- with assert_raises(self.error):
+ with pytest.raises(self.error):
M.parse_plural_forms(s)
else:
(n0, expr0) = M.parse_plural_forms(s)
del expr0
- assert_equal(n0, n)
+ assert n0 == n
(n1, expr1, ljunk1, rjunk1) = M.parse_plural_forms(s, strict=False) # pylint: disable=unbalanced-tuple-unpacking
del expr1
- assert_equal(n1, n)
- assert_equal(ljunk1, ljunk)
- assert_equal(rjunk1, rjunk)
+ assert n1 == n
+ assert ljunk1 == ljunk
+ assert rjunk1 == rjunk
def test_nplurals_0(self):
- with assert_raises(self.error):
+ with pytest.raises(self.error):
self.t('nplurals=0; plural=0;', n=0)
def test_nplurals_positive(self):
@@ -651,15 +642,15 @@ class test_fix_date_format:
def t(self, old, expected):
if expected is None:
- with assert_raises(M.DateSyntaxError):
+ with pytest.raises(M.DateSyntaxError):
M.fix_date_format(old)
else:
new = M.fix_date_format(old)
- assert_is_not_none(new)
- assert_equal(new, expected)
+ assert new is not None
+ assert new == expected
def tbp(self, old):
- with assert_raises(M.BoilerplateDate):
+ with pytest.raises(M.BoilerplateDate):
M.fix_date_format(old)
def test_boilerplate(self):
@@ -710,10 +701,9 @@ class test_fix_date_format:
self.t('2002-01-01 03:05', None)
def test_tz_hint(self):
- assert_equal(
- M.fix_date_format('2002-01-01 03:05', tz_hint='+0900'),
- '2002-01-01 03:05+0900',
- )
+ assert (
+ M.fix_date_format('2002-01-01 03:05', tz_hint='+0900') ==
+ '2002-01-01 03:05+0900')
def test_gmt_before_tz(self):
self.t(
@@ -762,30 +752,30 @@ class test_parse_date:
t = staticmethod(M.parse_date)
def test_nonexistent(self):
- with assert_raises(M.DateSyntaxError):
+ with pytest.raises(M.DateSyntaxError):
self.t('2010-02-29 19:49+0200')
def test_existent(self):
d = self.t('2003-09-08 21:26+0200')
- assert_equal(d.second, 0)
- assert_is_instance(d, datetime.datetime)
- assert_equal(str(d), '2003-09-08 21:26:00+02:00')
+ assert d.second == 0
+ assert isinstance(d, datetime.datetime)
+ assert str(d) == '2003-09-08 21:26:00+02:00'
def test_epoch(self):
d = self.t('2008-04-03 16:06+0300')
- assert_less(M.epoch, d)
+ assert M.epoch < d
class test_string_formats:
def test_nonempty(self):
# XXX Update this number after editing data/string-formats:
expected = 28
- assert_equal(len(M.string_formats), expected)
+ assert len(M.string_formats) == expected
def test_lowercase(self):
for s in M.string_formats:
- assert_is_instance(s, str)
- assert_true(s)
- assert_equal(s, s.lower())
+ assert isinstance(s, str)
+ assert s
+ assert s == s.lower()
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_iconv.py
===================================================================
--- i18nspector-0.26.orig/tests/test_iconv.py
+++ i18nspector-0.26/tests/test_iconv.py
@@ -18,10 +18,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-from nose.tools import (
- assert_equal,
- assert_raises,
-)
+import pytest
import lib.iconv as M
@@ -32,11 +29,11 @@ class _test:
def test_encode(self):
b = M.encode(self.u, self.e)
- assert_equal(b, self.b)
+ assert b == self.b
def test_decode(self):
u = M.decode(self.b, self.e)
- assert_equal(u, self.u)
+ assert u == self.u
class test_iso2(_test):
u = 'Żrą łódź? Część miń!'
@@ -50,7 +47,7 @@ class test_tcvn(_test):
def test_incomplete_char():
b = 'Ę'.encode('UTF-8')[:1]
- with assert_raises(UnicodeDecodeError):
+ with pytest.raises(UnicodeDecodeError):
M.decode(b, 'UTF-8')
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_ling.py
===================================================================
--- i18nspector-0.26.orig/tests/test_ling.py
+++ i18nspector-0.26/tests/test_ling.py
@@ -18,19 +18,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-import nose
-from nose.tools import (
- assert_equal,
- assert_false,
- assert_in,
- assert_is,
- assert_is_instance,
- assert_is_none,
- assert_not_equal,
- assert_not_in,
- assert_raises,
- assert_true,
-)
+import unittest
+
+import pytest
import lib.encodings
import lib.ling
@@ -45,12 +35,12 @@ class test_fix_codes:
def t(self, l1, l2):
lang = L.parse_language(l1)
- assert_equal(str(lang), l1)
+ assert str(lang) == l1
if l1 == l2:
- assert_is_none(lang.fix_codes())
+ assert lang.fix_codes() is None
else:
- assert_is(lang.fix_codes(), True)
- assert_equal(str(lang), l2)
+ assert lang.fix_codes() is True
+ assert str(lang) == l2
def test_2_to_2(self):
self.t('grc', 'grc')
@@ -69,18 +59,18 @@ class test_fix_codes:
self.t('gre_GR', 'el_GR')
def test_ll_not_found(self):
- with assert_raises(L.FixingLanguageCodesFailed):
+ with pytest.raises(L.FixingLanguageCodesFailed):
self.t('ry', '')
def test_cc_not_found(self):
- with assert_raises(L.FixingLanguageCodesFailed):
+ with pytest.raises(L.FixingLanguageCodesFailed):
self.t('el_RY', '')
def test_language_repr():
# Language.__repr__() is never used by i18nspector itself,
# but it's useful for debugging test failures.
lng = T('el')
- assert_equal(repr(lng), '<Language el>')
+ assert repr(lng) == '<Language el>'
class test_language_equality:
@@ -89,47 +79,47 @@ class test_language_equality:
def test_eq(self):
l1 = T('el', 'GR')
l2 = T('el', 'GR')
- assert_equal(l1, l2)
- assert_equal(l2, l1)
+ assert l1 == l2
+ assert l2 == l1
def test_ne(self):
l1 = T('el')
l2 = T('el', 'GR')
- assert_not_equal(l1, l2)
- assert_not_equal(l2, l1)
+ assert l1 != l2
+ assert l2 != l1
def test_ne_other_type(self):
l1 = T('el')
- assert_not_equal(l1, 42)
- assert_not_equal(42, l1)
+ assert l1 != 42
+ assert 42 != l1 # pylint: disable=misplaced-comparison-constant
def test_almost_equal(self):
l1 = T('el')
l2 = T('el', 'GR')
- assert_true(l1.is_almost_equal(l2))
- assert_true(l2.is_almost_equal(l1))
+ assert l1.is_almost_equal(l2)
+ assert l2.is_almost_equal(l1)
def test_not_almost_equal(self):
l1 = T('el', 'GR')
l2 = T('grc', 'GR')
- assert_false(l1.is_almost_equal(l2))
- assert_false(l2.is_almost_equal(l1))
+ assert not l1.is_almost_equal(l2)
+ assert not l2.is_almost_equal(l1)
def test_not_almost_equal_other_type(self):
l1 = T('el')
- with assert_raises(TypeError):
+ with pytest.raises(TypeError):
l1.is_almost_equal(42)
class test_remove_encoding:
def t(self, l1, l2):
lang = L.parse_language(l1)
- assert_equal(str(lang), l1)
+ assert str(lang) == l1
if l1 == l2:
- assert_is_none(lang.remove_encoding())
+ assert lang.remove_encoding() is None
else:
- assert_is(lang.remove_encoding(), True)
- assert_equal(str(lang), l2)
+ assert lang.remove_encoding() is True
+ assert str(lang) == l2
def test_without_encoding(self):
self.t('el', 'el')
@@ -141,12 +131,12 @@ class test_remove_nonlinguistic_modifier
def t(self, l1, l2):
lang = L.parse_language(l1)
- assert_equal(str(lang), l1)
+ assert str(lang) == l1
if l1 == l2:
- assert_is_none(lang.remove_nonlinguistic_modifier())
+ assert lang.remove_nonlinguistic_modifier() is None
else:
- assert_is(lang.remove_nonlinguistic_modifier(), True)
- assert_equal(str(lang), l2)
+ assert lang.remove_nonlinguistic_modifier() is True
+ assert str(lang) == l2
def test_quot(self):
self.t('en@quot', 'en@quot')
@@ -162,18 +152,18 @@ class test_lookup_territory_code:
def test_found(self):
cc = L.lookup_territory_code('GR')
- assert_equal(cc, 'GR')
+ assert cc == 'GR'
def test_not_found(self):
cc = L.lookup_territory_code('RG')
- assert_is_none(cc)
+ assert cc is None
class test_get_language_for_name:
def t(self, name, expected):
lang = L.get_language_for_name(name)
- assert_is_instance(lang, T)
- assert_equal(str(lang), expected)
+ assert isinstance(lang, T)
+ assert str(lang) == expected
def test_found(self):
self.t('Greek', 'el')
@@ -194,69 +184,75 @@ class test_get_language_for_name:
self.t('Pashto, Pushto', 'ps')
def test_lone_comma(self):
- with assert_raises(LookupError):
+ with pytest.raises(LookupError):
self.t(',', None)
def test_not_found(self):
- with assert_raises(LookupError):
+ with pytest.raises(LookupError):
self.t('Nadsat', None)
class test_parse_language:
def test_ll(self):
lang = L.parse_language('el')
- assert_equal(lang.language_code, 'el')
- assert_is_none(lang.territory_code)
- assert_is_none(lang.encoding)
- assert_is_none(lang.modifier)
+ assert lang.language_code == 'el'
+ assert lang.territory_code is None
+ assert lang.encoding is None
+ assert lang.modifier is None
def test_lll(self):
lang = L.parse_language('ell')
- assert_equal(lang.language_code, 'ell')
- assert_is_none(lang.territory_code)
- assert_is_none(lang.encoding)
- assert_is_none(lang.modifier)
+ assert lang.language_code == 'ell'
+ assert lang.territory_code is None
+ assert lang.encoding is None
+ assert lang.modifier is None
def test_ll_cc(self):
lang = L.parse_language('el_GR')
- assert_equal(lang.language_code, 'el')
- assert_equal(lang.territory_code, 'GR')
- assert_is_none(lang.encoding)
- assert_is_none(lang.modifier)
+ assert lang.language_code == 'el'
+ assert lang.territory_code == 'GR'
+ assert lang.encoding is None
+ assert lang.modifier is None
def test_ll_cc_enc(self):
lang = L.parse_language('el_GR.UTF-8')
- assert_equal(lang.language_code, 'el')
- assert_equal(lang.territory_code, 'GR')
- assert_equal(lang.encoding, 'UTF-8')
- assert_is_none(lang.modifier)
+ assert lang.language_code == 'el'
+ assert lang.territory_code == 'GR'
+ assert lang.encoding == 'UTF-8'
+ assert lang.modifier is None
def test_ll_cc_modifier(self):
lang = L.parse_language('en_US@quot')
- assert_equal(lang.language_code, 'en')
- assert_equal(lang.territory_code, 'US')
- assert_is_none(lang.encoding)
- assert_equal(lang.modifier, 'quot')
+ assert lang.language_code == 'en'
+ assert lang.territory_code == 'US'
+ assert lang.encoding is None
+ assert lang.modifier == 'quot'
def test_syntax_error(self):
- with assert_raises(L.LanguageSyntaxError):
+ with pytest.raises(L.LanguageSyntaxError):
L.parse_language('GR')
class test_get_primary_languages:
def test_found(self):
langs = L.get_primary_languages()
- assert_in('el', langs)
+ assert 'el' in langs
def test_not_found(self):
langs = L.get_primary_languages()
- assert_not_in('ry', langs)
+ assert 'ry' not in langs
- def test_iso_639(self):
+ # methods using the tools.collect_yielded decorator don't have a 'self'
+ # since they end up being run before 'self' exists. pylint doesn't
+ # understand this unusual situation
+
+ @tools.collect_yielded
+ def test_iso_639():
+ # pylint: disable=no-method-argument
def t(lang_str):
lang = L.parse_language(lang_str)
- assert_is_none(lang.fix_codes())
- assert_equal(str(lang), lang_str)
+ assert lang.fix_codes() is None
+ assert str(lang) == lang_str
for lang_str in L.get_primary_languages():
yield t, lang_str
@@ -267,34 +263,30 @@ class test_get_plural_forms:
return lang.get_plural_forms()
def test_found_ll(self):
- assert_equal(
- self.t('el'),
- ['nplurals=2; plural=n != 1;']
- )
+ assert (
+ self.t('el') ==
+ ['nplurals=2; plural=n != 1;'])
def test_found_ll_cc(self):
- assert_equal(
- self.t('el_GR'),
- ['nplurals=2; plural=n != 1;']
- )
+ assert (
+ self.t('el_GR') ==
+ ['nplurals=2; plural=n != 1;'])
def test_en_ca(self):
- assert_equal(
- self.t('en'),
- self.t('en_CA'),
- )
+ assert (
+ self.t('en') ==
+ self.t('en_CA'))
def test_pt_br(self):
- assert_not_equal(
- self.t('pt'),
- self.t('pt_BR'),
- )
+ assert (
+ self.t('pt') !=
+ self.t('pt_BR'))
def test_not_known(self):
- assert_is_none(self.t('la'))
+ assert self.t('la') is None
def test_not_found(self):
- assert_is_none(self.t('ry'))
+ assert self.t('ry') is None
class test_principal_territory:
@@ -302,115 +294,116 @@ class test_principal_territory:
# el -> el_GR
lang = L.parse_language('el')
cc = lang.get_principal_territory_code()
- assert_equal(cc, 'GR')
+ assert cc == 'GR'
def test_remove_2(self):
# el_GR -> el
lang = L.parse_language('el_GR')
- assert_equal(str(lang), 'el_GR')
+ assert str(lang) == 'el_GR'
rc = lang.remove_principal_territory_code()
- assert_is(rc, True)
- assert_equal(str(lang), 'el')
+ assert rc is True
+ assert str(lang) == 'el'
def test_found_3(self):
# ang -> ang_GB
lang = L.parse_language('ang')
cc = lang.get_principal_territory_code()
- assert_equal(cc, 'GB')
+ assert cc == 'GB'
def test_remove_3(self):
# ang_GB -> ang
lang = L.parse_language('ang_GB')
- assert_equal(str(lang), 'ang_GB')
+ assert str(lang) == 'ang_GB'
rc = lang.remove_principal_territory_code()
- assert_is(rc, True)
- assert_equal(str(lang), 'ang')
+ assert rc is True
+ assert str(lang) == 'ang'
def test_no_principal_territory_code(self):
# en -/-> en_US
lang = L.parse_language('en')
cc = lang.get_principal_territory_code()
- assert_is_none(cc)
+ assert cc is None
def test_no_remove_principal_territory_code(self):
# en_US -/-> en
lang = L.parse_language('en_US')
- assert_equal(str(lang), 'en_US')
+ assert str(lang) == 'en_US'
rc = lang.remove_principal_territory_code()
- assert_is_none(rc)
- assert_equal(str(lang), 'en_US')
+ assert rc is None
+ assert str(lang) == 'en_US'
def test_not_found(self):
lang = L.parse_language('ry')
cc = lang.get_principal_territory_code()
- assert_equal(cc, None)
+ assert cc is None
class test_unrepresentable_characters:
def test_ll_bad(self):
lang = L.parse_language('pl')
result = lang.get_unrepresentable_characters('ISO-8859-1')
- assert_not_equal(result, [])
+ assert result != []
def test_ll_ok(self):
lang = L.parse_language('pl')
result = lang.get_unrepresentable_characters('ISO-8859-2')
- assert_equal(result, [])
+ assert result == []
def test_ll_cc_bad(self):
lang = L.parse_language('pl_PL')
result = lang.get_unrepresentable_characters('ISO-8859-1')
- assert_not_equal(result, [])
+ assert result != []
def test_ll_cc_ok(self):
lang = L.parse_language('pl_PL')
result = lang.get_unrepresentable_characters('ISO-8859-2')
- assert_equal(result, [])
+ assert result == []
def test_ll_mod_bad(self):
lang = L.parse_language('en@quot')
result = lang.get_unrepresentable_characters('ISO-8859-1')
- assert_not_equal(result, [])
+ assert result != []
def test_ll_mod_ok(self):
lang = L.parse_language('en@quot')
result = lang.get_unrepresentable_characters('UTF-8')
- assert_equal(result, [])
+ assert result == []
def test_ll_cc_mod_bad(self):
lang = L.parse_language('en_US@quot')
result = lang.get_unrepresentable_characters('ISO-8859-1')
- assert_not_equal(result, [])
+ assert result != []
def test_ll_cc_mod_ok(self):
lang = L.parse_language('en_US@quot')
result = lang.get_unrepresentable_characters('UTF-8')
- assert_equal(result, [])
+ assert result == []
def test_ll_optional(self):
# U+0178 (LATIN CAPITAL LETTER Y WITH DIAERESIS) is not representable
# in ISO-8859-1, but we normally turn a blind eye to this.
lang = L.parse_language('fr')
result = lang.get_unrepresentable_characters('ISO-8859-1')
- assert_equal(result, [])
+ assert result == []
result = lang.get_unrepresentable_characters('ISO-8859-1', strict=True)
- assert_not_equal(result, [])
+ assert result != []
def test_ll_not_found(self):
lang = L.parse_language('ry')
result = lang.get_unrepresentable_characters('ISO-8859-1')
- assert_is_none(result)
+ assert result is None
@tools.fork_isolation
def test_extra_encoding(self):
encoding = 'GEORGIAN-PS'
lang = L.parse_language('pl')
- with assert_raises(LookupError):
+ with pytest.raises(LookupError):
''.encode(encoding)
E.install_extra_encodings()
result = lang.get_unrepresentable_characters(encoding)
- assert_not_equal(result, [])
+ assert result != []
+@tools.collect_yielded
def test_glibc_supported():
def t(l):
lang = L.parse_language(l)
@@ -419,16 +412,16 @@ def test_glibc_supported():
except L.FixingLanguageCodesFailed:
# FIXME: some ISO-639-3 codes are not recognized yet
if len(l.split('_')[0]) == 3:
- raise nose.SkipTest('expected failure')
+ raise unittest.SkipTest('expected failure')
reason = locales_to_skip.get(l)
if reason is not None:
- raise nose.SkipTest(reason)
+ raise unittest.SkipTest(reason)
raise
assert_equal(str(lang), l)
try:
file = open('/usr/share/i18n/SUPPORTED', encoding='ASCII')
except OSError as exc:
- raise nose.SkipTest(exc)
+ raise unittest.SkipTest(exc)
locales = set()
with file:
for line in file:
@@ -452,6 +445,7 @@ def test_glibc_supported():
for l in sorted(locales):
yield t, l
+@tools.collect_yielded
def test_poedit():
# https://github.com/vslavik/poedit/blob/v1.8.1-oss/src/language_impl_legacy.h
# There won't be any new names in this table,
@@ -459,178 +453,178 @@ def test_poedit():
def t(name, poedit_ll):
poedit_ll = L.parse_language(poedit_ll)
ll = L.get_language_for_name(name)
- assert_equal(ll, poedit_ll)
+ assert ll == poedit_ll
def x(name, poedit_ll):
poedit_ll = L.parse_language(poedit_ll)
- with assert_raises(LookupError):
+ with pytest.raises(LookupError):
L.get_language_for_name(name)
- raise nose.SkipTest('expected failure')
- yield t, 'Abkhazian', 'ab'
- yield t, 'Afar', 'aa'
- yield t, 'Afrikaans', 'af'
- yield t, 'Albanian', 'sq'
- yield t, 'Amharic', 'am'
- yield t, 'Arabic', 'ar'
- yield t, 'Armenian', 'hy'
- yield t, 'Assamese', 'as'
- yield t, 'Avestan', 'ae'
- yield t, 'Aymara', 'ay'
- yield t, 'Azerbaijani', 'az'
- yield t, 'Bashkir', 'ba'
- yield t, 'Basque', 'eu'
- yield t, 'Belarusian', 'be'
- yield t, 'Bengali', 'bn'
- yield t, 'Bislama', 'bi'
- yield t, 'Bosnian', 'bs'
- yield t, 'Breton', 'br'
- yield t, 'Bulgarian', 'bg'
- yield t, 'Burmese', 'my'
- yield t, 'Catalan', 'ca'
- yield t, 'Chamorro', 'ch'
- yield t, 'Chechen', 'ce'
- yield t, 'Chichewa; Nyanja', 'ny'
- yield t, 'Chinese', 'zh'
- yield t, 'Church Slavic', 'cu'
- yield t, 'Chuvash', 'cv'
- yield t, 'Cornish', 'kw'
- yield t, 'Corsican', 'co'
- yield t, 'Croatian', 'hr'
- yield t, 'Czech', 'cs'
- yield t, 'Danish', 'da'
- yield t, 'Dutch', 'nl'
- yield t, 'Dzongkha', 'dz'
- yield t, 'English', 'en'
- yield t, 'Esperanto', 'eo'
- yield t, 'Estonian', 'et'
- yield t, 'Faroese', 'fo'
- yield t, 'Fijian', 'fj'
- yield t, 'Finnish', 'fi'
- yield t, 'French', 'fr'
- yield t, 'Frisian', 'fy'
- yield t, 'Friulian', 'fur'
- yield t, 'Gaelic', 'gd'
- yield t, 'Galician', 'gl'
- yield t, 'Georgian', 'ka'
- yield t, 'German', 'de'
- yield t, 'Greek', 'el'
- yield t, 'Guarani', 'gn'
- yield t, 'Gujarati', 'gu'
- yield t, 'Hausa', 'ha'
- yield t, 'Hebrew', 'he'
- yield t, 'Herero', 'hz'
- yield t, 'Hindi', 'hi'
- yield t, 'Hiri Motu', 'ho'
- yield t, 'Hungarian', 'hu'
- yield t, 'Icelandic', 'is'
- yield t, 'Indonesian', 'id'
- yield t, 'Interlingua', 'ia'
- yield t, 'Interlingue', 'ie'
- yield t, 'Inuktitut', 'iu'
- yield t, 'Inupiaq', 'ik'
- yield t, 'Irish', 'ga'
- yield t, 'Italian', 'it'
- yield t, 'Japanese', 'ja'
- yield t, 'Javanese', 'jv' # https://github.com/vslavik/poedit/pull/193
- yield t, 'Kalaallisut', 'kl'
- yield t, 'Kannada', 'kn'
- yield t, 'Kashmiri', 'ks'
- yield t, 'Kazakh', 'kk'
- yield t, 'Khmer', 'km'
- yield t, 'Kikuyu', 'ki'
- yield t, 'Kinyarwanda', 'rw'
- yield t, 'Komi', 'kv'
- yield t, 'Korean', 'ko'
- yield t, 'Kuanyama', 'kj'
- yield t, 'Kurdish', 'ku'
- yield t, 'Kyrgyz', 'ky'
- yield t, 'Lao', 'lo'
- yield t, 'Latin', 'la'
- yield t, 'Latvian', 'lv'
- yield t, 'Letzeburgesch', 'lb'
- yield t, 'Lingala', 'ln'
- yield t, 'Lithuanian', 'lt'
- yield t, 'Macedonian', 'mk'
- yield t, 'Malagasy', 'mg'
- yield t, 'Malay', 'ms'
- yield t, 'Malayalam', 'ml'
- yield t, 'Maltese', 'mt'
- yield t, 'Maori', 'mi'
- yield t, 'Marathi', 'mr'
- yield t, 'Marshall', 'mh'
- yield t, 'Moldavian', 'ro_MD' # XXX poedit uses deprecated "mo"
- yield t, 'Mongolian', 'mn'
- yield t, 'Nauru', 'na'
- yield t, 'Navajo', 'nv'
- yield t, 'Ndebele, South', 'nr'
- yield t, 'Ndonga', 'ng'
- yield t, 'Nepali', 'ne'
- yield t, 'Northern Sami', 'se'
- yield t, 'Norwegian Bokmal', 'nb'
- yield t, 'Norwegian Nynorsk', 'nn'
- yield t, 'Occitan', 'oc'
- yield t, 'Oriya', 'or'
- yield t, 'Ossetian; Ossetic', 'os'
- yield t, 'Pali', 'pi'
- yield t, 'Panjabi', 'pa'
- yield t, 'Pashto, Pushto', 'ps'
- yield t, 'Persian', 'fa'
- yield t, 'Polish', 'pl'
- yield t, 'Portuguese', 'pt'
- yield t, 'Quechua', 'qu'
- yield t, 'Rhaeto-Romance', 'rm'
- yield t, 'Romanian', 'ro'
- yield t, 'Rundi', 'rn'
- yield t, 'Russian', 'ru'
- yield t, 'Samoan', 'sm'
- yield t, 'Sangro', 'sg'
- yield t, 'Sanskrit', 'sa'
- yield t, 'Sardinian', 'sc'
- yield t, 'Serbian', 'sr'
- yield t, 'Sesotho', 'st'
- yield t, 'Setswana', 'tn'
- yield t, 'Shona', 'sn'
- yield t, 'Sindhi', 'sd'
- yield t, 'Sinhalese', 'si'
- yield t, 'Siswati', 'ss'
- yield t, 'Slovak', 'sk'
- yield t, 'Slovenian', 'sl'
- yield t, 'Somali', 'so'
- yield t, 'Spanish', 'es'
- yield t, 'Sundanese', 'su'
- yield t, 'Swahili', 'sw'
- yield t, 'Swedish', 'sv'
- yield t, 'Tagalog', 'tl'
- yield t, 'Tahitian', 'ty'
- yield t, 'Tajik', 'tg'
- yield t, 'Tamil', 'ta'
- yield t, 'Tatar', 'tt'
- yield t, 'Telugu', 'te'
- yield t, 'Thai', 'th'
- yield t, 'Tibetan', 'bo'
- yield t, 'Tigrinya', 'ti'
- yield t, 'Tonga', 'to'
- yield t, 'Tsonga', 'ts'
- yield t, 'Turkish', 'tr'
- yield t, 'Turkmen', 'tk'
- yield t, 'Twi', 'tw'
- yield t, 'Ukrainian', 'uk'
- yield t, 'Urdu', 'ur'
- yield t, 'Uyghur', 'ug'
- yield t, 'Uzbek', 'uz'
- yield t, 'Vietnamese', 'vi'
- yield t, 'Volapuk', 'vo'
- yield t, 'Walloon', 'wa'
- yield t, 'Welsh', 'cy'
- yield t, 'Wolof', 'wo'
- yield t, 'Xhosa', 'xh'
- yield t, 'Yiddish', 'yi'
- yield t, 'Yoruba', 'yo'
- yield t, 'Zhuang', 'za'
- yield t, 'Zulu', 'zu'
+ raise unittest.SkipTest('expected failure')
+ yield t, ('Abkhazian', 'ab')
+ yield t, ('Afar', 'aa')
+ yield t, ('Afrikaans', 'af')
+ yield t, ('Albanian', 'sq')
+ yield t, ('Amharic', 'am')
+ yield t, ('Arabic', 'ar')
+ yield t, ('Armenian', 'hy')
+ yield t, ('Assamese', 'as')
+ yield t, ('Avestan', 'ae')
+ yield t, ('Aymara', 'ay')
+ yield t, ('Azerbaijani', 'az')
+ yield t, ('Bashkir', 'ba')
+ yield t, ('Basque', 'eu')
+ yield t, ('Belarusian', 'be')
+ yield t, ('Bengali', 'bn')
+ yield t, ('Bislama', 'bi')
+ yield t, ('Bosnian', 'bs')
+ yield t, ('Breton', 'br')
+ yield t, ('Bulgarian', 'bg')
+ yield t, ('Burmese', 'my')
+ yield t, ('Catalan', 'ca')
+ yield t, ('Chamorro', 'ch')
+ yield t, ('Chechen', 'ce')
+ yield t, ('Chichewa; Nyanja', 'ny')
+ yield t, ('Chinese', 'zh')
+ yield t, ('Church Slavic', 'cu')
+ yield t, ('Chuvash', 'cv')
+ yield t, ('Cornish', 'kw')
+ yield t, ('Corsican', 'co')
+ yield t, ('Croatian', 'hr')
+ yield t, ('Czech', 'cs')
+ yield t, ('Danish', 'da')
+ yield t, ('Dutch', 'nl')
+ yield t, ('Dzongkha', 'dz')
+ yield t, ('English', 'en')
+ yield t, ('Esperanto', 'eo')
+ yield t, ('Estonian', 'et')
+ yield t, ('Faroese', 'fo')
+ yield t, ('Fijian', 'fj')
+ yield t, ('Finnish', 'fi')
+ yield t, ('French', 'fr')
+ yield t, ('Frisian', 'fy')
+ yield t, ('Friulian', 'fur')
+ yield t, ('Gaelic', 'gd')
+ yield t, ('Galician', 'gl')
+ yield t, ('Georgian', 'ka')
+ yield t, ('German', 'de')
+ yield t, ('Greek', 'el')
+ yield t, ('Guarani', 'gn')
+ yield t, ('Gujarati', 'gu')
+ yield t, ('Hausa', 'ha')
+ yield t, ('Hebrew', 'he')
+ yield t, ('Herero', 'hz')
+ yield t, ('Hindi', 'hi')
+ yield t, ('Hiri Motu', 'ho')
+ yield t, ('Hungarian', 'hu')
+ yield t, ('Icelandic', 'is')
+ yield t, ('Indonesian', 'id')
+ yield t, ('Interlingua', 'ia')
+ yield t, ('Interlingue', 'ie')
+ yield t, ('Inuktitut', 'iu')
+ yield t, ('Inupiaq', 'ik')
+ yield t, ('Irish', 'ga')
+ yield t, ('Italian', 'it')
+ yield t, ('Japanese', 'ja')
+ yield t, ('Javanese', 'jv') # https://github.com/vslavik/poedit/pull/193
+ yield t, ('Kalaallisut', 'kl')
+ yield t, ('Kannada', 'kn')
+ yield t, ('Kashmiri', 'ks')
+ yield t, ('Kazakh', 'kk')
+ yield t, ('Khmer', 'km')
+ yield t, ('Kikuyu', 'ki')
+ yield t, ('Kinyarwanda', 'rw')
+ yield t, ('Komi', 'kv')
+ yield t, ('Korean', 'ko')
+ yield t, ('Kuanyama', 'kj')
+ yield t, ('Kurdish', 'ku')
+ yield t, ('Kyrgyz', 'ky')
+ yield t, ('Lao', 'lo')
+ yield t, ('Latin', 'la')
+ yield t, ('Latvian', 'lv')
+ yield t, ('Letzeburgesch', 'lb')
+ yield t, ('Lingala', 'ln')
+ yield t, ('Lithuanian', 'lt')
+ yield t, ('Macedonian', 'mk')
+ yield t, ('Malagasy', 'mg')
+ yield t, ('Malay', 'ms')
+ yield t, ('Malayalam', 'ml')
+ yield t, ('Maltese', 'mt')
+ yield t, ('Maori', 'mi')
+ yield t, ('Marathi', 'mr')
+ yield t, ('Marshall', 'mh')
+ yield t, ('Moldavian', 'ro_MD') # XXX poedit uses deprecated "mo"
+ yield t, ('Mongolian', 'mn')
+ yield t, ('Nauru', 'na')
+ yield t, ('Navajo', 'nv')
+ yield t, ('Ndebele, South', 'nr')
+ yield t, ('Ndonga', 'ng')
+ yield t, ('Nepali', 'ne')
+ yield t, ('Northern Sami', 'se')
+ yield t, ('Norwegian Bokmal', 'nb')
+ yield t, ('Norwegian Nynorsk', 'nn')
+ yield t, ('Occitan', 'oc')
+ yield t, ('Oriya', 'or')
+ yield t, ('Ossetian; Ossetic', 'os')
+ yield t, ('Pali', 'pi')
+ yield t, ('Panjabi', 'pa')
+ yield t, ('Pashto, Pushto', 'ps')
+ yield t, ('Persian', 'fa')
+ yield t, ('Polish', 'pl')
+ yield t, ('Portuguese', 'pt')
+ yield t, ('Quechua', 'qu')
+ yield t, ('Rhaeto-Romance', 'rm')
+ yield t, ('Romanian', 'ro')
+ yield t, ('Rundi', 'rn')
+ yield t, ('Russian', 'ru')
+ yield t, ('Samoan', 'sm')
+ yield t, ('Sangro', 'sg')
+ yield t, ('Sanskrit', 'sa')
+ yield t, ('Sardinian', 'sc')
+ yield t, ('Serbian', 'sr')
+ yield t, ('Sesotho', 'st')
+ yield t, ('Setswana', 'tn')
+ yield t, ('Shona', 'sn')
+ yield t, ('Sindhi', 'sd')
+ yield t, ('Sinhalese', 'si')
+ yield t, ('Siswati', 'ss')
+ yield t, ('Slovak', 'sk')
+ yield t, ('Slovenian', 'sl')
+ yield t, ('Somali', 'so')
+ yield t, ('Spanish', 'es')
+ yield t, ('Sundanese', 'su')
+ yield t, ('Swahili', 'sw')
+ yield t, ('Swedish', 'sv')
+ yield t, ('Tagalog', 'tl')
+ yield t, ('Tahitian', 'ty')
+ yield t, ('Tajik', 'tg')
+ yield t, ('Tamil', 'ta')
+ yield t, ('Tatar', 'tt')
+ yield t, ('Telugu', 'te')
+ yield t, ('Thai', 'th')
+ yield t, ('Tibetan', 'bo')
+ yield t, ('Tigrinya', 'ti')
+ yield t, ('Tonga', 'to')
+ yield t, ('Tsonga', 'ts')
+ yield t, ('Turkish', 'tr')
+ yield t, ('Turkmen', 'tk')
+ yield t, ('Twi', 'tw')
+ yield t, ('Ukrainian', 'uk')
+ yield t, ('Urdu', 'ur')
+ yield t, ('Uyghur', 'ug')
+ yield t, ('Uzbek', 'uz')
+ yield t, ('Vietnamese', 'vi')
+ yield t, ('Volapuk', 'vo')
+ yield t, ('Walloon', 'wa')
+ yield t, ('Welsh', 'cy')
+ yield t, ('Wolof', 'wo')
+ yield t, ('Xhosa', 'xh')
+ yield t, ('Yiddish', 'yi')
+ yield t, ('Yoruba', 'yo')
+ yield t, ('Zhuang', 'za')
+ yield t, ('Zulu', 'zu')
# TODO:
- yield x, '(Afan) Oromo', 'om'
- yield x, 'Bihari', 'bh' # "bh" is marked as collective in ISO-639-2
- yield x, 'Serbian (Latin)', 'sr_RS@latin'
- yield x, 'Serbo-Croatian', 'sh' # "sh" is deprecated in favor of "sr", "hr", "bs"
+ yield x, ('(Afan) Oromo', 'om')
+ yield x, ('Bihari', 'bh') # "bh" is marked as collective in ISO-639-2
+ yield x, ('Serbian (Latin)', 'sr_RS@latin')
+ yield x, ('Serbo-Croatian', 'sh') # "sh" is deprecated in favor of "sr", "hr", "bs"
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_misc.py
===================================================================
--- i18nspector-0.26.orig/tests/test_misc.py
+++ i18nspector-0.26/tests/test_misc.py
@@ -24,14 +24,7 @@ import stat
import tempfile
import time
-from nose.tools import (
- assert_almost_equal,
- assert_equal,
- assert_is_instance,
- assert_is_not_none,
- assert_raises,
- assert_true,
-)
+import pytest
import lib.misc as M
@@ -40,11 +33,11 @@ from . import tools
class test_unsorted:
def t(self, lst, expected):
- assert_is_instance(lst, list)
+ assert isinstance(lst, list)
r = M.unsorted(lst)
- assert_equal(r, expected)
+ assert r == expected
r = M.unsorted(x for x in lst)
- assert_equal(r, expected)
+ assert r == expected
def test_0(self):
self.t([], None)
@@ -71,7 +64,7 @@ class test_unsorted:
while True:
yield 23
r = M.unsorted(iterable())
- assert_equal(r, (37, 23))
+ assert r == (37, 23)
class test_check_sorted:
@@ -79,25 +72,24 @@ class test_check_sorted:
M.check_sorted([17, 23, 37])
def test_unsorted(self):
- with assert_raises(M.DataIntegrityError) as cm:
+ with pytest.raises(M.DataIntegrityError) as cm:
M.check_sorted([23, 37, 17])
- assert_equal(str(cm.exception), '37 > 17')
+ assert str(cm.value) == '37 > 17'
def test_sorted_vk():
lst = ['eggs', 'spam', 'ham']
d = dict(enumerate(lst))
- assert_equal(
- lst,
- list(M.sorted_vk(d))
- )
+ assert (
+ lst ==
+ list(M.sorted_vk(d)))
class test_utc_now:
def test_types(self):
now = M.utc_now()
- assert_is_instance(now, datetime.datetime)
- assert_is_not_none(now.tzinfo)
- assert_equal(now.tzinfo.utcoffset(now), datetime.timedelta(0))
+ assert isinstance(now, datetime.datetime)
+ assert now.tzinfo is not None
+ assert now.tzinfo.utcoffset(now) == datetime.timedelta(0)
@tools.fork_isolation
def test_tz_resistance(self):
@@ -108,18 +100,17 @@ class test_utc_now:
now1 = t('Etc/GMT-4')
now2 = t('Etc/GMT+2')
tdelta = (now1 - now2).total_seconds()
- assert_almost_equal(tdelta, 0, delta=0.75)
+ assert abs(tdelta - 0) <= 0.75
class test_format_range:
def t(self, x, y, max, expected): # pylint: disable=redefined-builtin
- assert_equal(
- M.format_range(range(x, y), max=max),
- expected
- )
+ assert (
+ M.format_range(range(x, y), max=max) ==
+ expected)
def test_max_is_lt_4(self):
- with assert_raises(ValueError):
+ with pytest.raises(ValueError):
self.t(5, 10, 3, None)
def test_len_lt_max(self):
@@ -139,7 +130,7 @@ def test_throwaway_tempdir():
with M.throwaway_tempdir('test'):
d = tempfile.gettempdir()
st = os.stat(d)
- assert_equal(stat.S_IMODE(st.st_mode), 0o700)
- assert_true(stat.S_ISDIR(st.st_mode))
+ assert stat.S_IMODE(st.st_mode) == 0o700
+ assert stat.S_ISDIR(st.st_mode)
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_moparser.py
===================================================================
--- i18nspector-0.26.orig/tests/test_moparser.py
+++ i18nspector-0.26/tests/test_moparser.py
@@ -20,10 +20,7 @@
import random
-from nose.tools import (
- assert_equal,
- assert_raises,
-)
+import pytest
import lib.moparser as M
@@ -38,21 +35,21 @@ def parser_for_bytes(data):
class test_magic:
def test_value(self):
- assert_equal(M.little_endian_magic, b'\xDE\x12\x04\x95')
- assert_equal(M.big_endian_magic, b'\x95\x04\x12\xDE')
+ assert M.little_endian_magic == b'\xDE\x12\x04\x95'
+ assert M.big_endian_magic == b'\x95\x04\x12\xDE'
def test_short(self):
for j in range(0, 3):
data = M.little_endian_magic[:j]
- with assert_raises(M.SyntaxError) as cm:
+ with pytest.raises(M.SyntaxError) as cm:
parser_for_bytes(data)
- assert_equal(str(cm.exception), 'unexpected magic')
+ assert str(cm.value) == 'unexpected magic'
def test_full(self):
for magic in {M.little_endian_magic, M.big_endian_magic}:
- with assert_raises(M.SyntaxError) as cm:
+ with pytest.raises(M.SyntaxError) as cm:
parser_for_bytes(magic)
- assert_equal(str(cm.exception), 'truncated file')
+ assert str(cm.value) == 'truncated file'
def test_random(self):
while True:
@@ -62,8 +59,8 @@ class test_magic:
if random_magic in {M.little_endian_magic, M.big_endian_magic}:
continue
break
- with assert_raises(M.SyntaxError) as cm:
+ with pytest.raises(M.SyntaxError) as cm:
parser_for_bytes(random_magic)
- assert_equal(str(cm.exception), 'unexpected magic')
+ assert str(cm.value) == 'unexpected magic'
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_polib4us.py
===================================================================
--- i18nspector-0.26.orig/tests/test_polib4us.py
+++ i18nspector-0.26/tests/test_polib4us.py
@@ -20,11 +20,6 @@
import polib
-from nose.tools import (
- assert_list_equal,
- assert_true,
-)
-
import lib.polib4us as M
from . import tools
@@ -50,7 +45,7 @@ msgstr "b"
file.write(s)
file.flush()
po = polib.pofile(file.name)
- assert_true(po[-1].obsolete)
+ assert po[-1].obsolete
t()
M.install_patches()
t()
@@ -60,9 +55,8 @@ def test_flag_splitting():
M.install_patches()
e = polib.POEntry()
e.flags = ['fuzzy,c-format']
- assert_list_equal(
- e.flags,
- ['fuzzy', 'c-format']
- )
+ assert (
+ e.flags ==
+ ['fuzzy', 'c-format'])
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_strformat_c.py
===================================================================
--- i18nspector-0.26.orig/tests/test_strformat_c.py
+++ i18nspector-0.26/tests/test_strformat_c.py
@@ -21,22 +21,25 @@
import os
import struct
import sys
+import unittest
import unittest.mock
-import nose
-from nose.tools import (
- assert_equal,
- assert_greater,
- assert_is_instance,
- assert_raises,
- assert_sequence_equal,
-)
+import pytest
import lib.strformat.c as M
+from . import tools
+
+
+# methods using the tools.collect_yielded decorator don't have a 'self'
+# since they end up being run before 'self' exists. pylint doesn't
+# understand this unusual situation
+# pylint: disable=no-method-argument
+
+
def test_INT_MAX():
struct.pack('=i', M.INT_MAX)
- with assert_raises(struct.error):
+ with pytest.raises(struct.error):
struct.pack('=i', M.INT_MAX + 1)
def is_glibc():
@@ -49,121 +52,134 @@ def is_glibc():
def test_NL_ARGMAX():
plat = sys.platform
if plat.startswith('linux') and is_glibc():
- assert_equal(
- M.NL_ARGMAX,
- os.sysconf('SC_NL_ARGMAX')
- )
+ assert (
+ M.NL_ARGMAX ==
+ os.sysconf('SC_NL_ARGMAX'))
else:
- raise nose.SkipTest('Test specific to Linux with glibc')
+ raise unittest.SkipTest('Test specific to Linux with glibc')
small_NL_ARGMAX = unittest.mock.patch('lib.strformat.c.NL_ARGMAX', 42)
# Setting NL_ARGMAX to a small number makes the *_index_out_of_range() tests
# much faster.
def test_lone_percent():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('%')
def test_invalid_conversion_spec():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('%!')
def test_add_argument():
fmt = M.FormatString('%s')
- with assert_raises(RuntimeError):
+ with pytest.raises(RuntimeError):
fmt.add_argument(2, None)
def test_text():
fmt = M.FormatString('eggs%dbacon%dspam')
- assert_equal(len(fmt), 5)
+ assert len(fmt) == 5
fmt = list(fmt)
- assert_equal(fmt[0], 'eggs')
- assert_equal(fmt[2], 'bacon')
- assert_equal(fmt[4], 'spam')
+ assert fmt[0] == 'eggs'
+ assert fmt[2] == 'bacon'
+ assert fmt[4] == 'spam'
class test_types:
- def t(self, s, tp, warn_type=None, integer=False):
+ @staticmethod
+ def t(s, tp, warn_type=None, integer=False):
fmt = M.FormatString(s)
[conv] = fmt
- assert_is_instance(conv, M.Conversion)
- assert_equal(conv.type, tp)
+ assert isinstance(conv, M.Conversion)
+ assert conv.type == tp
if tp == 'void':
- assert_sequence_equal(fmt.arguments, [])
+ assert fmt.arguments == []
else:
[[arg]] = fmt.arguments
- assert_equal(arg.type, tp)
+ assert arg.type == tp
if warn_type is None:
- assert_sequence_equal(fmt.warnings, [])
+ assert fmt.warnings == []
else:
[warning] = fmt.warnings
- assert_is_instance(warning, warn_type)
- assert_equal(conv.integer, integer)
+ assert isinstance(warning, warn_type)
+ assert conv.integer == integer
- def test_integer(self):
- def t(s, tp, warn_type=None):
+ @tools.collect_yielded
+ def test_integer():
+ def t(s, tp, suffix, warn_type=None):
integer = not suffix
- self.t(s, tp + suffix, warn_type, integer)
+ test_types.t(s, tp + suffix, warn_type, integer)
for c in 'din':
suffix = ''
if c == 'n':
suffix = ' *'
- yield t, ('%hh' + c), 'signed char'
- yield t, ('%h' + c), 'short int'
- yield t, ('%' + c), 'int'
- yield t, ('%l' + c), 'long int'
- yield t, ('%ll' + c), 'long long int'
- yield t, ('%L' + c), 'long long int', M.NonPortableConversion
- yield t, ('%q' + c), 'long long int', M.NonPortableConversion
- yield t, ('%j' + c), 'intmax_t'
- yield t, ('%z' + c), 'ssize_t'
- yield t, ('%Z' + c), 'ssize_t', M.NonPortableConversion
- yield t, ('%t' + c), 'ptrdiff_t'
+ yield t, (('%hh' + c), 'signed char', suffix)
+ yield t, (('%h' + c), 'short int', suffix)
+ yield t, (('%' + c), 'int', suffix)
+ yield t, (('%l' + c), 'long int', suffix)
+ yield t, (('%ll' + c), 'long long int', suffix)
+ yield t, (('%L' + c), 'long long int', suffix, M.NonPortableConversion)
+ yield t, (('%q' + c), 'long long int', suffix, M.NonPortableConversion)
+ yield t, (('%j' + c), 'intmax_t', suffix)
+ yield t, (('%z' + c), 'ssize_t', suffix)
+ yield t, (('%Z' + c), 'ssize_t', suffix, M.NonPortableConversion)
+ yield t, (('%t' + c), 'ptrdiff_t', suffix)
for c in 'ouxX':
suffix = ''
- yield t, ('%hh' + c), 'unsigned char'
- yield t, ('%h' + c), 'unsigned short int'
- yield t, ('%' + c), 'unsigned int'
- yield t, ('%l' + c), 'unsigned long int'
- yield t, ('%ll' + c), 'unsigned long long int'
- yield t, ('%L' + c), 'unsigned long long int', M.NonPortableConversion
- yield t, ('%q' + c), 'unsigned long long int', M.NonPortableConversion
- yield t, ('%j' + c), 'uintmax_t'
- yield t, ('%z' + c), 'size_t'
- yield t, ('%Z' + c), 'size_t', M.NonPortableConversion
- yield t, ('%t' + c), '[unsigned ptrdiff_t]'
+ yield t, (('%hh' + c), 'unsigned char', suffix)
+ yield t, (('%h' + c), 'unsigned short int', suffix)
+ yield t, (('%' + c), 'unsigned int', suffix)
+ yield t, (('%l' + c), 'unsigned long int', suffix)
+ yield t, (('%ll' + c), 'unsigned long long int', suffix)
+ yield t, (('%L' + c), 'unsigned long long int', suffix, M.NonPortableConversion)
+ yield t, (('%q' + c), 'unsigned long long int', suffix, M.NonPortableConversion)
+ yield t, (('%j' + c), 'uintmax_t', suffix)
+ yield t, (('%z' + c), 'size_t', suffix)
+ yield t, (('%Z' + c), 'size_t', suffix, M.NonPortableConversion)
+ yield t, (('%t' + c), '[unsigned ptrdiff_t]', suffix)
+
+ @tools.collect_yielded
+ def test_double():
+ def t(*args):
+ test_types.t(*args)
- def test_double(self):
- t = self.t
for c in 'aefgAEFG':
- yield t, ('%' + c), 'double'
- yield t, ('%l' + c), 'double', M.NonPortableConversion
- yield t, ('%L' + c), 'long double'
-
- def test_char(self):
- t = self.t
- yield t, '%c', 'char'
- yield t, '%lc', 'wint_t'
- yield t, '%C', 'wint_t', M.NonPortableConversion
- yield t, '%s', 'const char *'
- yield t, '%ls', 'const wchar_t *'
- yield t, '%S', 'const wchar_t *', M.NonPortableConversion
-
- def test_void(self):
- t = self.t
- yield t, '%p', 'void *'
- yield t, '%m', 'void'
- yield t, '%%', 'void'
+ yield t, (('%' + c), 'double')
+ yield t, (('%l' + c), 'double', M.NonPortableConversion)
+ yield t, (('%L' + c), 'long double')
+
+ @tools.collect_yielded
+ def test_char():
+ def t(*args):
+ test_types.t(*args)
+
+ yield t, ('%c', 'char')
+ yield t, ('%lc', 'wint_t')
+ yield t, ('%C', 'wint_t', M.NonPortableConversion)
+ yield t, ('%s', 'const char *')
+ yield t, ('%ls', 'const wchar_t *')
+ yield t, ('%S', 'const wchar_t *', M.NonPortableConversion)
+
+ @tools.collect_yielded
+ def test_void():
+ def t(*args):
+ test_types.t(*args)
+
+ yield t, ('%p', 'void *')
+ yield t, ('%m', 'void')
+ yield t, ('%%', 'void')
- def test_c99_macros(self):
+ @tools.collect_yielded
+ def test_c99_macros():
# pylint: disable=undefined-loop-variable
def _t(s, tp):
- return self.t(s, tp, integer=True)
+ return test_types.t(s, tp, integer=True)
def t(s, tp):
return (
_t,
- '%<{macro}>'.format(macro=s.format(c=c, n=n)),
- ('u' if unsigned else '') + tp.format(n=n)
+ (
+ '%<{macro}>'.format(macro=s.format(c=c, n=n)),
+ ('u' if unsigned else '') + tp.format(n=n)
+ )
)
# pylint: enable=undefined-loop-variable
for c in 'diouxX':
@@ -175,64 +191,71 @@ class test_types:
yield t('PRI{c}MAX', 'intmax_t')
yield t('PRI{c}PTR', 'intptr_t')
+_lengths = ['hh', 'h', 'l', 'll', 'q', 'j', 'z', 't', 'L']
+
class test_invalid_length:
- def t(self, s):
- with assert_raises(M.LengthError):
+ @staticmethod
+ def t(s):
+ with pytest.raises(M.LengthError):
M.FormatString(s)
- _lengths = ['hh', 'h', 'l', 'll', 'q', 'j', 'z', 't', 'L']
-
- def test_double(self):
- t = self.t
+ @tools.collect_yielded
+ def test_double():
+ def t(*args):
+ test_invalid_length.t(*args)
for c in 'aefgAEFG':
- for l in self._lengths:
+ for l in _lengths:
if l in 'lL':
continue
yield t, ('%' + l + c)
- def test_char(self):
- t = self.t
+ @tools.collect_yielded
+ def test_char():
+ def t(*args):
+ test_invalid_length.t(*args)
for c in 'cs':
- for l in self._lengths:
+ for l in _lengths:
if l != 'l':
yield t, '%' + l + c
yield t, ('%' + l + c.upper())
- def test_void(self):
- t = self.t
+ @tools.collect_yielded
+ def test_void():
+ def t(*args):
+ test_invalid_length.t(*args)
for c in 'pm%':
- for l in self._lengths:
+ for l in _lengths:
yield t, ('%' + l + c)
class test_numeration:
def test_percent(self):
- with assert_raises(M.ForbiddenArgumentIndex):
+ with pytest.raises(M.ForbiddenArgumentIndex):
M.FormatString('%1$%')
def test_errno(self):
# FIXME?
fmt = M.FormatString('%1$m')
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.arguments), 0)
+ assert len(fmt) == 1
+ assert len(fmt.arguments) == 0
def test_swapped(self):
fmt = M.FormatString('%2$s%1$d')
- assert_equal(len(fmt), 2)
+ assert len(fmt) == 2
[a1], [a2] = fmt.arguments
- assert_equal(a1.type, 'int')
- assert_equal(a2.type, 'const char *')
+ assert a1.type == 'int'
+ assert a2.type == 'const char *'
def test_numbering_mixture(self):
def t(s):
- with assert_raises(M.ArgumentNumberingMixture):
+ with pytest.raises(M.ArgumentNumberingMixture):
M.FormatString(s)
t('%s%2$s')
t('%2$s%s')
@small_NL_ARGMAX
def test_index_out_of_range(self):
- with assert_raises(M.ArgumentRangeError):
+ with pytest.raises(M.ArgumentRangeError):
M.FormatString('%0$d')
def fs(n):
s = ''.join(
@@ -241,17 +264,17 @@ class test_numeration:
)
return M.FormatString(s)
fmt = fs(M.NL_ARGMAX)
- assert_equal(len(fmt), M.NL_ARGMAX)
- assert_equal(len(fmt.arguments), M.NL_ARGMAX)
- with assert_raises(M.ArgumentRangeError):
+ assert len(fmt) == M.NL_ARGMAX
+ assert len(fmt.arguments) == M.NL_ARGMAX
+ with pytest.raises(M.ArgumentRangeError):
fs(M.NL_ARGMAX + 1)
def test_initial_gap(self):
- with assert_raises(M.MissingArgument):
+ with pytest.raises(M.MissingArgument):
M.FormatString('%2$d')
def test_gap(self):
- with assert_raises(M.MissingArgument):
+ with pytest.raises(M.MissingArgument):
M.FormatString('%3$d%1$d')
class test_redundant_flag:
@@ -259,7 +282,7 @@ class test_redundant_flag:
def t(self, s):
fmt = M.FormatString(s)
[exc] = fmt.warnings
- assert_is_instance(exc, M.RedundantFlag)
+ assert isinstance(exc, M.RedundantFlag)
def test_duplicate(self):
self.t('%--17d')
@@ -274,87 +297,114 @@ class test_redundant_flag:
class test_expected_flag:
- def t(self, s):
+ @staticmethod
+ def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
- def test_hash(self):
+ @tools.collect_yielded
+ def test_hash():
+ def t(*args):
+ test_expected_flag.t(*args)
for c in 'oxXaAeEfFgG':
- yield self.t, ('%#' + c)
+ yield t, ('%#' + c)
- def test_zero(self):
+ @tools.collect_yielded
+ def test_zero():
+ def t(*args):
+ test_expected_flag.t(*args)
for c in 'diouxXaAeEfFgG':
- yield self.t, ('%0' + c)
+ yield t, ('%0' + c)
- def test_apos(self):
+ @tools.collect_yielded
+ def test_apos():
+ def t(*args):
+ test_expected_flag.t(*args)
for c in 'diufFgG':
- yield self.t, ("%'" + c)
+ yield t, ("%'" + c)
- def test_other(self):
+ @tools.collect_yielded
+ def test_other():
+ def t(*args):
+ test_expected_flag.t(*args)
for flag in '- +I':
for c in 'diouxXaAeEfFgGcCsSpm':
- yield self.t, ('%' + flag + c)
+ yield t, ('%' + flag + c)
class test_unexpected_flag:
- def t(self, s):
- with assert_raises(M.FlagError):
+ @staticmethod
+ def t(s):
+ with pytest.raises(M.FlagError):
M.FormatString(s)
- def test_hash(self):
+ @tools.collect_yielded
+ def test_hash():
+ def t(*args):
+ test_unexpected_flag.t(*args)
for c in 'dicCsSnpm%':
- yield self.t, ('%#' + c)
+ yield t, ('%#' + c)
- def test_zero(self):
+ @tools.collect_yielded
+ def test_zero():
+ def t(*args):
+ test_unexpected_flag.t(*args)
for c in 'cCsSnpm%':
- yield self.t, ('%0' + c)
+ yield t, ('%0' + c)
- def test_apos(self):
+ @tools.collect_yielded
+ def test_apos():
+ def t(*args):
+ test_unexpected_flag.t(*args)
for c in 'oxXaAeEcCsSnpm%':
- yield self.t, ("%'" + c)
+ yield t, ("%'" + c)
- def test_other(self):
+ @tools.collect_yielded
+ def test_other():
+ def t(*args):
+ test_unexpected_flag.t(*args)
for c in '%n':
for flag in '- +I':
- yield self.t, ('%' + flag + c)
+ yield t, ('%' + flag + c)
class test_width:
- def test_ok(self):
+ @tools.collect_yielded
+ def test_ok():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
for c in 'diouxXaAeEfFgGcCsSp':
yield t, ('%1' + c)
yield t, '%1m' # FIXME?
def test_invalid(self):
for c in '%n':
- with assert_raises(M.WidthError):
+ with pytest.raises(M.WidthError):
M.FormatString('%1' + c)
def test_too_large(self):
fmt = M.FormatString('%{0}d'.format(M.INT_MAX))
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.arguments), 1)
- with assert_raises(M.WidthRangeError):
+ assert len(fmt) == 1
+ assert len(fmt.arguments) == 1
+ with pytest.raises(M.WidthRangeError):
M.FormatString('%{0}d'.format(M.INT_MAX + 1))
def test_variable(self):
fmt = M.FormatString('%*s')
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.arguments), 2)
+ assert len(fmt) == 1
+ assert len(fmt.arguments) == 2
[a1], [a2] = fmt.arguments
- assert_equal(a1.type, 'int')
- assert_equal(a2.type, 'const char *')
+ assert a1.type == 'int'
+ assert a2.type == 'const char *'
def _test_index(self, i):
fmt = M.FormatString('%2$*{0}$s'.format(i))
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.arguments), 2)
+ assert len(fmt) == 1
+ assert len(fmt.arguments) == 2
[a1], [a2] = fmt.arguments
- assert_equal(a1.type, 'int')
- assert_equal(a2.type, 'const char *')
+ assert a1.type == 'int'
+ assert a2.type == 'const char *'
def test_index(self):
self._test_index(1)
@@ -365,7 +415,7 @@ class test_width:
@small_NL_ARGMAX
def test_index_out_of_range(self):
- with assert_raises(M.ArgumentRangeError):
+ with pytest.raises(M.ArgumentRangeError):
M.FormatString('%1$*0$s')
def fs(n):
s = ''.join(
@@ -374,14 +424,14 @@ class test_width:
) + '%1$*{0}$s'.format(n)
return M.FormatString(s)
fmt = fs(M.NL_ARGMAX)
- assert_equal(len(fmt), M.NL_ARGMAX - 1)
- assert_equal(len(fmt.arguments), M.NL_ARGMAX)
- with assert_raises(M.ArgumentRangeError):
+ assert len(fmt) == M.NL_ARGMAX - 1
+ assert len(fmt.arguments) == M.NL_ARGMAX
+ with pytest.raises(M.ArgumentRangeError):
fs(M.NL_ARGMAX + 1)
def test_numbering_mixture(self):
def t(s):
- with assert_raises(M.ArgumentNumberingMixture):
+ with pytest.raises(M.ArgumentNumberingMixture):
M.FormatString(s)
t('%1$*s')
t('%*1$s')
@@ -390,58 +440,62 @@ class test_width:
class test_precision:
- def test_ok(self):
+ @tools.collect_yielded
+ def test_ok():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
for c in 'diouxXaAeEfFgGsS':
yield t, ('%.1' + c)
- def test_redundant_0(self):
+ @tools.collect_yielded
+ def test_redundant_0():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
[warning] = fmt.warnings
- assert_is_instance(warning, M.RedundantFlag)
+ assert isinstance(warning, M.RedundantFlag)
for c in 'diouxX':
yield t, ('%0.1' + c)
- def test_non_redundant_0(self):
+ @tools.collect_yielded
+ def test_non_redundant_0():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
- assert_sequence_equal(fmt.warnings, [])
+ assert len(fmt) == 1
+ assert fmt.warnings == []
for c in 'aAeEfFgG':
yield t, ('%0.1' + c)
- def test_unexpected(self):
+ @tools.collect_yielded
+ def test_unexpected():
def t(s):
- with assert_raises(M.PrecisionError):
+ with pytest.raises(M.PrecisionError):
M.FormatString(s)
for c in 'cCpnm%':
yield t, ('%.1' + c)
def test_too_large(self):
fmt = M.FormatString('%.{0}f'.format(M.INT_MAX))
- assert_equal(len(fmt), 1)
- with assert_raises(M.PrecisionRangeError):
+ assert len(fmt) == 1
+ with pytest.raises(M.PrecisionRangeError):
M.FormatString('%.{0}f'.format(M.INT_MAX + 1))
def test_variable(self):
fmt = M.FormatString('%.*f')
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.arguments), 2)
+ assert len(fmt) == 1
+ assert len(fmt.arguments) == 2
[a1], [a2] = fmt.arguments
- assert_equal(a1.type, 'int')
- assert_equal(a2.type, 'double')
+ assert a1.type == 'int'
+ assert a2.type == 'double'
def _test_index(self, i):
fmt = M.FormatString('%2$.*{0}$f'.format(i))
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.arguments), 2)
+ assert len(fmt) == 1
+ assert len(fmt.arguments) == 2
[a1], [a2] = fmt.arguments
- assert_equal(a1.type, 'int')
- assert_equal(a2.type, 'double')
+ assert a1.type == 'int'
+ assert a2.type == 'double'
def test_index(self):
self._test_index(1)
@@ -452,7 +506,7 @@ class test_precision:
@small_NL_ARGMAX
def test_index_out_of_range(self):
- with assert_raises(M.ArgumentRangeError):
+ with pytest.raises(M.ArgumentRangeError):
M.FormatString('%1$.*0$f')
def fs(n):
s = ''.join(
@@ -461,14 +515,14 @@ class test_precision:
) + '%1$.*{0}$f'.format(n)
return M.FormatString(s)
fmt = fs(M.NL_ARGMAX)
- assert_equal(len(fmt), M.NL_ARGMAX - 1)
- assert_equal(len(fmt.arguments), M.NL_ARGMAX)
- with assert_raises(M.ArgumentRangeError):
+ assert len(fmt) == M.NL_ARGMAX - 1
+ assert len(fmt.arguments) == M.NL_ARGMAX
+ with pytest.raises(M.ArgumentRangeError):
fs(M.NL_ARGMAX + 1)
def test_numbering_mixture(self):
def t(s):
- with assert_raises(M.ArgumentNumberingMixture):
+ with pytest.raises(M.ArgumentNumberingMixture):
M.FormatString(s)
t('%1$.*f')
t('%.*1$f')
@@ -481,15 +535,15 @@ class test_type_compatibility:
def t(s, tp):
fmt = M.FormatString(s)
[args] = fmt.arguments
- assert_greater(len(args), 1)
+ assert len(args) > 1
for arg in args:
- assert_equal(arg.type, tp)
+ assert arg.type == tp
t('%1$d%1$d', 'int')
t('%1$d%1$i', 'int')
def test_mismatch(self):
def t(s):
- with assert_raises(M.ArgumentTypeMismatch):
+ with pytest.raises(M.ArgumentTypeMismatch):
M.FormatString(s)
t('%1$d%1$hd')
t('%1$d%1$u')
@@ -498,11 +552,11 @@ class test_type_compatibility:
@small_NL_ARGMAX
def test_too_many_conversions():
def t(s):
- with assert_raises(M.ArgumentRangeError):
+ with pytest.raises(M.ArgumentRangeError):
M.FormatString(s)
s = M.NL_ARGMAX * '%d'
fmt = M.FormatString(s)
- assert_equal(len(fmt), M.NL_ARGMAX)
+ assert len(fmt) == M.NL_ARGMAX
t(s + '%f')
t(s + '%*f')
t(s + '%.*f')
@@ -512,7 +566,7 @@ class test_get_last_integer_conversion:
def test_overflow(self):
fmt = M.FormatString('%s%d')
for n in [-1, 0, 3]:
- with assert_raises(IndexError):
+ with pytest.raises(IndexError):
fmt.get_last_integer_conversion(n=n)
def t(self, s, n, tp=M.Conversion):
@@ -520,7 +574,7 @@ class test_get_last_integer_conversion:
conv = fmt.get_last_integer_conversion(n=n)
if tp is None:
tp = type(tp)
- assert_is_instance(conv, tp)
+ assert isinstance(conv, tp)
return conv
def test_okay(self):
Index: i18nspector-0.26/tests/test_strformat_perlbrace.py
===================================================================
--- i18nspector-0.26.orig/tests/test_strformat_perlbrace.py
+++ i18nspector-0.26/tests/test_strformat_perlbrace.py
@@ -18,40 +18,37 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-from nose.tools import (
- assert_equal,
- assert_raises,
-)
+import pytest
import lib.strformat.perlbrace as M
def test_lone_lcb():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('{')
def test_lone_rcb():
M.FormatString('}')
def test_invalid_field():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('{@}')
def test_text():
fmt = M.FormatString('bacon')
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
[fld] = fmt
- assert_equal(fld, 'bacon')
+ assert fld == 'bacon'
class test_named_arguments:
def test_good(self):
fmt = M.FormatString('{spam}')
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
[fld] = fmt
- assert_equal(fld, '{spam}')
+ assert fld == '{spam}'
def test_bad(self):
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('{3ggs}')
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_strformat_pybrace.py
===================================================================
--- i18nspector-0.26.orig/tests/test_strformat_pybrace.py
+++ i18nspector-0.26/tests/test_strformat_pybrace.py
@@ -21,18 +21,13 @@
import struct
import unittest.mock
-from nose.tools import (
- assert_equal,
- assert_is,
- assert_is_instance,
- assert_raises,
-)
+import pytest
import lib.strformat.pybrace as M
def test_SSIZE_MAX():
struct.pack('=i', M.SSIZE_MAX)
- with assert_raises(struct.error):
+ with pytest.raises(struct.error):
struct.pack('=i', M.SSIZE_MAX + 1)
small_SSIZE_MAX = unittest.mock.patch('lib.strformat.pybrace.SSIZE_MAX', 42)
@@ -40,31 +35,31 @@ small_SSIZE_MAX = unittest.mock.patch('l
# a very large number of arguments without running out of memory.
def test_lone_lcb():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('{')
def test_lone_rcb():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('}')
def test_invalid_field():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('{@}')
def test_add_argument():
fmt = M.FormatString('{}')
- with assert_raises(RuntimeError):
+ with pytest.raises(RuntimeError):
fmt.add_argument(None, None)
- with assert_raises(RuntimeError):
+ with pytest.raises(RuntimeError):
fmt.add_argument('eggs', None)
def test_text():
fmt = M.FormatString('eggs{}bacon{}spam')
- assert_equal(len(fmt), 5)
+ assert len(fmt) == 5
fmt = list(fmt)
- assert_equal(fmt[0], 'eggs')
- assert_equal(fmt[2], 'bacon')
- assert_equal(fmt[4], 'spam')
+ assert fmt[0] == 'eggs'
+ assert fmt[2] == 'bacon'
+ assert fmt[4] == 'spam'
class test_types:
@@ -72,12 +67,12 @@ class test_types:
types = frozenset(tp.__name__ for tp in types)
fmt = M.FormatString('{:' + k + '}')
[fld] = fmt
- assert_is_instance(fld, M.Field)
- assert_equal(fld.types, types)
- assert_equal(len(fmt.argument_map), 1)
+ assert isinstance(fld, M.Field)
+ assert fld.types == types
+ assert len(fmt.argument_map) == 1
[(key, [afld])] = fmt.argument_map.items()
- assert_equal(key, 0)
- assert_is(fld, afld)
+ assert key == 0
+ assert fld is afld
def test_default(self):
self.t('', int, float, str)
@@ -102,12 +97,12 @@ class test_conversion:
types = frozenset(tp.__name__ for tp in types)
fmt = M.FormatString('{!' + c + ':' + k + '}')
[fld] = fmt
- assert_is_instance(fld, M.Field)
- assert_equal(fld.types, types)
- assert_equal(len(fmt.argument_map), 1)
+ assert isinstance(fld, M.Field)
+ assert fld.types == types
+ assert len(fmt.argument_map) == 1
[(key, [afld])] = fmt.argument_map.items()
- assert_equal(key, 0)
- assert_is(fld, afld)
+ assert key == 0
+ assert fld is afld
def test_default(self):
for c in 'sra':
@@ -120,11 +115,11 @@ class test_conversion:
def test_numeric(self):
for c in 'sra':
for k in 'bcdoxXneEfFgG':
- with assert_raises(M.FormatTypeMismatch):
+ with pytest.raises(M.FormatTypeMismatch):
self.t(c, k, int)
def test_bad(self):
- with assert_raises(M.ConversionError):
+ with pytest.raises(M.ConversionError):
self.t('z', '')
class test_numbered_arguments:
@@ -134,12 +129,12 @@ class test_numbered_arguments:
def t(self, s, *types):
fmt = M.FormatString(s)
- assert_equal(len(fmt), len(types))
- assert_equal(len(fmt.argument_map), len(types))
+ assert len(fmt) == len(types)
+ assert len(fmt.argument_map) == len(types)
for (key, args), (xkey, xtype) in zip(sorted(fmt.argument_map.items()), enumerate(types)):
[arg] = args
- assert_equal(key, xkey)
- assert_equal(arg.types, frozenset({xtype.__name__}))
+ assert key == xkey
+ assert arg.types == frozenset({xtype.__name__})
def test_unnumbered(self):
self.t('{:d}{:f}', int, float)
@@ -151,9 +146,9 @@ class test_numbered_arguments:
self.t('{1:d}{0:f}', float, int)
def test_mixed(self):
- with assert_raises(M.ArgumentNumberingMixture):
+ with pytest.raises(M.ArgumentNumberingMixture):
self.t('{0:d}{:f}')
- with assert_raises(M.ArgumentNumberingMixture):
+ with pytest.raises(M.ArgumentNumberingMixture):
self.t('{:d}{0:f}')
def test_numbered_out_of_range(self):
@@ -161,7 +156,7 @@ class test_numbered_arguments:
s = ('{' + str(i) + '}')
M.FormatString(s)
t(M.SSIZE_MAX)
- with assert_raises(M.ArgumentRangeError):
+ with pytest.raises(M.ArgumentRangeError):
t(M.SSIZE_MAX + 1)
@small_SSIZE_MAX
@@ -170,7 +165,7 @@ class test_numbered_arguments:
s = '{}' * i
M.FormatString(s)
t(M.SSIZE_MAX + 1)
- with assert_raises(M.ArgumentRangeError):
+ with pytest.raises(M.ArgumentRangeError):
t(M.SSIZE_MAX + 2)
class test_named_arguments:
@@ -179,21 +174,21 @@ class test_named_arguments:
fmt = M.FormatString('{spam}')
[fld] = fmt
[(aname, [afld])] = fmt.argument_map.items()
- assert_equal(aname, 'spam')
- assert_is(fld, afld)
+ assert aname == 'spam'
+ assert fld is afld
def test_bad(self):
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('{3ggs}')
class test_format_spec:
def test_bad_char(self):
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('{:@}')
def test_bad_letter(self):
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('{:Z}')
def test_comma(self):
@@ -203,7 +198,7 @@ class test_format_spec:
for k in 'bcdoxXeEfFgG':
t(k)
for k in 'ns':
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
t(k)
def test_alt_sign(self):
@@ -213,7 +208,7 @@ class test_format_spec:
t(c, '')
for k in 'bcdoxXneEfFgG':
t(c, k)
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
t(c, 's')
def test_align(self):
@@ -228,7 +223,7 @@ class test_format_spec:
t(c, '')
for k in 'bcdoxXneEfFgG':
t(c, k)
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
t(c, 's')
def test_width(self):
@@ -239,7 +234,7 @@ class test_format_spec:
for k in 'bcdoxXneEfFgGs\0':
for i in 4, 37, M.SSIZE_MAX:
t(i, k)
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
t(M.SSIZE_MAX + 1, k)
def test_precision(self):
@@ -250,11 +245,11 @@ class test_format_spec:
for k in 'neEfFgGs\0':
for i in {4, 37, M.SSIZE_MAX}:
t(i, k)
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
t(M.SSIZE_MAX + 1, k)
for k in 'bcdoxX':
for i in {4, 37, M.SSIZE_MAX, M.SSIZE_MAX + 1}:
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
t(i, k)
def test_type_compat(self):
@@ -262,7 +257,7 @@ class test_format_spec:
s = '{0:' + k1 + '}{0:' + k2 + '}'
M.FormatString(s)
def e(k1, k2):
- with assert_raises(M.ArgumentTypeMismatch):
+ with pytest.raises(M.ArgumentTypeMismatch):
t(k1, k2)
ks = 'bcdoxXneEfFgGs'
compat = [
@@ -291,13 +286,13 @@ class test_format_spec:
s = '{' + str(v) + ':{' + str(f) + '}}'
return M.FormatString(s)
fmt = t()
- assert_equal(len(fmt.argument_map), 2)
+ assert len(fmt.argument_map) == 2
t(v=0, f=M.SSIZE_MAX)
- with assert_raises(M.ArgumentRangeError):
+ with pytest.raises(M.ArgumentRangeError):
t(v=0, f=(M.SSIZE_MAX + 1))
- with assert_raises(M.ArgumentNumberingMixture):
+ with pytest.raises(M.ArgumentNumberingMixture):
t(v=0)
- with assert_raises(M.ArgumentNumberingMixture):
+ with pytest.raises(M.ArgumentNumberingMixture):
t(f=0)
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_strformat_python.py
===================================================================
--- i18nspector-0.26.orig/tests/test_strformat_python.py
+++ i18nspector-0.26/tests/test_strformat_python.py
@@ -20,53 +20,55 @@
import struct
-from nose.tools import (
- assert_equal,
- assert_greater,
- assert_is_instance,
- assert_raises,
- assert_sequence_equal,
-)
+import pytest
import lib.strformat.python as M
+from . import tools
+
+
+# methods using the tools.collect_yielded decorator don't have a 'self'
+# since they end up being run before 'self' exists. pylint doesn't
+# understand this unusual situation
+# pylint: disable=no-method-argument
+
def test_SSIZE_MAX():
struct.pack('=i', M.SSIZE_MAX)
- with assert_raises(struct.error):
+ with pytest.raises(struct.error):
struct.pack('=i', M.SSIZE_MAX + 1)
def test_lone_percent():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('%')
def test_invalid_conversion_spec():
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
M.FormatString('%!')
def test_add_argument():
fmt = M.FormatString('%s')
- with assert_raises(RuntimeError):
+ with pytest.raises(RuntimeError):
fmt.add_argument(None, None)
- with assert_raises(RuntimeError):
+ with pytest.raises(RuntimeError):
fmt.add_argument('eggs', None)
def test_text():
fmt = M.FormatString('eggs%dbacon%dspam')
- assert_equal(len(fmt), 5)
+ assert len(fmt) == 5
fmt = list(fmt)
- assert_equal(fmt[0], 'eggs')
- assert_equal(fmt[2], 'bacon')
- assert_equal(fmt[4], 'spam')
+ assert fmt[0] == 'eggs'
+ assert fmt[2] == 'bacon'
+ assert fmt[4] == 'spam'
class test_map:
def t(self, key):
s = '%(' + key + ')s'
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
- assert_sequence_equal(fmt.seq_arguments, [])
+ assert len(fmt) == 1
+ assert fmt.seq_arguments == []
[pkey] = fmt.map_arguments.keys()
- assert_equal(key, pkey)
+ assert key == pkey
def test_simple(self):
self.t('eggs')
@@ -75,69 +77,82 @@ class test_map:
self.t('eggs(ham)spam')
def test_unbalanced_parens(self):
- with assert_raises(M.Error):
+ with pytest.raises(M.Error):
self.t('eggs(ham')
class test_types:
- def t(self, s, tp, warn_type=None):
+ @staticmethod
+ def t( s, tp, warn_type=None):
fmt = M.FormatString(s)
[conv] = fmt
- assert_is_instance(conv, M.Conversion)
- assert_equal(conv.type, tp)
- assert_equal(len(fmt.map_arguments), 0)
+ assert isinstance(conv, M.Conversion)
+ assert conv.type == tp
+ assert len(fmt.map_arguments) == 0
if tp == 'None':
- assert_sequence_equal(fmt.seq_arguments, [])
+ assert fmt.seq_arguments == []
else:
[arg] = fmt.seq_arguments
- assert_equal(arg.type, tp)
+ assert arg.type == tp
if warn_type is None:
- assert_equal(len(fmt.warnings), 0)
+ assert len(fmt.warnings) == 0
else:
[warning] = fmt.warnings
- assert_is_instance(warning, warn_type)
+ assert isinstance(warning, warn_type)
- def test_integer(self):
- t = self.t
+ @tools.collect_yielded
+ def test_integer():
+ def t(*args):
+ test_types.t(*args)
for c in 'oxXdi':
- yield t, '%' + c, 'int'
- yield t, '%u', 'int', M.ObsoleteConversion
+ yield t, ('%' + c, 'int')
+ yield t, ('%u', 'int', M.ObsoleteConversion)
- def test_float(self):
- t = self.t
+ @tools.collect_yielded
+ def test_float():
+ def t(*args):
+ test_types.t(*args)
for c in 'eEfFgG':
- yield t, '%' + c, 'float'
-
- def test_str(self):
- t = self.t
- yield t, '%c', 'chr'
- yield t, '%s', 'str'
+ yield t, ('%' + c, 'float')
- def test_repr(self):
- t = self.t
+ @tools.collect_yielded
+ def test_str():
+ def t(*args):
+ test_types.t(*args)
+ yield t, ('%c', 'chr')
+ yield t, ('%s', 'str')
+
+ @tools.collect_yielded
+ def test_repr():
+ def t(*args):
+ test_types.t(*args)
for c in 'ra':
- yield t, '%' + c, 'object'
+ yield t, ('%' + c, 'object')
- def test_void(self):
- yield self.t, '%%', 'None'
+ @tools.collect_yielded
+ def test_void():
+ def t(*args):
+ test_types.t(*args)
+ yield t, ('%%', 'None')
+@tools.collect_yielded
def test_length():
def t(l):
fmt = M.FormatString('%' + l + 'd')
[warning] = fmt.warnings
- assert_is_instance(warning, M.RedundantLength)
+ assert isinstance(warning, M.RedundantLength)
for l in 'hlL':
yield t, l
class test_indexing:
def test_percent(self):
- with assert_raises(M.ForbiddenArgumentKey):
+ with pytest.raises(M.ForbiddenArgumentKey):
M.FormatString('%(eggs)%')
def test_indexing_mixture(self):
def t(s):
- with assert_raises(M.ArgumentIndexingMixture):
+ with pytest.raises(M.ArgumentIndexingMixture):
M.FormatString(s)
t('%s%(eggs)s')
t('%(eggs)s%s')
@@ -149,7 +164,7 @@ class test_multiple_flags:
def t(self, s):
fmt = M.FormatString(s)
[exc] = fmt.warnings
- assert_is_instance(exc, M.RedundantFlag)
+ assert isinstance(exc, M.RedundantFlag)
def test_duplicate(self):
self.t('%--17d')
@@ -160,108 +175,114 @@ class test_multiple_flags:
def test_plus_space(self):
self.t('%+ d')
+@tools.collect_yielded
def test_single_flag():
def t(s, expected):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
if expected:
- assert_sequence_equal(fmt.warnings, [])
+ assert fmt.warnings == []
else:
[exc] = fmt.warnings
- assert_is_instance(exc, M.RedundantFlag)
+ assert isinstance(exc, M.RedundantFlag)
for c in 'dioxXeEfFgGcrsa%':
- yield t, ('%#' + c), (c in 'oxXeEfFgG')
+ yield t, (('%#' + c), (c in 'oxXeEfFgG'))
for flag in '0 +':
- yield t, ('%' + flag + c), (c in 'dioxXeEfFgG')
- yield t, ('%-' + c), True
+ yield t, (('%' + flag + c), (c in 'dioxXeEfFgG'))
+ yield t, (('%-' + c), True)
class test_width:
- def test_ok(self):
+ @tools.collect_yielded
+ def test_ok():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
- assert_sequence_equal(fmt.warnings, [])
+ assert len(fmt) == 1
+ assert fmt.warnings == []
for c in 'dioxXeEfFgGcrsa%':
yield t, ('%1' + c)
def test_too_large(self):
fmt = M.FormatString('%{0}d'.format(M.SSIZE_MAX))
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.seq_arguments), 1)
- assert_equal(len(fmt.map_arguments), 0)
- with assert_raises(M.WidthRangeError):
+ assert len(fmt) == 1
+ assert len(fmt.seq_arguments) == 1
+ assert len(fmt.map_arguments) == 0
+ with pytest.raises(M.WidthRangeError):
M.FormatString('%{0}d'.format(M.SSIZE_MAX + 1))
def test_variable(self):
fmt = M.FormatString('%*s')
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.map_arguments), 0)
+ assert len(fmt) == 1
+ assert len(fmt.map_arguments) == 0
[a1, a2] = fmt.seq_arguments
- assert_equal(a1.type, 'int')
- assert_equal(a2.type, 'str')
+ assert a1.type == 'int'
+ assert a2.type == 'str'
def test_indexing_mixture(self):
def t(s):
- with assert_raises(M.ArgumentIndexingMixture):
+ with pytest.raises(M.ArgumentIndexingMixture):
M.FormatString(s)
t('%*s%(eggs)s')
t('%(eggs)s%*s')
class test_precision:
- def test_ok(self):
+ @tools.collect_yielded
+ def test_ok():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
for c in 'dioxXeEfFgGrsa':
yield t, ('%.1' + c)
- def test_redundant_0(self):
+ @tools.collect_yielded
+ def test_redundant_0():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
[warning] = fmt.warnings
- assert_is_instance(warning, M.RedundantFlag)
+ assert isinstance(warning, M.RedundantFlag)
for c in 'dioxX':
yield t, ('%0.1' + c)
- def test_non_redundant_0(self):
+ @tools.collect_yielded
+ def test_non_redundant_0():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
- assert_sequence_equal(fmt.warnings, [])
+ assert len(fmt) == 1
+ assert fmt.warnings == []
for c in 'eEfFgG':
yield t, ('%0.1' + c)
- def test_unexpected(self):
+ @tools.collect_yielded
+ def test_unexpected():
def t(s):
fmt = M.FormatString(s)
- assert_equal(len(fmt), 1)
+ assert len(fmt) == 1
[warning] = fmt.warnings
- assert_is_instance(warning, M.RedundantPrecision)
+ assert isinstance(warning, M.RedundantPrecision)
for c in 'c%':
yield t, ('%.1' + c)
def test_too_large(self):
fmt = M.FormatString('%.{0}f'.format(M.SSIZE_MAX))
- assert_equal(len(fmt), 1)
- with assert_raises(M.PrecisionRangeError):
+ assert len(fmt) == 1
+ with pytest.raises(M.PrecisionRangeError):
M.FormatString('%.{0}f'.format(M.SSIZE_MAX + 1))
def test_variable(self):
fmt = M.FormatString('%.*f')
- assert_equal(len(fmt), 1)
- assert_equal(len(fmt.map_arguments), 0)
+ assert len(fmt) == 1
+ assert len(fmt.map_arguments) == 0
[a1, a2] = fmt.seq_arguments
- assert_equal(a1.type, 'int')
- assert_equal(a2.type, 'float')
+ assert a1.type == 'int'
+ assert a2.type == 'float'
def test_indexing_mixture(self):
def t(s):
- with assert_raises(M.ArgumentIndexingMixture):
+ with pytest.raises(M.ArgumentIndexingMixture):
M.FormatString(s)
t('%.*f%(eggs)f')
t('%(eggs)f%.*f')
@@ -271,26 +292,26 @@ class test_type_compatibility:
def test_okay(self):
def t(s, tp):
fmt = M.FormatString(s)
- assert_equal(len(fmt.seq_arguments), 0)
+ assert len(fmt.seq_arguments) == 0
[args] = fmt.map_arguments.values()
- assert_greater(len(args), 1)
+ assert len(args) > 1
for arg in args:
- assert_equal(arg.type, tp)
+ assert arg.type == tp
t('%(eggs)d%(eggs)d', 'int')
t('%(eggs)d%(eggs)i', 'int')
def test_mismatch(self):
def t(s):
- with assert_raises(M.ArgumentTypeMismatch):
+ with pytest.raises(M.ArgumentTypeMismatch):
M.FormatString(s)
t('%(eggs)d%(eggs)s')
def test_seq_conversions():
def t(s, n):
fmt = M.FormatString(s)
- assert_equal(len(fmt.seq_conversions), n)
+ assert len(fmt.seq_conversions) == n
for arg in fmt.seq_conversions:
- assert_is_instance(arg, M.Conversion)
+ assert isinstance(arg, M.Conversion)
t('%d', 1)
t('%d%d', 2)
t('eggs%dham', 1)
Index: i18nspector-0.26/tests/test_tags.py
===================================================================
--- i18nspector-0.26.orig/tests/test_tags.py
+++ i18nspector-0.26/tests/test_tags.py
@@ -24,26 +24,20 @@ import inspect
import operator
import pkgutil
-from nose.tools import (
- assert_equal,
- assert_false,
- assert_is_instance,
- assert_raises,
- assert_true,
-)
+import pytest
import lib.check
import lib.tags as M
+from . import tools
class test_escape:
def t(self, s, expected):
result = M.safe_format('{}', s)
- assert_is_instance(result, M.safestr)
- assert_equal(
- result,
- expected
- )
+ assert isinstance(result, M.safestr)
+ assert (
+ result ==
+ expected)
def test_safe(self):
s = 'fox'
@@ -75,6 +69,7 @@ def ast_to_tagnames(node):
if ok:
yield node.args[0].s
+@tools.collect_yielded
def test_consistency():
source_tagnames = set()
def visit_mod(modname):
@@ -117,13 +112,13 @@ class test_enums:
for op in operators:
for i, x in enumerate(keys):
for j, y in enumerate(keys):
- assert_equal(op(x, y), op(i, j))
+ assert op(x, y) == op(i, j)
if op is operator.eq:
- assert_false(op(x, j))
+ assert not op(x, j)
elif op is operator.ne:
- assert_true(op(x, j))
+ assert op(x, j)
else:
- with assert_raises(TypeError):
+ with pytest.raises(TypeError):
op(x, j)
def test_severities(self):
Index: i18nspector-0.26/tests/test_terminal.py
===================================================================
--- i18nspector-0.26.orig/tests/test_terminal.py
+++ i18nspector-0.26/tests/test_terminal.py
@@ -23,17 +23,13 @@ import os
import pty
import sys
-from nose.tools import (
- assert_equal,
-)
-
import lib.terminal as T
from . import tools
def test_strip_delay():
def t(s, r=b''):
- assert_equal(T._strip_delay(s), r) # pylint: disable=protected-access
+ assert T._strip_delay(s) == r # pylint: disable=protected-access
t(b'$<1>')
t(b'$<2/>')
t(b'$<3*>')
@@ -56,7 +52,7 @@ def assert_tseq_equal(s, expected):
# but not their subclasses. We don't want detailed comparisons,
# because diff could contain control characters.
pass
- assert_equal(S(expected), S(s))
+ assert S(expected) == S(s)
def test_dummy():
t = assert_tseq_equal
Index: i18nspector-0.26/tests/test_version.py
===================================================================
--- i18nspector-0.26.orig/tests/test_version.py
+++ i18nspector-0.26/tests/test_version.py
@@ -20,10 +20,6 @@
import os
-from nose.tools import (
- assert_equal,
-)
-
from lib.cli import __version__
here = os.path.dirname(__file__)
@@ -34,7 +30,7 @@ def test_changelog():
with open(path, 'rt', encoding='UTF-8') as file:
line = file.readline()
changelog_version = line.split()[1].strip('()')
- assert_equal(changelog_version, __version__)
+ assert changelog_version == __version__
def test_manpage():
path = os.path.join(docdir, 'manpage.rst')
@@ -44,6 +40,6 @@ def test_manpage():
if line.startswith(':version:'):
manpage_version = line.split()[-1]
break
- assert_equal(manpage_version, __version__)
+ assert manpage_version == __version__
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/test_xml.py
===================================================================
--- i18nspector-0.26.orig/tests/test_xml.py
+++ i18nspector-0.26/tests/test_xml.py
@@ -21,11 +21,7 @@
import re
import xml.etree.ElementTree as etree
-from nose.tools import (
- assert_is_none,
- assert_is_not_none,
- assert_raises,
-)
+import pytest
import lib.xml as M
@@ -44,7 +40,7 @@ class test_well_formed:
class test_malformed:
def t(self, s):
- with assert_raises(M.SyntaxError):
+ with pytest.raises(M.SyntaxError):
M.check_fragment(s)
def test_non_xml_character(self):
@@ -73,7 +69,7 @@ class test_name_re():
def test_good(self):
def t(s):
match = self.regexp.match(s)
- assert_is_not_none(match)
+ assert match is not None
t(':')
t('_')
t('e')
@@ -85,7 +81,7 @@ class test_name_re():
def test_bad(self):
def t(s):
match = self.regexp.match(s)
- assert_is_none(match)
+ assert match is None
t('')
t('0')
t('-')
Index: i18nspector-0.26/tests/tools.py
===================================================================
--- i18nspector-0.26.orig/tests/tools.py
+++ i18nspector-0.26/tests/tools.py
@@ -1,4 +1,5 @@
# Copyright © 2012-2019 Jakub Wilk <jwilk@jwilk.net>
+# Copyright © 2021 Stuart Prescott <stuart@debian.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the “Software”), to deal
@@ -23,8 +24,9 @@ import os
import sys
import tempfile
import traceback
+import unittest
-import nose
+import pytest
temporary_file = functools.partial(
tempfile.NamedTemporaryFile,
@@ -52,8 +54,8 @@ def fork_isolation(f):
EXIT_SKIP_TEST = 102
exit = os._exit # pylint: disable=redefined-builtin,protected-access
- # sys.exit() can't be used here, because nose catches all exceptions,
- # including SystemExit
+ # sys.exit() can't be used here, because the test harness catches all
+ # exceptions, including SystemExit
# pylint:disable=consider-using-sys-exit
@@ -66,7 +68,7 @@ def fork_isolation(f):
os.close(readfd)
try:
f(*args, **kwargs)
- except nose.SkipTest as exc:
+ except unittest.SkipTest as exc:
s = str(exc).encode('UTF-8')
with os.fdopen(writefd, 'wb') as fp:
fp.write(s)
@@ -90,7 +92,7 @@ def fork_isolation(f):
if status == (EXIT_EXCEPTION << 8):
raise IsolatedException() from Exception('\n\n' + msg)
elif status == (EXIT_SKIP_TEST << 8):
- raise nose.SkipTest(msg)
+ raise unittest.SkipTest(msg)
elif status == 0 and msg == '':
pass
else:
@@ -100,6 +102,37 @@ def fork_isolation(f):
return wrapper
+
+def collect_yielded(collect_func):
+ # figure out if this is a function or method being wrapped
+ # as the wrapper needs a slightly different signature
+ if collect_func.__name__ != collect_func.__qualname__:
+ # method
+ @pytest.mark.parametrize("func, test_args",
+ list(collect_func()))
+ def yield_tester(self, func, test_args):
+ # pylint: disable=unused-argument
+ # self is unused here
+ if isinstance(test_args, (tuple, list)):
+ func(*test_args)
+ elif isinstance(test_args, (str, int, float)):
+ func(test_args)
+ else:
+ raise ValueError("args must be either a tuple or a str")
+ else:
+ # function
+ @pytest.mark.parametrize("func, test_args",
+ list(collect_func()))
+ def yield_tester(func, test_args):
+ if isinstance(test_args, (tuple, list)):
+ func(*test_args)
+ elif isinstance(test_args, (str, int, float)):
+ func(test_args)
+ else:
+ raise ValueError("args must be either a tuple or a str")
+ return yield_tester
+
+
basedir = os.path.join(
os.path.dirname(__file__),
os.pardir,
Index: i18nspector-0.26/.coveragerc
===================================================================
--- i18nspector-0.26.orig/.coveragerc
+++ i18nspector-0.26/.coveragerc
@@ -1,5 +1,11 @@
[run]
branch = true
+omit =
+ *_boot*.py
+ */lib/python*/*
+ */dist-packages/*
+ */tests/*
+source = lib
[report]
show_missing = true
Index: i18nspector-0.26/private/update-branch-coverage
===================================================================
--- i18nspector-0.26.orig/private/update-branch-coverage
+++ i18nspector-0.26/private/update-branch-coverage
@@ -1,6 +1,6 @@
-#!/usr/bin/env python3
+#!/bin/bash
-# Copyright © 2014-2018 Jakub Wilk <jwilk@jwilk.net>
+# Copyright © 2021 Stuart Prescott <stuart@debian.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the “Software”), to deal
@@ -20,55 +20,22 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-import glob
-import io
-import os
-import sys
-
-import nose
-import nose.plugins.cover
-
-class Coverage(nose.plugins.cover.Coverage):
-
- stream = None
-
- def report(self, stream):
- return super().report(self.stream)
-
-basedir = os.path.join(
- os.path.dirname(__file__),
- os.pardir,
-)
-
-def main():
- os.chdir(basedir)
- module_glob = os.path.join('tests', 'test_*.py')
- modules = glob.glob(module_glob)
- argv = [
- sys.argv[0],
- '--with-coverage',
- '--cover-package=lib',
- '--cover-erase',
- ] + modules
- path = os.path.join(
- 'tests',
- 'coverage'
- )
- plugin = Coverage()
- report_stream = plugin.stream = io.StringIO()
- print('Generated automatically by private/update-branch-coverage. '
- 'Do not edit.\n', file=report_stream)
- ok = nose.run(argv=argv, plugins=[plugin])
- if not ok:
- sys.exit(1)
- report_stream.seek(0)
- with open(path + '.tmp', 'wt', encoding='ASCII') as file:
- for line in report_stream:
- line = line.rstrip()
- print(line, file=file)
- os.rename(path + '.tmp', path)
-if __name__ == '__main__':
- main()
+set -e
+
+basedir=$(dirname "$0")
+
+cd "$basedir/.."
+
+pytest --cov lib/ --cov-branch -rsx -v tests --ignore tests/blackbox_tests
+
+(
+ set -e
+ echo 'Generated automatically by private/update-branch-coverage. Do not edit.'
+ echo
+ python3-coverage report
+) > tests/coverage.tmp
+
+mv tests/coverage.tmp tests/coverage
# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/blackbox_tests/__init__.py
===================================================================
--- i18nspector-0.26.orig/tests/blackbox_tests/__init__.py
+++ i18nspector-0.26/tests/blackbox_tests/__init__.py
@@ -1,415 +0,0 @@
-# Copyright © 2012-2017 Jakub Wilk <jwilk@jwilk.net>
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the “Software”), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-import difflib
-import inspect
-import io
-import multiprocessing as mp
-import os
-import re
-import shlex
-import signal
-import subprocess as ipc
-import sys
-import traceback
-import unittest
-
-import nose
-import nose.plugins
-
-from .. import tools
-
-here = os.path.dirname(__file__)
-
-# ----------------------------------------
-
-def this():
- '''
- Return function that called this function. (Hopefully!)
- '''
- return globals()[inspect.stack()[1][0].f_code.co_name]
-
-# ----------------------------------------
-
-_parse_etag = re.compile(r'([A-Z]): (([\w-]+).*)').match
-
-def parse_etag(contents, path):
- match = _parse_etag(contents)
- if match is None:
- return
- t = ETag(match.group(1), path, match.group(2))
- return t
-
-def etags_from_tagstring(obj, path):
- try:
- docstring = obj.tagstring
- except AttributeError:
- return
- for line in docstring.splitlines():
- line = line.lstrip()
- t = parse_etag(line, path)
- if t is not None:
- yield t
-
-def tagstring(s):
- def update(x):
- x.tagstring = s
- return x
- return update
-
-# ----------------------------------------
-
-class ETag():
-
- _ellipsis = '<...>'
- _split = re.compile('({})'.format(re.escape(_ellipsis))).split
-
- def __init__(self, code, path, rest):
- self._s = s = '{code}: {path}: {rest}'.format(
- code=code,
- path=path,
- rest=rest,
- )
- self.tag = rest.split(None, 1)[0]
- regexp = ''.join(
- '.*' if chunk == self._ellipsis else re.escape(chunk)
- for chunk in self._split(s)
- )
- self._regexp = re.compile('^{}$'.format(regexp))
-
- def __eq__(self, other):
- if isinstance(other, str):
- return self._regexp.match(other)
- else:
- return NotImplemented
-
- def __str__(self):
- return self._s
-
- def __repr__(self):
- return repr(self._s)
-
-# ----------------------------------------
-
-def _get_signal_names():
- data = dict(
- (name, getattr(signal, name))
- for name in dir(signal)
- if re.compile('^SIG[A-Z0-9]*$').match(name)
- )
- try:
- if data['SIGABRT'] == data['SIGIOT']:
- del data['SIGIOT']
- except KeyError:
- pass
- try:
- if data['SIGCHLD'] == data['SIGCLD']:
- del data['SIGCLD']
- except KeyError:
- pass
- for name, n in data.items():
- yield n, name
-
-_signal_names = dict(_get_signal_names())
-
-def get_signal_name(n):
- try:
- return _signal_names[n]
- except KeyError:
- return str(n)
-
-# ----------------------------------------
-
-test_file_extensions = ('.mo', '.po', '.pot', '.pop')
-# .pop is a special extension to trigger unknown-file-type
-
-class Plugin(nose.plugins.Plugin):
-
- name = 'po-plugin'
- enabled = True
-
- def options(self, parser, env):
- pass
-
- def wantFile(self, path):
- if path.endswith(test_file_extensions):
- if path.startswith(os.path.join(os.path.abspath(here), '')):
- return True
-
- def loadTestsFromFile(self, path):
- if self.wantFile(path):
- yield TestCase(path)
-
- def wantFunction(self, func):
- if getattr(func, 'redundant', False):
- return False
-
-class TestCase(unittest.TestCase):
-
- def __init__(self, path):
- super().__init__('_test')
- self.path = os.path.relpath(path)
-
- def _test(self):
- _test_file(self.path, basedir=None)
-
- def __str__(self):
- return self.path
-
-class SubprocessError(Exception):
- pass
-
-def queue_get(queue, process):
- '''
- Remove and return an item from the queue.
- Block until the process terminates.
- '''
- while True:
- try:
- return queue.get(timeout=1)
- # This semi-active waiting is ugly, but there doesn't seem be any
- # obvious better way.
- except mp.queues.Empty:
- if process.exitcode is None:
- continue
- else:
- raise
-
-def run_i18nspector(options, path):
- commandline = os.environ.get('I18NSPECTOR_COMMANDLINE')
- if commandline is None:
- # We cheat here a bit, because exec(3)ing is very expensive.
- # Let's load the needed Python modules, and use multiprocessing to
- # “emulate” the command execution.
- import lib.cli # pylint: disable=import-outside-toplevel
- assert lib.cli # make pyflakes happy
- prog = os.path.join(here, os.pardir, os.pardir, 'i18nspector')
- commandline = [sys.executable, prog]
- queue = mp.Queue()
- child = mp.Process(
- target=_mp_run_i18nspector,
- args=(prog, options, path, queue)
- )
- child.start()
- [stdout, stderr] = (
- s.splitlines()
- for s in queue_get(queue, child)
- )
- child.join()
- rc = child.exitcode
- else:
- commandline = shlex.split(commandline)
- commandline += options
- commandline += [path]
- fixed_env = dict(os.environ, PYTHONIOENCODING='UTF-8')
- child = ipc.Popen(commandline, stdout=ipc.PIPE, stderr=ipc.PIPE, env=fixed_env)
- stdout, stderr = (
- s.decode('UTF-8').splitlines()
- for s in child.communicate()
- )
- rc = child.poll()
- assert isinstance(rc, int)
- if rc == 0:
- return stdout
- if rc < 0:
- message = ['command was interrupted by signal {sig}'.format(sig=get_signal_name(-rc))] # pylint: disable=invalid-unary-operand-type
- else:
- message = ['command exited with status {rc}'.format(rc=rc)]
- message += ['']
- if stdout:
- message += ['stdout:']
- message += ['| ' + s for s in stdout] + ['']
- else:
- message += ['stdout: (empty)']
- if stderr:
- message += ['stderr:']
- message += ['| ' + s for s in stderr]
- else:
- message += ['stderr: (empty)']
- raise SubprocessError('\n'.join(message))
-
-def _mp_run_i18nspector(prog, options, path, queue):
- with open(prog, 'rt', encoding='UTF-8') as file:
- code = file.read()
- sys.argv = [prog] + list(options) + [path]
- orig_stdout = sys.stdout
- orig_stderr = sys.stderr
- code = compile(code, prog, 'exec')
- io_stdout = io.StringIO()
- io_stderr = io.StringIO()
- gvars = dict(
- __file__=prog,
- )
- (sys.stdout, sys.stderr) = (io_stdout, io_stderr)
- try:
- try:
- exec(code, gvars) # pylint: disable=exec-used
- finally:
- (sys.stdout, sys.stderr) = (orig_stdout, orig_stderr)
- stdout = io_stdout.getvalue()
- stderr = io_stderr.getvalue()
- except SystemExit:
- queue.put([stdout, stderr])
- raise
- except: # pylint: disable=bare-except
- exctp, exc, tb = sys.exc_info()
- stderr += ''.join(
- traceback.format_exception(exctp, exc, tb)
- )
- queue.put([stdout, stderr])
- sys.exit(1)
- raise # hi, pydiatra!
- else:
- queue.put([stdout, stderr])
- sys.exit(0)
-
-def assert_emit_tags(path, etags, *, options=()):
- etags = list(etags)
- stdout = run_i18nspector(options, path)
- expected_failure = os.path.basename(path).startswith('xfail-')
- if stdout != etags:
- if expected_failure:
- raise nose.SkipTest('expected failure')
- str_etags = [str(x) for x in etags]
- message = ['Tags differ:', '']
- diff = list(
- difflib.unified_diff(str_etags, stdout, n=9999)
- )
- message += diff[3:]
- raise AssertionError('\n'.join(message))
- elif expected_failure:
- raise AssertionError('unexpected success')
-
-class TestFileSyntaxError(Exception):
- pass
-
-def _parse_test_header_file(file, path, *, comments_only):
- etags = []
- options = []
- for n, line in enumerate(file):
- orig_line = line
- if comments_only:
- if n == 0 and line.startswith('#!'):
- continue
- if line.startswith('# '):
- line = line[2:]
- else:
- break
- if line.startswith('--'):
- options += shlex.split(line)
- else:
- etag = parse_etag(line, path)
- if etag is None:
- if comments_only:
- break
- else:
- raise TestFileSyntaxError(orig_line)
- etags += [etag]
- return etags, options
-
-def _parse_test_headers(path):
- # <path>.tags:
- try:
- file = open(path + '.tags', encoding='UTF-8')
- except FileNotFoundError:
- pass
- else:
- with file:
- return _parse_test_header_file(file, path, comments_only=False)
- # <path>.gen:
- try:
- file = open(path + '.gen', encoding='UTF-8', errors='ignore')
- except FileNotFoundError:
- pass
- else:
- with file:
- return _parse_test_header_file(file, path, comments_only=True)
- # <path>:
- with open(path, 'rt', encoding='UTF-8', errors='ignore') as file:
- return _parse_test_header_file(file, path, comments_only=True)
-
-def _test_file(path, basedir=here):
- if basedir is not None:
- path = os.path.relpath(os.path.join(basedir, path), start=os.getcwd())
- options = []
- etags, options = _parse_test_headers(path)
- assert_emit_tags(path, etags, options=options)
-
-def get_coverage_for_file(path):
- etags, options = _parse_test_headers(path)
- del options
- return (t.tag for t in etags)
-
-def get_coverage_for_function(fn):
- for etag in etags_from_tagstring(fn, ''):
- yield etag.tag
-
-def _get_test_filenames():
- for root, dirnames, filenames in os.walk(here):
- del dirnames
- for filename in filenames:
- if not filename.endswith(test_file_extensions):
- continue
- yield os.path.join(root, filename)
-
-def test_file():
- for filename in _get_test_filenames():
- path = os.path.relpath(filename, start=here)
- yield _test_file, path
-test_file.redundant = True # not needed if the plugin is enabled
-
-@tagstring('''
-E: os-error No such file or directory
-''')
-def test_os_error_no_such_file():
- with tools.temporary_directory() as tmpdir:
- path = os.path.join(tmpdir, 'nonexistent.po')
- expected = etags_from_tagstring(this(), path)
- assert_emit_tags(path, expected)
-
-@tagstring('''
-E: os-error Permission denied
-''')
-def test_os_error_permission_denied():
- if os.getuid() == 0:
- raise nose.SkipTest('this test must not be run as root')
- with tools.temporary_directory() as tmpdir:
- path = os.path.join(tmpdir, 'denied.po')
- with open(path, 'wb'):
- pass
- os.chmod(path, 0)
- expected = etags_from_tagstring(this(), path)
- assert_emit_tags(path, expected)
-
-# ----------------------------------------
-
-def get_coverage():
- coverage = set()
- for filename in _get_test_filenames():
- for tag in get_coverage_for_file(filename):
- coverage.add(tag)
- for objname, obj in globals().items():
- if not objname.startswith('test_'):
- continue
- for tag in get_coverage_for_function(obj):
- coverage.add(tag)
- return coverage
-
-# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/blackbox_tests/conftest.py
===================================================================
--- /dev/null
+++ i18nspector-0.26/tests/blackbox_tests/conftest.py
@@ -0,0 +1,424 @@
+# Copyright © 2012-2021 Jakub Wilk <jwilk@jwilk.net>
+# Copyright © 2021 Stuart Prescott <stuart@debian.org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the “Software”), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import difflib
+import inspect
+import io
+import multiprocessing as mp
+import os
+import re
+import shlex
+import signal
+import subprocess as ipc
+import sys
+import traceback
+import unittest
+
+import pytest
+
+
+here = os.path.dirname(__file__)
+
+
+# ----------------------------------------
+
+def this():
+ '''
+ Return function that called this function. (Hopefully!)
+ '''
+ return globals()[inspect.stack()[1][0].f_code.co_name]
+
+# ----------------------------------------
+
+_parse_etag = re.compile(r'([A-Z]): (([\w-]+).*)').match
+
+def parse_etag(contents, path):
+ match = _parse_etag(contents)
+ if match is None:
+ return
+ t = ETag(match.group(1), path, match.group(2))
+ return t
+
+def etags_from_tagstring(obj, path):
+ try:
+ docstring = obj.tagstring
+ except AttributeError:
+ return
+ for line in docstring.splitlines():
+ line = line.lstrip()
+ t = parse_etag(line, path)
+ if t is not None:
+ yield t
+
+def tagstring(s):
+ def update(x):
+ x.tagstring = s
+ return x
+ return update
+
+# ----------------------------------------
+
+class ETag():
+
+ _ellipsis = '<...>'
+ _split = re.compile('({})'.format(re.escape(_ellipsis))).split
+
+ def __init__(self, code, path, rest):
+ self._s = s = '{code}: {path}: {rest}'.format(
+ code=code,
+ path=path,
+ rest=rest,
+ )
+ self.tag = rest.split(None, 1)[0]
+ regexp = ''.join(
+ '.*' if chunk == self._ellipsis else re.escape(chunk)
+ for chunk in self._split(s)
+ )
+ self._regexp = re.compile('^{}$'.format(regexp))
+
+ def __eq__(self, other):
+ if isinstance(other, str):
+ return self._regexp.match(other)
+ else:
+ return NotImplemented
+
+ def __str__(self):
+ return self._s
+
+ def __repr__(self):
+ return repr(self._s)
+
+# ----------------------------------------
+
+def _get_signal_names():
+ data = dict(
+ (name, getattr(signal, name))
+ for name in dir(signal)
+ if re.compile('^SIG[A-Z0-9]*$').match(name)
+ )
+ try:
+ if data['SIGABRT'] == data['SIGIOT']:
+ del data['SIGIOT']
+ except KeyError:
+ pass
+ try:
+ if data['SIGCHLD'] == data['SIGCLD']:
+ del data['SIGCLD']
+ except KeyError:
+ pass
+ for name, n in data.items():
+ yield n, name
+
+_signal_names = dict(_get_signal_names())
+
+def get_signal_name(n):
+ try:
+ return _signal_names[n]
+ except KeyError:
+ return str(n)
+
+# ----------------------------------------
+
+# Here, a pytest hook function (pytest_collect_file) is used to decide that
+# the .mo/.po/.pot files in the directory are actually test items.
+# For each file that is found, a PoTestFile is created. For each PoTestFile,
+# a testable item (PoTestItem) is created; if needed, there could be be
+# more than one PoTestItem per PoTestFile, but the code currently only
+# creates a single test.
+
+test_file_extensions = ('.mo', '.po', '.pot', '.pop')
+# .pop is a special extension to trigger unknown-file-type
+
+
+def pytest_collect_file(parent, path):
+ """hook function that decides that po files are actually tests"""
+ if path.ext in test_file_extensions:
+ return PoTestFile.from_parent(parent, fspath=path)
+
+
+class PoTestFile(pytest.File):
+ """Class to yield one or more test items that are contained in the file
+
+ In this implementation, only one test is yielded.
+ """
+ # pylint: disable=abstract-method
+ # pylint gets confused about this subclassing and emits warnings about
+ # (unneeded) abstract methods not being defined.
+ # https://github.com/pytest-dev/pytest/issues/7591
+
+ def collect(self):
+ # record the po file's basename and its full filesystem path as
+ # strings; pytest will happily use Path objects but the rest of
+ # stdlib on older Python versions only wants str not Path.
+ fname = str(self.fspath)
+ name = os.path.basename(fname)
+ yield PoTestItem.from_parent(self, name=name, filename=fname)
+
+
+class PoTestItem(pytest.Item):
+ """Class that represents a single test."""
+ # pylint: disable=abstract-method
+
+ def __init__(self, name, parent, filename):
+ super().__init__(name, parent)
+ self.filename = filename
+
+ def runtest(self):
+ """run the test
+
+ The intended i18nspector error tags are extracted from the file,
+ i18nspector is run on the file and the sets of tags are asserted
+ to be identical. Exceptions may also be raised for various failure
+ modes of i18nspector or other test harness failures.
+ """
+ etags, options = self.parse_test_headers()
+ assert_emit_tags(self.filename, etags, options=options)
+
+ def repr_failure(self, excinfo, style=None):
+ """Presentation of test failures for when self.runtest() raises an exception."""
+ if isinstance(excinfo.value, PoTestFileException):
+ return "\n".join(
+ [
+ "blackbox test failed for " + self.name,
+ str(excinfo.value),
+ ]
+ )
+ else:
+ return "\n".join(
+ [
+ "blackbox test error for " + self.name,
+ str(excinfo.value),
+ ]
+ )
+
+ def reportinfo(self):
+ """ header for test failure/error/stdout reporting """
+ return self.fspath, 0, "blackbox test: " + self.name
+
+ def _parse_test_header_file(self, fh, path, *, comments_only):
+ etags = []
+ options = []
+ for n, line in enumerate(fh):
+ orig_line = line
+ if comments_only:
+ if n == 0 and line.startswith('#!'):
+ continue
+ if line.startswith('# '):
+ line = line[2:]
+ else:
+ break
+ if line.startswith('--'):
+ options += shlex.split(line)
+ else:
+ etag = parse_etag(line, path)
+ if etag is None:
+ if comments_only:
+ break
+ else:
+ raise TestFileSyntaxError(orig_line)
+ etags += [etag]
+ return etags, options
+
+ def parse_test_headers(self):
+ path = self.filename
+ # <path>.tags:
+ try:
+ fh = open(path + '.tags', encoding='UTF-8') # pylint: disable=consider-using-with
+ except FileNotFoundError:
+ pass
+ else:
+ with fh:
+ return self._parse_test_header_file(fh, path, comments_only=False)
+ # <path>.gen:
+ try:
+ fh = open(path + '.gen', encoding='UTF-8', errors='ignore') # pylint: disable=consider-using-with
+ except FileNotFoundError:
+ pass
+ else:
+ with fh:
+ return self._parse_test_header_file(fh, path, comments_only=True)
+ # <path>:
+ with open(path, 'rt', encoding='UTF-8', errors='ignore') as fh:
+ return self._parse_test_header_file(fh, path, comments_only=True)
+
+
+class PoTestFileException(AssertionError):
+ """Custom exception for error reporting."""
+
+
+class TestFileSyntaxError(Exception):
+ pass
+
+
+def queue_get(queue, process):
+ '''
+ Remove and return an item from the queue.
+ Block until the process terminates.
+ '''
+ while True:
+ try:
+ return queue.get(timeout=1)
+ # This semi-active waiting is ugly, but there doesn't seem be any
+ # obvious better way.
+ except mp.queues.Empty:
+ if process.exitcode is None:
+ continue
+ else:
+ raise
+
+def run_i18nspector(options, path):
+ commandline = os.environ.get('I18NSPECTOR_COMMANDLINE')
+ if commandline is None:
+ # We cheat here a bit, because exec(3)ing is very expensive.
+ # Let's load the needed Python modules, and use multiprocessing to
+ # “emulate” the command execution.
+ import lib.cli # pylint: disable=import-outside-toplevel
+ assert lib.cli # make pyflakes happy
+ prog = os.path.join(here, os.pardir, os.pardir, 'i18nspector')
+ commandline = [sys.executable, prog]
+ queue = mp.Queue()
+ child = mp.Process(
+ target=_mp_run_i18nspector,
+ args=(prog, options, path, queue)
+ )
+ child.start()
+ [stdout, stderr] = (
+ s.splitlines()
+ for s in queue_get(queue, child)
+ )
+ child.join()
+ rc = child.exitcode
+ else:
+ commandline = shlex.split(commandline)
+ commandline += options
+ commandline += [path]
+ fixed_env = dict(os.environ, PYTHONIOENCODING='UTF-8')
+ with ipc.Popen(commandline, stdout=ipc.PIPE, stderr=ipc.PIPE, env=fixed_env) as child:
+ stdout, stderr = (
+ s.decode('UTF-8').splitlines()
+ for s in child.communicate()
+ )
+ rc = child.poll()
+ assert isinstance(rc, int)
+ if rc == 0:
+ return stdout
+ if rc < 0:
+ message = ['command was interrupted by signal {sig}'.format(sig=get_signal_name(-rc))] # pylint: disable=invalid-unary-operand-type
+ else:
+ message = ['command exited with status {rc}'.format(rc=rc)]
+ message += ['']
+ if stdout:
+ message += ['stdout:']
+ message += ['| ' + s for s in stdout] + ['']
+ else:
+ message += ['stdout: (empty)']
+ if stderr:
+ message += ['stderr:']
+ message += ['| ' + s for s in stderr]
+ else:
+ message += ['stderr: (empty)']
+ raise PoTestFileException('\n'.join(message))
+
+def _mp_run_i18nspector(prog, options, path, queue):
+ with open(prog, 'rt', encoding='UTF-8') as file:
+ code = file.read()
+ sys.argv = [prog] + list(options) + [path]
+ orig_stdout = sys.stdout
+ orig_stderr = sys.stderr
+ code = compile(code, prog, 'exec')
+ io_stdout = io.StringIO()
+ io_stderr = io.StringIO()
+ gvars = dict(
+ __file__=prog,
+ )
+ (sys.stdout, sys.stderr) = (io_stdout, io_stderr)
+ try:
+ try:
+ exec(code, gvars) # pylint: disable=exec-used
+ finally:
+ (sys.stdout, sys.stderr) = (orig_stdout, orig_stderr)
+ stdout = io_stdout.getvalue()
+ stderr = io_stderr.getvalue()
+ except SystemExit:
+ queue.put([stdout, stderr])
+ raise
+ except: # pylint: disable=bare-except
+ exctp, exc, tb = sys.exc_info()
+ stderr += ''.join(
+ traceback.format_exception(exctp, exc, tb)
+ )
+ queue.put([stdout, stderr])
+ sys.exit(1)
+ raise # hi, pydiatra!
+ else:
+ queue.put([stdout, stderr])
+ sys.exit(0)
+
+def assert_emit_tags(path, etags, *, options=()):
+ etags = list(etags)
+ stdout = run_i18nspector(options, path)
+ expected_failure = os.path.basename(path).startswith('xfail-')
+ if stdout != etags:
+ if expected_failure:
+ raise unittest.SkipTest('expected failure')
+ str_etags = [str(x) for x in etags]
+ message = ['Tags differ:', '']
+ diff = list(
+ difflib.unified_diff(str_etags, stdout, n=9999)
+ )
+ message += diff[3:]
+ raise PoTestFileException('\n'.join(message))
+ elif expected_failure:
+ raise PoTestFileException('unexpected success')
+
+
+# ----------------------------------------
+# Tag coverage recording code
+
+class PofileRecorderPlugin:
+ """pytest plugin to just record the test files that are collected"""
+ def __init__(self):
+ self.collected = []
+
+ def pytest_collection_modifyitems(self, items):
+ for item in items:
+ self.collected.append((item.nodeid, item))
+
+
+def get_coverage():
+ # ask pytest to enumerate the tests it knows of in this directory
+ directory = os.path.dirname(__file__)
+ pofile_recorder = PofileRecorderPlugin()
+ pytest.main(['--collect-only', '-p', 'no:terminal', directory], plugins=[pofile_recorder])
+
+ coverage = set()
+ for _, item in pofile_recorder.collected:
+ if isinstance(item, PoTestItem):
+ etags, _ = item.parse_test_headers()
+ for t in etags:
+ coverage.add(t.tag)
+ else:
+ for tag in etags_from_tagstring(item.function, ''):
+ coverage.add(tag.tag)
+
+ return coverage
+
+# vim:ts=4 sts=4 sw=4 et
Index: i18nspector-0.26/tests/blackbox_tests/test_errors.py
===================================================================
--- /dev/null
+++ i18nspector-0.26/tests/blackbox_tests/test_errors.py
@@ -0,0 +1,36 @@
+import inspect
+import os.path
+import unittest
+
+from .conftest import tagstring, etags_from_tagstring, assert_emit_tags
+from .. import tools
+
+
+def this():
+ '''
+ Return function that called this function. (Hopefully!)
+ '''
+ return globals()[inspect.stack()[1][0].f_code.co_name]
+
+@tagstring('''
+E: os-error No such file or directory
+''')
+def test_os_error_no_such_file():
+ with tools.temporary_directory() as tmpdir:
+ path = os.path.join(tmpdir, 'nonexistent.po')
+ expected = etags_from_tagstring(this(), path)
+ assert_emit_tags(path, expected)
+
+@tagstring('''
+E: os-error Permission denied
+''')
+def test_os_error_permission_denied():
+ if os.getuid() == 0:
+ raise unittest.SkipTest('this test must not be run as root')
+ with tools.temporary_directory() as tmpdir:
+ path = os.path.join(tmpdir, 'denied.po')
+ with open(path, 'wb'):
+ pass
+ os.chmod(path, 0)
+ expected = etags_from_tagstring(this(), path)
+ assert_emit_tags(path, expected)
Index: i18nspector-0.26/private/update-tag-coverage
===================================================================
--- i18nspector-0.26.orig/private/update-tag-coverage
+++ i18nspector-0.26/private/update-tag-coverage
@@ -21,12 +21,14 @@
# SOFTWARE.
import os
+import os.path
import sys
sys.path[0] += '/..'
from lib import tags
-from tests import blackbox_tests
+from tests.blackbox_tests import conftest as blackbox_tests
+
def main():
coverage = blackbox_tests.get_coverage()