jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/990725 )
Change subject: Detect range blocks with Page.is_blocked() ......................................................................
Detect range blocks with Page.is_blocked()
Bug: T301282 Change-Id: I4a5f7d92eec659998ceb23d0c0b3bae749920ec9 --- M pywikibot/page/_user.py M pywikibot/tools/__init__.py M tests/tools_tests.py 3 files changed, 107 insertions(+), 2 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/page/_user.py b/pywikibot/page/_user.py index 08e6561..3cfb12e 100644 --- a/pywikibot/page/_user.py +++ b/pywikibot/page/_user.py @@ -17,7 +17,7 @@ from pywikibot.page._links import Link from pywikibot.page._page import Page from pywikibot.page._revision import Revision -from pywikibot.tools import deprecated, is_ip_address +from pywikibot.tools import deprecated, is_ip_address, is_ip_network
__all__ = ('User', ) @@ -85,6 +85,10 @@ """Determine if the user is editing as an IP address.""" return is_ip_address(self.username)
+ def is_CIDR(self) -> bool: # noqa: N802 + """Determine if the input refers to a range of IP addresses.""" + return is_ip_network(self.username) + def getprops(self, force: bool = False) -> dict: """ Return a properties about the user. @@ -95,7 +99,7 @@ del self._userprops if not hasattr(self, '_userprops'): self._userprops = list(self.site.users([self.username, ]))[0] - if self.isAnonymous(): + if self.isAnonymous() or self.is_CIDR(): r = list(self.site.blocks(iprange=self.username, total=1)) if r: self._userprops['blockedby'] = r[0]['by'] diff --git a/pywikibot/tools/__init__.py b/pywikibot/tools/__init__.py index 088120c..f66ecd8 100644 --- a/pywikibot/tools/__init__.py +++ b/pywikibot/tools/__init__.py @@ -77,6 +77,7 @@ 'PYTHON_VERSION', 'as_filename', 'is_ip_address', + 'is_ip_network', 'has_module', 'classproperty', 'suppress_warnings', @@ -112,6 +113,20 @@ return False
+def is_ip_network(value: str) -> bool: + """Check if a value is a valid range of IPv4 or IPv6 addresses. + + .. versionadded:: 9.0 + + :param value: value to check + """ + with suppress(ValueError): + ipaddress.ip_network(value) + return True + + return False + + def has_module(module: str, version: str | None = None) -> bool: """Check if a module can be imported.
diff --git a/tests/tools_tests.py b/tests/tools_tests.py index 070c545..bc9d6e8 100755 --- a/tests/tools_tests.py +++ b/tests/tools_tests.py @@ -24,6 +24,7 @@ classproperty, has_module, is_ip_address, + is_ip_network, suppress_warnings, ) from pywikibot.tools.itertools import ( @@ -839,6 +840,81 @@ self.assertFalse(is_ip_address(address))
+class TestIsIpNetwork(TestCase): + + """Unit test class for is_ip_network.""" + + net = False + + def test_valid_ipv4_ranges(self): + """Check with valid IPv4 address ranges.""" + valid_ranges = ( + '0.0.0.0/32', + '1.2.3.4/32', + '1.2.3.0/24', + '192.168.0.0/16', + '192.168.0.0/15', + '255.0.0.0/8', + '0.0.0.0/1' + ) + + for ip_range in valid_ranges: + with self.subTest(ip_network=ip_range): + self.assertTrue(is_ip_network(ip_range)) + + def test_invalid_ipv4_ranges(self): + """Check with invalid IPv4 address ranges.""" + invalid_ranges = ( + None, + '', + '0.0.0', + '1.2.3.256', + '1.2.3.-1', + '0.0.0.a', + 'a.b.c.d', + '1.2.3.4/24', + '192.168.0.0/8', + '192.168.1.0/15' + ) + + for ip_range in invalid_ranges: + with self.subTest(ip_network=ip_range): + self.assertFalse(is_ip_network(ip_range)) + + def test_valid_ipv6_ranges(self): + """Check with valid IPv6 address ranges.""" + valid_ranges = ( + 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329/128', + 'fe80:0:0:0:202:b3ff:fe1e:8329/128', + '::ffff:5.9.158.75/128', + '2001:0db8:0000:0000:0000:0000:0000:0000/32', + '2001:0db8::/32', + '::/64', + '::/1', + ) + + for ip_range in valid_ranges: + with self.subTest(ip_network=ip_range): + self.assertTrue(is_ip_network(ip_range)) + + def test_invalid_ipv6_addresses(self): + """Check with invalid IPv6 addresses.""" + invalid_ranges = ( + None, + '/32', + ':/32', + ':::/32', + '2001:db8::aaaa::1/128', + 'fe80:0000:0000:0000:0202:b3ff:fe1e: 8329/128', + 'fe80:0000:0000:0000:0202:b3ff:fe1e:829g/128', + '2001:0db8::/16' + ) + + for ip_range in invalid_ranges: + with self.subTest(ip_network=ip_range): + self.assertFalse(is_ip_network(ip_range)) + + class TestHasModule(TestCase):
"""Unit test class for has_module."""
pywikibot-commits@lists.wikimedia.org