diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 9fd3532158c..fc60e13daad 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -1060,6 +1060,8 @@ class UserString(Sequence): def __float__(self): return float(self.data) def __complex__(self): return complex(self.data) def __hash__(self): return hash(self.data) + def __getnewargs__(self): + return (self.data[:],) def __eq__(self, string): if isinstance(string, UserString): @@ -1104,9 +1106,13 @@ class UserString(Sequence): __rmul__ = __mul__ def __mod__(self, args): return self.__class__(self.data % args) + def __rmod__(self, format): + return self.__class__(format % args) # the following methods are defined in alphabetical order: def capitalize(self): return self.__class__(self.data.capitalize()) + def casefold(self): + return self.__class__(self.data.casefold()) def center(self, width, *args): return self.__class__(self.data.center(width, *args)) def count(self, sub, start=0, end=_sys.maxsize): @@ -1129,6 +1135,8 @@ class UserString(Sequence): return self.data.find(sub, start, end) def format(self, *args, **kwds): return self.data.format(*args, **kwds) + def format_map(self, mapping): + return self.data.format_map(mapping) def index(self, sub, start=0, end=_sys.maxsize): return self.data.index(sub, start, end) def isalpha(self): return self.data.isalpha() @@ -1138,6 +1146,7 @@ class UserString(Sequence): def isidentifier(self): return self.data.isidentifier() def islower(self): return self.data.islower() def isnumeric(self): return self.data.isnumeric() + def isprintable(self): return self.data.isprintable() def isspace(self): return self.data.isspace() def istitle(self): return self.data.istitle() def isupper(self): return self.data.isupper() @@ -1146,6 +1155,7 @@ class UserString(Sequence): return self.__class__(self.data.ljust(width, *args)) def lower(self): return self.__class__(self.data.lower()) def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars)) + maketrans = str.maketrans def partition(self, sep): return self.data.partition(sep) def replace(self, old, new, maxsplit=-1): diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index d96eae74589..a15651fd7d2 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -12,7 +12,7 @@ import keyword import re import sys import types -from collections import UserDict +from collections import UserDict, UserString, UserList from collections import ChainMap from collections import deque from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable @@ -24,6 +24,26 @@ from collections.abc import Sequence, MutableSequence from collections.abc import ByteString +class TestUserObjects(unittest.TestCase): + def _superset_test(self, a, b): + self.assertGreaterEqual( + set(dir(a)), + set(dir(b)), + '{a} should have all the methods of {b}'.format( + a=a.__name__, + b=b.__name__, + ), + ) + def test_str_protocol(self): + self._superset_test(UserString, str) + + def test_list_protocol(self): + self._superset_test(UserList, list) + + def test_dict_protocol(self): + self._superset_test(UserDict, dict) + + ################################################################################ ### ChainMap (helper class for configparser and the string module) ################################################################################ @@ -1848,7 +1868,8 @@ def test_main(verbose=None): NamedTupleDocs = doctest.DocTestSuite(module=collections) test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, TestCollectionABCs, TestCounter, TestChainMap, - TestOrderedDict, GeneralMappingTests, SubclassMappingTests] + TestOrderedDict, GeneralMappingTests, SubclassMappingTests, + TestUserObjects] support.run_unittest(*test_classes) support.run_doctest(collections, verbose) diff --git a/Misc/NEWS b/Misc/NEWS index 918c6a4d96f..02ce0e77667 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -64,6 +64,10 @@ Library - Issue 24230: The tempfile module now accepts bytes for prefix, suffix and dir parameters and returns bytes in such situations (matching the os module APIs). +- Issue #22189: collections.UserString now supports __getnewargs__(), + __rmod__(), casefold(), format_map(), isprintable(), and maketrans(). + Patch by Joe Jevnik. + - Issue 24244: Prevents termination when an invalid format string is encountered on Windows in strftime.