Tachyon /Users/simon/.local/share/uv/python/cpython-3.15.0-macos-aarch64-none/lib/python3.15/collections/__init__.py
89
Self Samples
176
Cumulative
2
Lines Hit
0.60%
% of Total
87
Max Self
89
Max Total
Intensity:
Cold Hot
Self Time
Total Time
Show All
Hot Only
Heat
Specialization
Line
Self
Total
Code
1
'''This module implements specialized container datatypes providing
2
alternatives to Python's general purpose built-in containers, dict,
3
list, set, and tuple.
4
5
* namedtuple factory function for creating tuple subclasses with named fields
6
* deque list-like container with fast appends and pops on either end
7
* ChainMap dict-like class for creating a single view of multiple mappings
8
* Counter dict subclass for counting hashable objects
9
* OrderedDict dict subclass that remembers the order entries were added
10
* defaultdict dict subclass that calls a factory function to supply missing values
11
* UserDict wrapper around dictionary objects for easier dict subclassing
12
* UserList wrapper around list objects for easier list subclassing
13
* UserString wrapper around string objects for easier string subclassing
14
15
'''
16
17
__all__ = [
18
'ChainMap',
19
'Counter',
20
'OrderedDict',
21
'UserDict',
22
'UserList',
23
'UserString',
24
'defaultdict',
25
'deque',
26
'namedtuple',
27
]
28
29
import _collections_abc
30
import sys as _sys
31
32
_sys.modules['collections.abc'] = _collections_abc
33
abc = _collections_abc
34
35
lazy from copy import copy as _copy
36
lazy from heapq import nlargest as _nlargest
37
from itertools import chain as _chain
38
from itertools import repeat as _repeat
39
from itertools import starmap as _starmap
40
from keyword import iskeyword as _iskeyword
41
from operator import eq as _eq
42
from operator import itemgetter as _itemgetter
43
from reprlib import recursive_repr as _recursive_repr
44
from _weakref import proxy as _proxy
45
46
try:
47
from _collections import deque
48
except ImportError:
49
pass
50
else:
51
_collections_abc.MutableSequence.register(deque)
52
53
try:
54
# Expose _deque_iterator to support pickling deque iterators
55
from _collections import _deque_iterator # noqa: F401
56
except ImportError:
57
pass
58
59
try:
60
from _collections import defaultdict
61
except ImportError:
62
pass
63
64
65
################################################################################
66
### OrderedDict
67
################################################################################
68
69
class _OrderedDictKeysView(_collections_abc.KeysView):
70
71
def __reversed__(self):
72
yield from reversed(self._mapping)
73
74
class _OrderedDictItemsView(_collections_abc.ItemsView):
75
76
def __reversed__(self):
77
for key in reversed(self._mapping):
78
yield (key, self._mapping[key])
79
80
class _OrderedDictValuesView(_collections_abc.ValuesView):
81
82
def __reversed__(self):
83
for key in reversed(self._mapping):
84
yield self._mapping[key]
85
86
class _Link(object):
87
__slots__ = 'prev', 'next', 'key', '__weakref__'
88
89
class OrderedDict(dict):
90
'Dictionary that remembers insertion order'
91
# An inherited dict maps keys to values.
92
# The inherited dict provides __getitem__, __len__, __contains__, and get.
93
# The remaining methods are order-aware.
94
# Big-O running times for all methods are the same as regular dictionaries.
95
96
# The internal self.__map dict maps keys to links in a doubly linked list.
97
# The circular doubly linked list starts and ends with a sentinel element.
98
# The sentinel element never gets deleted (this simplifies the algorithm).
99
# The sentinel is in self.__hardroot with a weakref proxy in self.__root.
100
# The prev links are weakref proxies (to prevent circular references).
101
# Individual links are kept alive by the hard reference in self.__map.
102
# Those hard references disappear when a key is deleted from an OrderedDict.
103
104
def __new__(cls, /, *args, **kwds):
105
"Create the ordered dict object and set up the underlying structures."
106
self = dict.__new__(cls)
107
self.__hardroot = _Link()
108
self.__root = root = _proxy(self.__hardroot)
109
root.prev = root.next = root
110
self.__map = {}
111
return self
112
113
def __init__(self, other=(), /, **kwds):
114
'''Initialize an ordered dictionary. The signature is the same as
115
regular dictionaries. Keyword argument order is preserved.
116
'''
117
self.__update(other, **kwds)
118
119
def __setitem__(self, key, value,
120
dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
121
'od.__setitem__(i, y) <==> od[i]=y'
122
# Setting a new item creates a new link at the end of the linked list,
123
# and the inherited dictionary is updated with the new key/value pair.
124
if key not in self:
125
self.__map[key] = link = Link()
126
root = self.__root
127
last = root.prev
128
link.prev, link.next, link.key = last, root, key
129
last.next = link
130
root.prev = proxy(link)
131
dict_setitem(self, key, value)
132
133
def __delitem__(self, key, dict_delitem=dict.__delitem__):
134
'od.__delitem__(y) <==> del od[y]'
135
# Deleting an existing item uses self.__map to find the link which gets
136
# removed by updating the links in the predecessor and successor nodes.
137
dict_delitem(self, key)
138
link = self.__map.pop(key)
139
link_prev = link.prev
140
link_next = link.next
141
link_prev.next = link_next
142
link_next.prev = link_prev
143
link.prev = None
144
link.next = None
145
146
def __iter__(self):
147
'od.__iter__() <==> iter(od)'
148
# Traverse the linked list in order.
149
root = self.__root
150
curr = root.next
151
while curr is not root:
152
yield curr.key
153
curr = curr.next
154
155
def __reversed__(self):
156
'od.__reversed__() <==> reversed(od)'
157
# Traverse the linked list in reverse order.
158
root = self.__root
159
curr = root.prev
160
while curr is not root:
161
yield curr.key
162
curr = curr.prev
163
164
def clear(self):
165
'od.clear() -> None. Remove all items from od.'
166
root = self.__root
167
root.prev = root.next = root
168
self.__map.clear()
169
dict.clear(self)
170
171
def popitem(self, last=True):
172
'''Remove and return a (key, value) pair from the dictionary.
173
174
Pairs are returned in LIFO order if last is true or FIFO order if false.
175
'''
176
if not self:
177
raise KeyError('dictionary is empty')
178
root = self.__root
179
if last:
180
link = root.prev
181
link_prev = link.prev
182
link_prev.next = root
183
root.prev = link_prev
184
else:
185
link = root.next
186
link_next = link.next
187
root.next = link_next
188
link_next.prev = root
189
key = link.key
190
del self.__map[key]
191
value = dict.pop(self, key)
192
return key, value
193
194
def move_to_end(self, key, last=True):
195
'''Move an existing element to the end (or beginning if last is false).
196
197
Raise KeyError if the element does not exist.
198
'''
199
link = self.__map[key]
200
link_prev = link.prev
201
link_next = link.next
202
soft_link = link_next.prev
203
link_prev.next = link_next
204
link_next.prev = link_prev
205
root = self.__root
206
if last:
207
last = root.prev
208
link.prev = last
209
link.next = root
210
root.prev = soft_link
211
last.next = link
212
else:
213
first = root.next
214
link.prev = root
215
link.next = first
216
first.prev = soft_link
217
root.next = link
218
219
def __sizeof__(self):
220
sizeof = _sys.getsizeof
221
n = len(self) + 1 # number of links including root
222
size = sizeof(self.__dict__) # instance dictionary
223
size += sizeof(self.__map) * 2 # internal dict and inherited dict
224
size += sizeof(self.__hardroot) * n # link objects
225
size += sizeof(self.__root) * n # proxy objects
226
return size
227
228
update = __update = _collections_abc.MutableMapping.update
229
230
def keys(self):
231
"D.keys() -> a set-like object providing a view on D's keys"
232
return _OrderedDictKeysView(self)
233
234
def items(self):
235
"D.items() -> a set-like object providing a view on D's items"
236
return _OrderedDictItemsView(self)
237
238
def values(self):
239
"D.values() -> an object providing a view on D's values"
240
return _OrderedDictValuesView(self)
241
242
__ne__ = _collections_abc.MutableMapping.__ne__
243
244
__marker = object()
245
246
def pop(self, key, default=__marker):
247
'''od.pop(k[,d]) -> v, remove specified key and return the corresponding
248
value. If key is not found, d is returned if given, otherwise KeyError
249
is raised.
250
251
'''
252
marker = self.__marker
253
result = dict.pop(self, key, marker)
254
if result is not marker:
255
# The same as in __delitem__().
256
link = self.__map.pop(key)
257
link_prev = link.prev
258
link_next = link.next
259
link_prev.next = link_next
260
link_next.prev = link_prev
261
link.prev = None
262
link.next = None
263
return result
264
if default is marker:
265
raise KeyError(key)
266
return default
267
268
def setdefault(self, key, default=None):
269
'''Insert key with a value of default if key is not in the dictionary.
270
271
Return the value for key if key is in the dictionary, else default.
272
'''
273
if key in self:
274
return self[key]
275
self[key] = default
276
return default
277
278
@_recursive_repr()
279
def __repr__(self):
280
'od.__repr__() <==> repr(od)'
281
if not self:
282
return '%s()' % (self.__class__.__name__,)
283
return '%s(%r)' % (self.__class__.__name__, dict(self.items()))
284
285
def __reduce__(self):
286
'Return state information for pickling'
287
state = self.__getstate__()
288
if state:
289
if isinstance(state, tuple):
290
state, slots = state
291
else:
292
slots = {}
293
state = state.copy()
294
slots = slots.copy()
295
for k in vars(OrderedDict()):
296
state.pop(k, None)
297
slots.pop(k, None)
298
if slots:
299
state = state, slots
300
else:
301
state = state or None
302
return self.__class__, (), state, None, iter(self.items())
303
304
def copy(self):
305
'od.copy() -> a shallow copy of od'
306
return self.__class__(self)
307
308
@classmethod
309
def fromkeys(cls, iterable, value=None):
310
'''Create a new ordered dictionary with keys from iterable and values set to value.
311
'''
312
self = cls()
313
for key in iterable:
314
self[key] = value
315
return self
316
317
def __eq__(self, other):
318
'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
319
while comparison to a regular mapping is order-insensitive.
320
321
'''
322
if isinstance(other, OrderedDict):
323
return dict.__eq__(self, other) and all(map(_eq, self, other))
324
return dict.__eq__(self, other)
325
326
def __ior__(self, other):
327
self.update(other)
328
return self
329
330
def __or__(self, other):
331
if not isinstance(other, (dict, frozendict)):
332
return NotImplemented
333
new = self.__class__(self)
334
new.update(other)
335
return new
336
337
def __ror__(self, other):
338
if not isinstance(other, (dict, frozendict)):
339
return NotImplemented
340
new = self.__class__(other)
341
new.update(self)
342
return new
343
344
345
try:
346
from _collections import OrderedDict
347
except ImportError:
348
# Leave the pure Python version in place.
349
pass
350
351
352
################################################################################
353
### namedtuple
354
################################################################################
355
356
try:
357
from _collections import _tuplegetter
358
except ImportError:
359
_tuplegetter = lambda index, doc: property(_itemgetter(index), doc=doc)
360
361
def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None):
362
"""Returns a new subclass of tuple with named fields.
363
364
>>> Point = namedtuple('Point', ['x', 'y'])
365
>>> Point.__doc__ # docstring for the new class
366
'Point(x, y)'
367
>>> p = Point(11, y=22) # instantiate with positional args or keywords
368
>>> p[0] + p[1] # indexable like a plain tuple
369
33
370
>>> x, y = p # unpack like a regular tuple
371
>>> x, y
372
(11, 22)
373
>>> p.x + p.y # fields also accessible by name
374
33
375
>>> d = p._asdict() # convert to a dictionary
376
>>> d['x']
377
11
378
>>> Point(**d) # convert from a dictionary
379
Point(x=11, y=22)
380
>>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
381
Point(x=100, y=22)
382
383
"""
384
385
# Validate the field names. At the user's option, either generate an error
386
# message or automatically replace the field name with a valid name.
387
if isinstance(field_names, str):
388
field_names = field_names.replace(',', ' ').split()
389
field_names = list(map(str, field_names))
390
typename = _sys.intern(str(typename))
391
392
if rename:
393
seen = set()
394
for index, name in enumerate(field_names):
395
if (not name.isidentifier()
396
or _iskeyword(name)
397
or name.startswith('_')
398
or name in seen):
399
field_names[index] = f'_{index}'
400
seen.add(name)
401
402
for name in [typename] + field_names:
403
if type(name) is not str:
404
raise TypeError('Type names and field names must be strings')
405
if not name.isidentifier():
406
raise ValueError('Type names and field names must be valid '
407
f'identifiers: {name!r}')
408
if _iskeyword(name):
409
raise ValueError('Type names and field names cannot be a '
410
f'keyword: {name!r}')
411
412
seen = set()
413
for name in field_names:
414
if name.startswith('_') and not rename:
415
raise ValueError('Field names cannot start with an underscore: '
416
f'{name!r}')
417
if name in seen:
418
raise ValueError(f'Encountered duplicate field name: {name!r}')
419
seen.add(name)
420
421
field_defaults = {}
422
if defaults is not None:
423
defaults = tuple(defaults)
424
if len(defaults) > len(field_names):
425
raise TypeError('Got more default values than field names')
426
field_defaults = dict(reversed(list(zip(reversed(field_names),
427
reversed(defaults)))))
428
429
# Variables used in the methods and docstrings
430
field_names = tuple(map(_sys.intern, field_names))
431
num_fields = len(field_names)
432
arg_list = ', '.join(field_names)
433
if num_fields == 1:
434
arg_list += ','
435
repr_fmt = '(' + ', '.join(f'{name}=%r' for name in field_names) + ')'
436
tuple_new = tuple.__new__
437
_dict, _tuple, _len, _map, _zip = dict, tuple, len, map, zip
438
439
# Create all the named tuple methods to be added to the class namespace
440
441
namespace = {
442
'_tuple_new': tuple_new,
443
'__builtins__': {},
444
'__name__': f'namedtuple_{typename}',
445
}
446
code = f'lambda _cls, {arg_list}: _tuple_new(_cls, ({arg_list}))'
447
__new__ = eval(code, namespace)
448
__new__.__name__ = '__new__'
449
__new__.__doc__ = f'Create new instance of {typename}({arg_list})'
450
if defaults is not None:
451
__new__.__defaults__ = defaults
452
453
@classmethod
454
def _make(cls, iterable):
455
result = tuple_new(cls, iterable)
456
if _len(result) != num_fields:
457
raise TypeError(f'Expected {num_fields} arguments, got {len(result)}')
458
return result
459
460
_make.__func__.__doc__ = (f'Make a new {typename} object from a sequence '
461
'or iterable')
462
463
def _replace(self, /, **kwds):
464
result = self._make(_map(kwds.pop, field_names, self))
465
if kwds:
466
raise TypeError(f'Got unexpected field names: {list(kwds)!r}')
467
return result
468
469
_replace.__doc__ = (f'Return a new {typename} object replacing specified '
470
'fields with new values')
471
472
def __repr__(self):
473
'Return a nicely formatted representation string'
474
return self.__class__.__name__ + repr_fmt % self
475
476
def _asdict(self):
477
'Return a new dict which maps field names to their values.'
478
return _dict(_zip(self._fields, self))
479
480
def __getnewargs__(self):
481
'Return self as a plain tuple. Used by copy and pickle.'
482
return _tuple(self)
483
484
# Modify function metadata to help with introspection and debugging
485
for method in (
486
__new__,
487
_make.__func__,
488
_replace,
489
__repr__,
490
_asdict,
491
__getnewargs__,
492
):
493
method.__qualname__ = f'{typename}.{method.__name__}'
494
495
# Build-up the class namespace dictionary
496
# and use type() to build the result class
497
class_namespace = {
498
'__doc__': f'{typename}({arg_list})',
499
'__slots__': (),
500
'_fields': field_names,
501
'_field_defaults': field_defaults,
502
'__new__': __new__,
503
'_make': _make,
504
'__replace__': _replace,
505
'_replace': _replace,
506
'__repr__': __repr__,
507
'_asdict': _asdict,
508
'__getnewargs__': __getnewargs__,
509
'__match_args__': field_names,
510
}
511
for index, name in enumerate(field_names):
512
doc = _sys.intern(f'Alias for field number {index}')
513
class_namespace[name] = _tuplegetter(index, doc)
514
515
result = type(typename, (tuple,), class_namespace)
516
517
# For pickling to work, the __module__ variable needs to be set to the frame
518
# where the named tuple is created. Bypass this step in environments where
519
# sys._getframe is not defined (Jython for example) or sys._getframe is not
520
# defined for arguments greater than 0 (IronPython), or where the user has
521
# specified a particular module.
522
if module is None:
523
try:
524
module = _sys._getframemodulename(1) or '__main__'
525
except AttributeError:
526
try:
527
module = _sys._getframe(1).f_globals.get('__name__', '__main__')
528
except (AttributeError, ValueError):
529
pass
530
if module is not None:
531
result.__module__ = module
532
533
return result
534
535
536
########################################################################
537
### Counter
538
########################################################################
539
540
def _count_elements(mapping, iterable):
541
'Tally elements from the iterable.'
542
mapping_get = mapping.get
543
for elem in iterable:
544
mapping[elem] = mapping_get(elem, 0) + 1
545
546
try: # Load C helper function if available
547
from _collections import _count_elements
548
except ImportError:
549
pass
550
551
class Counter(dict):
552
'''Dict subclass for counting hashable items. Sometimes called a bag
553
or multiset. Elements are stored as dictionary keys and their counts
554
are stored as dictionary values.
555
556
When constructed from a Mapping or Counter, the original object's
557
values will be used as the initial counts.
558
559
>>> c = Counter('abcdeabcdabcaba') # count elements from a string
560
561
>>> c.most_common(3) # three most common elements
562
[('a', 5), ('b', 4), ('c', 3)]
563
>>> sorted(c) # list all unique elements
564
['a', 'b', 'c', 'd', 'e']
565
>>> ''.join(sorted(c.elements())) # list elements with repetitions
566
'aaaaabbbbcccdde'
567
>>> sum(c.values()) # total of all counts
568
15
569
570
>>> c['a'] # count of letter 'a'
571
5
572
>>> for elem in 'shazam': # update counts from an iterable
573
... c[elem] += 1 # by adding 1 to each element's count
574
>>> c['a'] # now there are seven 'a'
575
7
576
>>> del c['b'] # remove all 'b'
577
>>> c['b'] # now there are zero 'b'
578
0
579
580
>>> d = Counter('simsalabim') # make another counter
581
>>> c.update(d) # add in the second counter
582
>>> c['a'] # now there are nine 'a'
583
9
584
585
>>> c.clear() # empty the counter
586
>>> c
587
Counter()
588
589
Note: If a count is set to zero or reduced to zero, it will remain
590
in the counter until the entry is deleted or the counter is cleared:
591
592
>>> c = Counter('aaabbc')
593
>>> c['b'] -= 2 # reduce the count of 'b' by two
594
>>> c.most_common() # 'b' is still in, but its count is zero
595
[('a', 3), ('c', 1), ('b', 0)]
596
597
'''
598
# References:
599
# http://en.wikipedia.org/wiki/Multiset
600
# http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
601
# http://www.java2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
602
# http://code.activestate.com/recipes/259174/
603
# Knuth, TAOCP Vol. II section 4.6.3
604
605
def __init__(self, iterable=None, /, **kwds):
606
'''Create a new, empty Counter object. And if given, count elements
607
from an input iterable. Or, initialize the count from another mapping
608
of elements to their counts.
609
610
>>> c = Counter() # a new, empty counter
611
>>> c = Counter('gallahad') # a new counter from an iterable
612
>>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping
613
>>> c = Counter(a=4, b=2) # a new counter from keyword args
614
615
'''
616
super().__init__()
617
2
89
self.update(iterable, **kwds)
618
619
def __missing__(self, key):
620
'The count of elements not in the Counter is zero.'
621
# Needed so that self[missing_item] does not raise KeyError
622
return 0
623
624
def total(self):
625
'Sum of the counts'
626
return sum(self.values())
627
628
def most_common(self, n=None):
629
'''List the n most common elements and their counts from the most
630
common to the least. If n is None, then list all element counts.
631
632
>>> Counter('abracadabra').most_common(3)
633
[('a', 5), ('b', 2), ('r', 2)]
634
635
'''
636
# Emulate Bag.sortedByCount from Smalltalk
637
if n is None:
638
return sorted(self.items(), key=_itemgetter(1), reverse=True)
639
640
return _nlargest(n, self.items(), key=_itemgetter(1))
641
642
def elements(self):
643
'''Iterator over elements repeating each as many times as its count.
644
645
>>> c = Counter('ABCABC')
646
>>> sorted(c.elements())
647
['A', 'A', 'B', 'B', 'C', 'C']
648
649
Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
650
651
>>> import math
652
>>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
653
>>> math.prod(prime_factors.elements())
654
1836
655
656
Note, if an element's count has been set to zero or is a negative
657
number, elements() will ignore it.
658
659
'''
660
# Emulate Bag.do from Smalltalk and Multiset.begin from C++.
661
return _chain.from_iterable(_starmap(_repeat, self.items()))
662
663
# Override dict methods where necessary
664
665
@classmethod
666
def fromkeys(cls, iterable, v=None):
667
# There is no equivalent method for counters because the semantics
668
# would be ambiguous in cases such as Counter.fromkeys('aaabbc', v=2).
669
# Initializing counters to zero values isn't necessary because zero
670
# is already the default value for counter lookups. Initializing
671
# to one is easily accomplished with Counter(set(iterable)). For
672
# more exotic cases, create a dictionary first using a dictionary
673
# comprehension or dict.fromkeys().
674
raise NotImplementedError(
675
'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
676
677
def update(self, iterable=None, /, **kwds):
678
'''Like dict.update() but add counts instead of replacing them.
679
680
Source can be an iterable, a dictionary, or another Counter instance.
681
682
>>> c = Counter('which')
683
>>> c.update('witch') # add elements from another iterable
684
>>> d = Counter('watch')
685
>>> c.update(d) # add elements from another counter
686
>>> c['h'] # four 'h' in which, witch, and watch
687
4
688
689
'''
690
# The regular dict.update() operation makes no sense here because the
691
# replace behavior results in some of the original untouched counts
692
# being mixed-in with all of the other counts for a mismash that
693
# doesn't have a straight-forward interpretation in most counting
694
# contexts. Instead, we implement straight-addition. Both the inputs
695
# and outputs are allowed to contain zero and negative counts.
696
697
if iterable is not None:
698
if isinstance(iterable, _collections_abc.Mapping):
699
if self:
700
self_get = self.get
701
for elem, count in iterable.items():
702
self[elem] = count + self_get(elem, 0)
703
else:
704
# fast path when counter is empty
705
super().update(iterable)
706
else:
707
87
87
_count_elements(self, iterable)
708
if kwds:
709
self.update(kwds)
710
711
def subtract(self, iterable=None, /, **kwds):
712
'''Like dict.update() but subtracts counts instead of replacing them.
713
Counts can be reduced below zero. Both the inputs and outputs are
714
allowed to contain zero and negative counts.
715
716
Source can be an iterable, a dictionary, or another Counter instance.
717
718
>>> c = Counter('which')
719
>>> c.subtract('witch') # subtract elements from another iterable
720
>>> c.subtract(Counter('watch')) # subtract elements from another counter
721
>>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch
722
0
723
>>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch
724
-1
725
726
'''
727
if iterable is not None:
728
self_get = self.get
729
if isinstance(iterable, _collections_abc.Mapping):
730
for elem, count in iterable.items():
731
self[elem] = self_get(elem, 0) - count
732
else:
733
for elem in iterable:
734
self[elem] = self_get(elem, 0) - 1
735
if kwds:
736
self.subtract(kwds)
737
738
def copy(self):
739
'Return a shallow copy.'
740
return self.__class__(self)
741
742
def __reduce__(self):
743
return self.__class__, (dict(self),)
744
745
def __delitem__(self, elem):
746
'Like dict.__delitem__() but does not raise KeyError for missing values.'
747
if elem in self:
748
super().__delitem__(elem)
749
750
def __repr__(self):
751
if not self:
752
return f'{self.__class__.__name__}()'
753
try:
754
# dict() preserves the ordering returned by most_common()
755
d = dict(self.most_common())
756
except TypeError:
757
# handle case where values are not orderable
758
d = dict(self)
759
return f'{self.__class__.__name__}({d!r})'
760
761
# Multiset-style mathematical operations discussed in:
762
# Knuth TAOCP Volume II section 4.6.3 exercise 19
763
# and at http://en.wikipedia.org/wiki/Multiset
764
#
765
# Outputs guaranteed to only include positive counts.
766
#
767
# To strip negative and zero counts, add-in an empty counter:
768
# c += Counter()
769
#
770
# Results are ordered according to when an element is first
771
# encountered in the left operand and then by the order
772
# encountered in the right operand.
773
#
774
# When the multiplicities are all zero or one, multiset operations
775
# are guaranteed to be equivalent to the corresponding operations
776
# for regular sets.
777
#
778
# Given counter multisets such as:
779
# cp = Counter(a=1, b=0, c=1)
780
# cq = Counter(c=1, d=0, e=1)
781
#
782
# The corresponding regular sets would be:
783
# sp = {'a', 'c'}
784
# sq = {'c', 'e'}
785
#
786
# All of the following relations would hold:
787
# (cp == cq) == (sp == sq)
788
# (cp != cq) == (sp != sq)
789
# (cp <= cq) == (sp <= sq)
790
# (cp < cq) == (sp < sq)
791
# (cp >= cq) == (sp >= sq)
792
# (cp > cq) == (sp > sq)
793
# set(cp + cq) == sp | sq
794
# set(cp - cq) == sp - sq
795
# set(cp | cq) == sp | sq
796
# set(cp & cq) == sp & sq
797
# set(cp ^ cq) == sp ^ sq
798
799
def __eq__(self, other):
800
'True if all counts agree. Missing counts are treated as zero.'
801
if not isinstance(other, Counter):
802
return NotImplemented
803
return all(self[e] == other[e] for c in (self, other) for e in c)
804
805
def __ne__(self, other):
806
'True if any counts disagree. Missing counts are treated as zero.'
807
if not isinstance(other, Counter):
808
return NotImplemented
809
return not self == other
810
811
def __le__(self, other):
812
'True if all counts in self are a subset of those in other.'
813
if not isinstance(other, Counter):
814
return NotImplemented
815
return all(self[e] <= other[e] for c in (self, other) for e in c)
816
817
def __lt__(self, other):
818
'True if all counts in self are a proper subset of those in other.'
819
if not isinstance(other, Counter):
820
return NotImplemented
821
return self <= other and self != other
822
823
def __ge__(self, other):
824
'True if all counts in self are a superset of those in other.'
825
if not isinstance(other, Counter):
826
return NotImplemented
827
return all(self[e] >= other[e] for c in (self, other) for e in c)
828
829
def __gt__(self, other):
830
'True if all counts in self are a proper superset of those in other.'
831
if not isinstance(other, Counter):
832
return NotImplemented
833
return self >= other and self != other
834
835
def __add__(self, other):
836
'''Add counts from two counters.
837
838
>>> Counter('abbb') + Counter('bcc')
839
Counter({'b': 4, 'c': 2, 'a': 1})
840
841
'''
842
if not isinstance(other, Counter):
843
return NotImplemented
844
result = Counter()
845
for elem, count in self.items():
846
newcount = count + other[elem]
847
if newcount > 0:
848
result[elem] = newcount
849
for elem, count in other.items():
850
if elem not in self and count > 0:
851
result[elem] = count
852
return result
853
854
def __sub__(self, other):
855
''' Subtract count, but keep only results with positive counts.
856
857
>>> Counter('abbbc') - Counter('bccd')
858
Counter({'b': 2, 'a': 1})
859
860
'''
861
if not isinstance(other, Counter):
862
return NotImplemented
863
result = Counter()
864
for elem, count in self.items():
865
newcount = count - other[elem]
866
if newcount > 0:
867
result[elem] = newcount
868
for elem, count in other.items():
869
if elem not in self and count < 0:
870
result[elem] = 0 - count
871
return result
872
873
def __or__(self, other):
874
'''Union is the maximum of value in either of the input counters.
875
876
>>> Counter('abbb') | Counter('bcc')
877
Counter({'b': 3, 'c': 2, 'a': 1})
878
879
'''
880
if not isinstance(other, Counter):
881
return NotImplemented
882
result = Counter()
883
for elem, count in self.items():
884
other_count = other[elem]
885
newcount = other_count if count < other_count else count
886
if newcount > 0:
887
result[elem] = newcount
888
for elem, count in other.items():
889
if elem not in self and count > 0:
890
result[elem] = count
891
return result
892
893
def __and__(self, other):
894
''' Intersection is the minimum of corresponding counts.
895
896
>>> Counter('abbb') & Counter('bcc')
897
Counter({'b': 1})
898
899
'''
900
if not isinstance(other, Counter):
901
return NotImplemented
902
result = Counter()
903
for elem, count in self.items():
904
other_count = other[elem]
905
newcount = count if count < other_count else other_count
906
if newcount > 0:
907
result[elem] = newcount
908
return result
909
910
def __xor__(self, other):
911
'''Symmetric difference. Absolute value of count differences.
912
913
The symmetric difference p ^ q is equivalent to:
914
915
(p - q) | (q - p).
916
917
For each element, symmetric difference gives the same result as:
918
919
max(p[elem], q[elem]) - min(p[elem], q[elem])
920
921
>>> Counter(a=5, b=3, c=2, d=2) ^ Counter(a=1, b=3, c=5, e=1)
922
Counter({'a': 4, 'c': 3, 'd': 2, 'e': 1})
923
924
'''
925
if not isinstance(other, Counter):
926
return NotImplemented
927
result = Counter()
928
for elem, count in self.items():
929
newcount = abs(count - other[elem])
930
if newcount:
931
result[elem] = newcount
932
for elem, count in other.items():
933
if elem not in self and count:
934
result[elem] = abs(count)
935
return result
936
937
def __pos__(self):
938
'Adds an empty counter, effectively stripping negative and zero counts'
939
result = Counter()
940
for elem, count in self.items():
941
if count > 0:
942
result[elem] = count
943
return result
944
945
def __neg__(self):
946
'''Subtracts from an empty counter. Strips positive and zero counts,
947
and flips the sign on negative counts.
948
949
'''
950
result = Counter()
951
for elem, count in self.items():
952
if count < 0:
953
result[elem] = 0 - count
954
return result
955
956
def _keep_positive(self):
957
'''Internal method to strip elements with a negative or zero count'''
958
nonpositive = [elem for elem, count in self.items() if not count > 0]
959
for elem in nonpositive:
960
del self[elem]
961
return self
962
963
def __iadd__(self, other):
964
'''Inplace add from another counter, keeping only positive counts.
965
966
>>> c = Counter('abbb')
967
>>> c += Counter('bcc')
968
>>> c
969
Counter({'b': 4, 'c': 2, 'a': 1})
970
971
'''
972
for elem, count in other.items():
973
self[elem] += count
974
return self._keep_positive()
975
976
def __isub__(self, other):
977
'''Inplace subtract counter, but keep only results with positive counts.
978
979
>>> c = Counter('abbbc')
980
>>> c -= Counter('bccd')
981
>>> c
982
Counter({'b': 2, 'a': 1})
983
984
'''
985
for elem, count in other.items():
986
self[elem] -= count
987
return self._keep_positive()
988
989
def __ior__(self, other):
990
'''Inplace union is the maximum of value from either counter.
991
992
>>> c = Counter('abbb')
993
>>> c |= Counter('bcc')
994
>>> c
995
Counter({'b': 3, 'c': 2, 'a': 1})
996
997
'''
998
for elem, other_count in other.items():
999
count = self[elem]
1000
if other_count > count:
1001
self[elem] = other_count
1002
return self._keep_positive()
1003
1004
def __iand__(self, other):
1005
'''Inplace intersection is the minimum of corresponding counts.
1006
1007
>>> c = Counter('abbb')
1008
>>> c &= Counter('bcc')
1009
>>> c
1010
Counter({'b': 1})
1011
1012
'''
1013
for elem, count in self.items():
1014
other_count = other[elem]
1015
if other_count < count:
1016
self[elem] = other_count
1017
return self._keep_positive()
1018
1019
def __ixor__(self, other):
1020
'''Inplace symmetric difference. Absolute value of count differences.
1021
1022
>>> c = Counter(a=5, b=3, c=2, d=2)
1023
>>> c ^= Counter(a=1, b=3, c=5, e=1)
1024
>>> c
1025
Counter({'a': 4, 'c': 3, 'd': 2, 'e': 1})
1026
1027
'''
1028
for elem, count in self.items():
1029
self[elem] = abs(count - other[elem])
1030
for elem, count in other.items():
1031
if elem not in self:
1032
self[elem] = abs(count)
1033
return self._keep_positive()
1034
1035
1036
########################################################################
1037
### ChainMap
1038
########################################################################
1039
1040
class ChainMap(_collections_abc.MutableMapping):
1041
''' A ChainMap groups multiple dicts (or other mappings) together
1042
to create a single, updateable view.
1043
1044
The underlying mappings are stored in a list. That list is public and can
1045
be accessed or updated using the *maps* attribute. There is no other
1046
state.
1047
1048
Lookups search the underlying mappings successively until a key is found.
1049
In contrast, writes, updates, and deletions only operate on the first
1050
mapping.
1051
1052
'''
1053
1054
def __init__(self, *maps):
1055
'''Initialize a ChainMap by setting *maps* to the given mappings.
1056
If no mappings are provided, a single empty dictionary is used.
1057
1058
'''
1059
self.maps = list(maps) or [{}] # always at least one map
1060
1061
def __missing__(self, key):
1062
raise KeyError(key)
1063
1064
def __getitem__(self, key):
1065
for mapping in self.maps:
1066
try:
1067
return mapping[key] # can't use 'key in mapping' with defaultdict
1068
except KeyError:
1069
pass
1070
return self.__missing__(key) # support subclasses that define __missing__
1071
1072
def get(self, key, default=None):
1073
return self[key] if key in self else default # needs to make use of __contains__
1074
1075
def __len__(self):
1076
return len(set().union(*self.maps)) # reuses stored hash values if possible
1077
1078
def __iter__(self):
1079
d = {}
1080
for mapping in map(dict.fromkeys, reversed(self.maps)):
1081
d |= mapping # reuses stored hash values if possible
1082
return iter(d)
1083
1084
def __contains__(self, key):
1085
for mapping in self.maps:
1086
if key in mapping:
1087
return True
1088
return False
1089
1090
def __bool__(self):
1091
return any(self.maps)
1092
1093
@_recursive_repr()
1094
def __repr__(self):
1095
return f'{self.__class__.__name__}({", ".join(map(repr, self.maps))})'
1096
1097
@classmethod
1098
def fromkeys(cls, iterable, value=None, /):
1099
'Create a new ChainMap with keys from iterable and values set to value.'
1100
return cls(dict.fromkeys(iterable, value))
1101
1102
def copy(self):
1103
'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
1104
return self.__class__(self.maps[0].copy(), *self.maps[1:])
1105
1106
__copy__ = copy
1107
1108
def new_child(self, m=None, **kwargs): # like Django's Context.push()
1109
'''New ChainMap with a new map followed by all previous maps.
1110
If no map is provided, an empty dict is used.
1111
Keyword arguments update the map or new empty dict.
1112
'''
1113
if m is None:
1114
m = kwargs
1115
elif kwargs:
1116
m.update(kwargs)
1117
return self.__class__(m, *self.maps)
1118
1119
@property
1120
def parents(self): # like Django's Context.pop()
1121
'New ChainMap from maps[1:].'
1122
return self.__class__(*self.maps[1:])
1123
1124
def __setitem__(self, key, value):
1125
self.maps[0][key] = value
1126
1127
def __delitem__(self, key):
1128
try:
1129
del self.maps[0][key]
1130
except KeyError:
1131
raise KeyError(f'Key not found in the first mapping: {key!r}')
1132
1133
def popitem(self):
1134
'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
1135
try:
1136
return self.maps[0].popitem()
1137
except KeyError:
1138
raise KeyError('No keys found in the first mapping.')
1139
1140
def pop(self, key, *args):
1141
'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
1142
try:
1143
return self.maps[0].pop(key, *args)
1144
except KeyError:
1145
raise KeyError(f'Key not found in the first mapping: {key!r}')
1146
1147
def clear(self):
1148
'Clear maps[0], leaving maps[1:] intact.'
1149
self.maps[0].clear()
1150
1151
def __ior__(self, other):
1152
self.maps[0].update(other)
1153
return self
1154
1155
def __or__(self, other):
1156
if not isinstance(other, _collections_abc.Mapping):
1157
return NotImplemented
1158
m = self.copy()
1159
m.maps[0].update(other)
1160
return m
1161
1162
def __ror__(self, other):
1163
if not isinstance(other, _collections_abc.Mapping):
1164
return NotImplemented
1165
m = dict(other)
1166
for child in reversed(self.maps):
1167
m.update(child)
1168
return self.__class__(m)
1169
1170
1171
################################################################################
1172
### UserDict
1173
################################################################################
1174
1175
class UserDict(_collections_abc.MutableMapping):
1176
1177
# Start by filling-out the abstract methods
1178
def __init__(self, dict=None, /, **kwargs):
1179
self.data = {}
1180
if dict is not None:
1181
self.update(dict)
1182
if kwargs:
1183
self.update(kwargs)
1184
1185
def __len__(self):
1186
return len(self.data)
1187
1188
def __getitem__(self, key):
1189
if key in self.data:
1190
return self.data[key]
1191
if hasattr(self.__class__, "__missing__"):
1192
return self.__class__.__missing__(self, key)
1193
raise KeyError(key)
1194
1195
def __setitem__(self, key, item):
1196
self.data[key] = item
1197
1198
def __delitem__(self, key):
1199
del self.data[key]
1200
1201
def __iter__(self):
1202
return iter(self.data)
1203
1204
# Modify __contains__ and get() to work like dict
1205
# does when __missing__ is present.
1206
def __contains__(self, key):
1207
return key in self.data
1208
1209
def get(self, key, default=None):
1210
if key in self:
1211
return self[key]
1212
return default
1213
1214
1215
# Now, add the methods in dicts but not in MutableMapping
1216
def __repr__(self):
1217
return repr(self.data)
1218
1219
def __or__(self, other):
1220
if isinstance(other, UserDict):
1221
return self.__class__(self.data | other.data)
1222
if isinstance(other, (dict, frozendict)):
1223
return self.__class__(self.data | other)
1224
return NotImplemented
1225
1226
def __ror__(self, other):
1227
if isinstance(other, UserDict):
1228
return self.__class__(other.data | self.data)
1229
if isinstance(other, (dict, frozendict)):
1230
return self.__class__(other | self.data)
1231
return NotImplemented
1232
1233
def __ior__(self, other):
1234
if isinstance(other, UserDict):
1235
self.data |= other.data
1236
else:
1237
self.data |= other
1238
return self
1239
1240
def __copy__(self):
1241
inst = self.__class__.__new__(self.__class__)
1242
inst.__dict__.update(self.__dict__)
1243
# Create a copy and avoid triggering descriptors
1244
inst.__dict__["data"] = self.__dict__["data"].copy()
1245
return inst
1246
1247
def copy(self):
1248
if self.__class__ is UserDict:
1249
return UserDict(self.data.copy())
1250
data = self.data
1251
try:
1252
self.data = {}
1253
c = _copy(self)
1254
finally:
1255
self.data = data
1256
c.update(self)
1257
return c
1258
1259
1260
# This method has a default implementation in MutableMapping, but dict's
1261
# equivalent is last-in, first-out instead of first-in, first-out.
1262
def popitem(self):
1263
"""Remove and return a (key, value) pair as a 2-tuple.
1264
1265
Removes pairs in the same order as the wrapped mapping's popitem()
1266
method. For dict objects (the default), that order is last-in,
1267
first-out (LIFO).
1268
Raises KeyError if the UserDict is empty.
1269
"""
1270
return self.data.popitem()
1271
1272
1273
@classmethod
1274
def fromkeys(cls, iterable, value=None):
1275
d = cls()
1276
for key in iterable:
1277
d[key] = value
1278
return d
1279
1280
1281
################################################################################
1282
### UserList
1283
################################################################################
1284
1285
class UserList(_collections_abc.MutableSequence):
1286
"""A more or less complete user-defined wrapper around list objects."""
1287
1288
def __init__(self, initlist=None):
1289
self.data = []
1290
if initlist is not None:
1291
# XXX should this accept an arbitrary sequence?
1292
if type(initlist) == type(self.data):
1293
self.data[:] = initlist
1294
elif isinstance(initlist, UserList):
1295
self.data[:] = initlist.data[:]
1296
else:
1297
self.data = list(initlist)
1298
1299
def __repr__(self):
1300
return repr(self.data)
1301
1302
def __lt__(self, other):
1303
return self.data < self.__cast(other)
1304
1305
def __le__(self, other):
1306
return self.data <= self.__cast(other)
1307
1308
def __eq__(self, other):
1309
return self.data == self.__cast(other)
1310
1311
def __gt__(self, other):
1312
return self.data > self.__cast(other)
1313
1314
def __ge__(self, other):
1315
return self.data >= self.__cast(other)
1316
1317
def __cast(self, other):
1318
return other.data if isinstance(other, UserList) else other
1319
1320
def __contains__(self, item):
1321
return item in self.data
1322
1323
def __len__(self):
1324
return len(self.data)
1325
1326
def __getitem__(self, i):
1327
if isinstance(i, slice):
1328
return self.__class__(self.data[i])
1329
else:
1330
return self.data[i]
1331
1332
def __setitem__(self, i, item):
1333
self.data[i] = item
1334
1335
def __delitem__(self, i):
1336
del self.data[i]
1337
1338
def __add__(self, other):
1339
if isinstance(other, UserList):
1340
return self.__class__(self.data + other.data)
1341
elif isinstance(other, type(self.data)):
1342
return self.__class__(self.data + other)
1343
return self.__class__(self.data + list(other))
1344
1345
def __radd__(self, other):
1346
if isinstance(other, UserList):
1347
return self.__class__(other.data + self.data)
1348
elif isinstance(other, type(self.data)):
1349
return self.__class__(other + self.data)
1350
return self.__class__(list(other) + self.data)
1351
1352
def __iadd__(self, other):
1353
if isinstance(other, UserList):
1354
self.data += other.data
1355
elif isinstance(other, type(self.data)):
1356
self.data += other
1357
else:
1358
self.data += list(other)
1359
return self
1360
1361
def __mul__(self, n):
1362
return self.__class__(self.data * n)
1363
1364
__rmul__ = __mul__
1365
1366
def __imul__(self, n):
1367
self.data *= n
1368
return self
1369
1370
def __copy__(self):
1371
inst = self.__class__.__new__(self.__class__)
1372
inst.__dict__.update(self.__dict__)
1373
# Create a copy and avoid triggering descriptors
1374
inst.__dict__["data"] = self.__dict__["data"][:]
1375
return inst
1376
1377
def append(self, item):
1378
self.data.append(item)
1379
1380
def insert(self, i, item):
1381
self.data.insert(i, item)
1382
1383
def pop(self, i=-1):
1384
return self.data.pop(i)
1385
1386
def remove(self, item):
1387
self.data.remove(item)
1388
1389
def clear(self):
1390
self.data.clear()
1391
1392
def copy(self):
1393
return self.__class__(self)
1394
1395
def count(self, item):
1396
return self.data.count(item)
1397
1398
def index(self, item, *args):
1399
return self.data.index(item, *args)
1400
1401
def reverse(self):
1402
self.data.reverse()
1403
1404
def sort(self, /, *args, **kwds):
1405
self.data.sort(*args, **kwds)
1406
1407
def extend(self, other):
1408
if isinstance(other, UserList):
1409
self.data.extend(other.data)
1410
else:
1411
self.data.extend(other)
1412
1413
1414
################################################################################
1415
### UserString
1416
################################################################################
1417
1418
class UserString(_collections_abc.Sequence):
1419
1420
def __init__(self, seq):
1421
if isinstance(seq, str):
1422
self.data = seq
1423
elif isinstance(seq, UserString):
1424
self.data = seq.data[:]
1425
else:
1426
self.data = str(seq)
1427
1428
def __str__(self):
1429
return str(self.data)
1430
1431
def __repr__(self):
1432
return repr(self.data)
1433
1434
def __int__(self):
1435
return int(self.data)
1436
1437
def __float__(self):
1438
return float(self.data)
1439
1440
def __complex__(self):
1441
return complex(self.data)
1442
1443
def __hash__(self):
1444
return hash(self.data)
1445
1446
def __getnewargs__(self):
1447
return (self.data[:],)
1448
1449
def __eq__(self, string):
1450
if isinstance(string, UserString):
1451
return self.data == string.data
1452
return self.data == string
1453
1454
def __lt__(self, string):
1455
if isinstance(string, UserString):
1456
return self.data < string.data
1457
return self.data < string
1458
1459
def __le__(self, string):
1460
if isinstance(string, UserString):
1461
return self.data <= string.data
1462
return self.data <= string
1463
1464
def __gt__(self, string):
1465
if isinstance(string, UserString):
1466
return self.data > string.data
1467
return self.data > string
1468
1469
def __ge__(self, string):
1470
if isinstance(string, UserString):
1471
return self.data >= string.data
1472
return self.data >= string
1473
1474
def __contains__(self, char):
1475
if isinstance(char, UserString):
1476
char = char.data
1477
return char in self.data
1478
1479
def __len__(self):
1480
return len(self.data)
1481
1482
def __getitem__(self, index):
1483
return self.__class__(self.data[index])
1484
1485
def __add__(self, other):
1486
if isinstance(other, UserString):
1487
return self.__class__(self.data + other.data)
1488
elif isinstance(other, str):
1489
return self.__class__(self.data + other)
1490
return self.__class__(self.data + str(other))
1491
1492
def __radd__(self, other):
1493
if isinstance(other, str):
1494
return self.__class__(other + self.data)
1495
return self.__class__(str(other) + self.data)
1496
1497
def __mul__(self, n):
1498
return self.__class__(self.data * n)
1499
1500
__rmul__ = __mul__
1501
1502
def __mod__(self, args):
1503
return self.__class__(self.data % args)
1504
1505
def __rmod__(self, template):
1506
return self.__class__(str(template) % self)
1507
1508
# the following methods are defined in alphabetical order:
1509
def capitalize(self):
1510
return self.__class__(self.data.capitalize())
1511
1512
def casefold(self):
1513
return self.__class__(self.data.casefold())
1514
1515
def center(self, width, *args):
1516
return self.__class__(self.data.center(width, *args))
1517
1518
def count(self, sub, start=0, end=_sys.maxsize):
1519
if isinstance(sub, UserString):
1520
sub = sub.data
1521
return self.data.count(sub, start, end)
1522
1523
def removeprefix(self, prefix, /):
1524
if isinstance(prefix, UserString):
1525
prefix = prefix.data
1526
return self.__class__(self.data.removeprefix(prefix))
1527
1528
def removesuffix(self, suffix, /):
1529
if isinstance(suffix, UserString):
1530
suffix = suffix.data
1531
return self.__class__(self.data.removesuffix(suffix))
1532
1533
def encode(self, encoding='utf-8', errors='strict'):
1534
encoding = 'utf-8' if encoding is None else encoding
1535
errors = 'strict' if errors is None else errors
1536
return self.data.encode(encoding, errors)
1537
1538
def endswith(self, suffix, start=0, end=_sys.maxsize):
1539
return self.data.endswith(suffix, start, end)
1540
1541
def expandtabs(self, tabsize=8):
1542
return self.__class__(self.data.expandtabs(tabsize))
1543
1544
def find(self, sub, start=0, end=_sys.maxsize):
1545
if isinstance(sub, UserString):
1546
sub = sub.data
1547
return self.data.find(sub, start, end)
1548
1549
def format(self, /, *args, **kwds):
1550
return self.data.format(*args, **kwds)
1551
1552
def format_map(self, mapping):
1553
return self.data.format_map(mapping)
1554
1555
def index(self, sub, start=0, end=_sys.maxsize):
1556
if isinstance(sub, UserString):
1557
sub = sub.data
1558
return self.data.index(sub, start, end)
1559
1560
def isalpha(self):
1561
return self.data.isalpha()
1562
1563
def isalnum(self):
1564
return self.data.isalnum()
1565
1566
def isascii(self):
1567
return self.data.isascii()
1568
1569
def isdecimal(self):
1570
return self.data.isdecimal()
1571
1572
def isdigit(self):
1573
return self.data.isdigit()
1574
1575
def isidentifier(self):
1576
return self.data.isidentifier()
1577
1578
def islower(self):
1579
return self.data.islower()
1580
1581
def isnumeric(self):
1582
return self.data.isnumeric()
1583
1584
def isprintable(self):
1585
return self.data.isprintable()
1586
1587
def isspace(self):
1588
return self.data.isspace()
1589
1590
def istitle(self):
1591
return self.data.istitle()
1592
1593
def isupper(self):
1594
return self.data.isupper()
1595
1596
def join(self, seq):
1597
return self.data.join(seq)
1598
1599
def ljust(self, width, *args):
1600
return self.__class__(self.data.ljust(width, *args))
1601
1602
def lower(self):
1603
return self.__class__(self.data.lower())
1604
1605
def lstrip(self, chars=None):
1606
return self.__class__(self.data.lstrip(chars))
1607
1608
maketrans = str.maketrans
1609
1610
def partition(self, sep):
1611
return self.data.partition(sep)
1612
1613
def replace(self, old, new, maxsplit=-1):
1614
if isinstance(old, UserString):
1615
old = old.data
1616
if isinstance(new, UserString):
1617
new = new.data
1618
return self.__class__(self.data.replace(old, new, maxsplit))
1619
1620
def rfind(self, sub, start=0, end=_sys.maxsize):
1621
if isinstance(sub, UserString):
1622
sub = sub.data
1623
return self.data.rfind(sub, start, end)
1624
1625
def rindex(self, sub, start=0, end=_sys.maxsize):
1626
if isinstance(sub, UserString):
1627
sub = sub.data
1628
return self.data.rindex(sub, start, end)
1629
1630
def rjust(self, width, *args):
1631
return self.__class__(self.data.rjust(width, *args))
1632
1633
def rpartition(self, sep):
1634
return self.data.rpartition(sep)
1635
1636
def rstrip(self, chars=None):
1637
return self.__class__(self.data.rstrip(chars))
1638
1639
def split(self, sep=None, maxsplit=-1):
1640
return self.data.split(sep, maxsplit)
1641
1642
def rsplit(self, sep=None, maxsplit=-1):
1643
return self.data.rsplit(sep, maxsplit)
1644
1645
def splitlines(self, keepends=False):
1646
return self.data.splitlines(keepends)
1647
1648
def startswith(self, prefix, start=0, end=_sys.maxsize):
1649
return self.data.startswith(prefix, start, end)
1650
1651
def strip(self, chars=None):
1652
return self.__class__(self.data.strip(chars))
1653
1654
def swapcase(self):
1655
return self.__class__(self.data.swapcase())
1656
1657
def title(self):
1658
return self.__class__(self.data.title())
1659
1660
def translate(self, *args):
1661
return self.__class__(self.data.translate(*args))
1662
1663
def upper(self):
1664
return self.__class__(self.data.upper())
1665
1666
def zfill(self, width):
1667
return self.__class__(self.data.zfill(width))