jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1081397?usp=email )
Change subject: [tests] update coverage
......................................................................
[tests] update coverage
Change-Id: Icd41894db54a0ed067f5ff2c3370ca2cc69ee2b9
---
M tests/__init__.py
M tests/aspects.py
2 files changed, 50 insertions(+), 55 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/tests/__init__.py b/tests/__init__.py
index 00e5dbf..8eb9a7a 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -217,7 +217,7 @@
'Disabled test modules (to run: python -m unittest ...):\n {}'
.format(', '.join(disabled_test_modules)))
- if extra_test_modules:
+ if extra_test_modules: # pragma: no cover
unittest_print(
'Extra test modules (run after library, before scripts):\n {}'
.format(', '.join(extra_test_modules)))
diff --git a/tests/aspects.py b/tests/aspects.py
index 67d5bad..7a6da4e 100644
--- a/tests/aspects.py
+++ b/tests/aspects.py
@@ -120,14 +120,12 @@
msg, f'len({safe_repr(seq)}): {first_len} != {second_len}')
self.fail(msg)
- def assertPageInNamespaces(self, page, namespaces):
- """
- Assert that Pages is in namespaces.
+ def assertPageInNamespaces(self, page, namespaces: int | set[int]) -> None:
+ """Assert that Pages is in namespaces.
:param page: Page
:type page: pywikibot.BasePage
:param namespaces: expected namespaces
- :type namespaces: int or set of int
"""
if isinstance(namespaces, int):
namespaces = {namespaces}
@@ -170,18 +168,13 @@
titles = list(titles)
return titles
- def assertPagesInNamespaces(self, gen, namespaces):
- """
- Assert that generator returns Pages all in namespaces.
+ def assertPagesInNamespaces(self, gen, namespaces: int | set[int]) -> None:
+ """Assert that generator returns Pages all in namespaces.
:param gen: generator to iterate
:type gen: generator
:param namespaces: expected namespaces
- :type namespaces: int or set of int
"""
- if isinstance(namespaces, int):
- namespaces = {namespaces}
-
for page in gen:
self.assertPageInNamespaces(page, namespaces)
@@ -200,8 +193,8 @@
:raises TypeError: Invalid *namespaces* type
"""
if isinstance(namespaces, int):
- namespaces = {namespaces}
- elif not isinstance(namespaces, set):
+ namespaces = {namespaces} # pragma: no cover
+ elif not isinstance(namespaces, set): # pragma: no cover
raise TypeError('namespaces argument must be an int or a set, not '
f'{type(namespaces).__name__}')
@@ -282,12 +275,13 @@
for required_module in required_modules:
try:
__import__(required_module, globals(), locals(), [], 0)
- except ModuleNotFoundError:
+ except ModuleNotFoundError: # pragma: no cover
missing += [required_module]
if not missing:
return obj
- skip_decorator = unittest.skip(f"{', '.join(missing)} not installed")
- return skip_decorator(obj)
+ skip_decorator = unittest.skip( # pragma: no cover
+ f"{', '.join(missing)} not installed")
+ return skip_decorator(obj) # pragma: no cover
return test_requirement
@@ -317,17 +311,17 @@
"""Validate environment."""
if not isinstance(self.site, BaseSite) \
or isinstance(self.site, DrySite):
- raise Exception(
+ raise Exception( # pragma: no cover
f'{type(self).__name__}.site must be a BaseSite not '
f'{type(self.site).__name__}.')
if args or kwargs:
- raise Exception(
+ raise Exception( # pragma: no cover
f'Test method {method.__name__!r} has parameters which is '
f'not supported with require_version decorator.')
_, op, version = re.split('([<>]=?)', version_needed)
- if not op:
+ if not op: # pragma: no cover
raise Exception(f'There is no valid operator given with '
f'version {version_needed!r}')
@@ -336,7 +330,7 @@
if not skip:
return method(self, *args, **kwargs)
- myreason = ' to ' + reason if reason else ''
+ myreason = ' to ' + reason if reason else '' # pragma: no cover
raise unittest.SkipTest(
f'MediaWiki {op} v{version} required{myreason}.')
@@ -396,7 +390,7 @@
def __init__(self, code, fam=None, user=None):
"""Initializer."""
- raise SiteDefinitionError(
+ raise SiteDefinitionError( # pragma: no cover
f'Loading site {fam}:{code} during dry test not permitted')
@@ -452,11 +446,11 @@
super().setUpClass()
if not hasattr(cls, 'sites'):
- return
+ return # pragma: no cover
for key, data in cls.sites.items():
if 'hostname' not in data:
- raise Exception(
+ raise Exception( # pragma: no cover
f'{cls.__name__}: hostname not defined for {key}')
hostname = data['hostname']
@@ -522,7 +516,7 @@
:raises Exception: test class cannot use *write* attribute
together with *cached* and must be run on test sites only.
"""
- if issubclass(cls, ForceCacheMixin):
+ if issubclass(cls, ForceCacheMixin): # pragma: no cover
raise Exception(f'{cls.__name__} cannot be a subclass of both'
' SiteWriteMixin and ForceCacheMixin')
@@ -535,7 +529,7 @@
if (not hasattr(site.family, 'test_codes')
or site.code not in site.family.test_codes):
- raise Exception(
+ raise Exception( # pragma: no cover
f'{cls.__name__} should only be run on test sites. To run '
f'this test, add {site.code!r} to the {site.family.name}'
" family attribute 'test_codes'."
@@ -631,7 +625,7 @@
# For multi-site test classes, or site is specified as a param,
# the cached userpage object may not be the desired site.
if hasattr(self, '_userpage') and self._userpage.site == site:
- return self._userpage
+ return self._userpage # pragma: no cover
userpage = pywikibot.User(site, site.username())
self._userpage = userpage
@@ -761,7 +755,7 @@
if hostnames:
dct.setdefault('sites', {})
for hostname in hostnames:
- if hostname in dct['sites']:
+ if hostname in dct['sites']: # pragma: no cover
raise AttributeError(f'hostname {hostname!r} already found'
f"in dict['sites']:\n{dict['sites']}")
dct['sites'][hostname] = {'hostname': hostname}
@@ -779,7 +773,7 @@
# test writer explicitly sets 'site=False' so code reviewers
# check that the script invoked by pwb will not load a site.
if dct.get('pwb') and 'site' not in dct:
- raise Exception(
+ raise Exception( # pragma: no cover
f'{name}: Test classes using pwb must set "site";'
' add site=False if the test script will not use a site'
)
@@ -790,7 +784,7 @@
del dct['site']
# If there isn't a site, require declaration of net activity.
- if 'net' not in dct:
+ if 'net' not in dct: # pragma: no cover
raise Exception(f'{name}: Test classes without a site'
' configured must set "net"')
@@ -814,7 +808,7 @@
if dct.get('net'):
bases = cls.add_base(bases, CheckHostnameMixin)
- elif hostnames:
+ elif hostnames: # pragma: no cover
raise Exception('"net" must be True with hostnames defined')
if dct.get('write'):
@@ -843,7 +837,7 @@
# A multi-site test method only accepts 'self' and the site-key
if test_func.__code__.co_argcount != 2:
- raise Exception(
+ raise Exception( # pragma: no cover
f'{name}: Test method {test} must accept either 1 or 2 '
f'arguments; {test_func.__code__.co_argcount} found'
)
@@ -884,7 +878,7 @@
if doc_suffix:
if not doc:
doc = method.__doc__
- if doc[-1] != '.':
+ if doc[-1] != '.': # pragma: no cover
raise ValueError('doc string must end with a period.')
doc = doc[:-1] + ' ' + doc_suffix + '.'
@@ -911,7 +905,7 @@
# This stores the site under the site name.
if not cls.sites:
- cls.sites = {}
+ cls.sites = {} # pragma: no cover
# If the test is not cached, create new Site objects for this class
cm = cls._uncached()
@@ -964,17 +958,17 @@
*name*.
"""
if not name and hasattr(cls, 'sites'):
- if len(cls.sites) != 1:
+ if len(cls.sites) != 1: # pragma: no cover
raise Exception(f'"{cls.__name__}.get_site(name=None)"'
' called with multiple sites')
name = next(iter(cls.sites.keys()))
- if name and name not in cls.sites:
+ if name and name not in cls.sites: # pragma: no cover
raise Exception(f'"{name}" not declared in {cls.__name__}')
if isinstance(cls.site, BaseSite):
- if cls.sites[name]['site'] != cls.site:
+ if cls.sites[name]['site'] != cls.site: # pragma: no cover
raise Exception(f'{cls.__name__}.site is different from '
f"{cls.__name__}.sites[{name!r}]['site']:\n"
f"{cls.site} != {cls.sites[name]['site']}")
@@ -985,9 +979,9 @@
@classmethod
def has_site_user(cls, family, code):
"""Check the user config has a user for the site."""
- if not family:
+ if not family: # pragma: no cover
raise Exception(f'no family defined for {cls.__name__}')
- if not code:
+ if not code: # pragma: no cover
raise Exception(f'no site code defined for {cls.__name__}')
usernames = config.usernames
@@ -1027,7 +1021,7 @@
maintitle = removeprefix(maintitle, 'Special:MyLanguage/') # T278702
mainpage = pywikibot.Page(site, maintitle)
if not isinstance(site, DrySite) and mainpage.isRedirectPage():
- mainpage = mainpage.getRedirectTarget()
+ mainpage = mainpage.getRedirectTarget() # pragma: no cover
if force:
mainpage = pywikibot.Page(self.site, mainpage.title())
@@ -1189,7 +1183,7 @@
super().setUpClass()
if not (hasattr(cls, 'site') and hasattr(cls, 'sites')) \
- or len(cls.sites) != 1:
+ or len(cls.sites) != 1: # pragma: no cover
raise Exception('"site" or "sites" attribute is missing or "sites"'
'entries count is different from 1')
@@ -1218,7 +1212,7 @@
with cls._uncached():
for data in cls.sites.values():
if 'site' not in data:
- continue
+ continue # pragma: no cover
site = data['site']
if not site.has_data_repository:
@@ -1227,8 +1221,9 @@
if (hasattr(cls, 'repo')
and cls.repo != site.data_repository()):
- raise Exception(f'{cls.__name__}: sites do not all have'
- ' the same data repository')
+ raise Exception( # pragma: no cover
+ f'{cls.__name__}: sites do not all have the same data'
+ ' repository')
cls.repo = site.data_repository()
@@ -1327,7 +1322,7 @@
"""Prepare the environment for running the pwb.py script."""
super().setUp()
self.orig_pywikibot_dir = None
- if 'PYWIKIBOT_DIR' in os.environ:
+ if 'PYWIKIBOT_DIR' in os.environ: # pragma: no cover
self.orig_pywikibot_dir = os.environ['PYWIKIBOT_DIR']
base_dir = pywikibot.config.base_dir
os.environ['PYWIKIBOT_DIR'] = base_dir
@@ -1336,7 +1331,7 @@
"""Restore the environment after running the pwb.py script."""
super().tearDown()
del os.environ['PYWIKIBOT_DIR']
- if self.orig_pywikibot_dir:
+ if self.orig_pywikibot_dir: # pragma: no cover
os.environ['PYWIKIBOT_DIR'] = self.orig_pywikibot_dir
def execute(self, args: list[str], **kwargs):
@@ -1405,7 +1400,7 @@
self.warning_log = []
self.expect_warning_filename = inspect.getfile(self.__class__)
- if self.expect_warning_filename.endswith('.pyc'):
+ if self.expect_warning_filename.endswith('.pyc'): # pragma: no cover
self.expect_warning_filename = self.expect_warning_filename[:-1]
self._do_test_warning_filename = True
@@ -1439,14 +1434,14 @@
msg = f'{deprecated} is deprecated'
if instead:
msg += f'; use {instead} instead.'
- elif instead is None:
+ elif instead is None: # pragma: no cover
msg = None
- elif instead is True:
+ elif instead is True: # pragma: no cover
msg = cls.INSTEAD
- elif instead is False:
+ elif instead is False: # pragma: no cover
msg = cls.NO_INSTEAD
else:
- raise TypeError(
+ raise TypeError( # pragma: no cover
f'instead argument must not be a {type(instead).__name__!r}')
return msg
@@ -1485,7 +1480,7 @@
if (match and bool(match[1]) == (msg is self.INSTEAD)
or msg is None):
break
- else:
+ else: # pragma: no cover
self.fail('No generic deprecation message match found in '
f'{deprecation_messages}')
else:
@@ -1494,7 +1489,7 @@
if message.startswith(head) \
and message.endswith(tail):
break
- else:
+ else: # pragma: no cover
self.fail(f"'{msg}' not found in {self.deprecation_messages}"
'(ignoring since)')
if self._do_test_warning_filename:
@@ -1522,7 +1517,7 @@
def assertNoDeprecation(self, msg=None):
"""Assert that no deprecation warning happened."""
- if msg:
+ if msg: # pragma: no cover
self.assertNotIn(msg, self.deprecation_messages)
else:
self.assertIsEmpty(self.deprecation_messages)
@@ -1537,7 +1532,7 @@
for item in self.warning_log:
if (self._ignore_unknown_warning_packages
and 'pywikibot' not in item.filename):
- continue
+ continue # pragma: no cover
if item.filename != filename:
self.fail(f'expected warning filename {filename}; warning '
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1081397?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.wikimedia.org/r/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: Icd41894db54a0ed067f5ff2c3370ca2cc69ee2b9
Gerrit-Change-Number: 1081397
Gerrit-PatchSet: 1
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot