2023-09-04 06:41:58 -03:00
|
|
|
import doctest
|
2023-09-04 09:24:03 -03:00
|
|
|
import unittest
|
2023-09-04 06:41:58 -03:00
|
|
|
|
2022-03-26 13:55:35 -03:00
|
|
|
doctests = """
|
|
|
|
|
|
|
|
Setup
|
|
|
|
|
|
|
|
>>> class AClass:
|
|
|
|
... def __init__(self):
|
|
|
|
... self._setitem_name = None
|
|
|
|
... self._setitem_val = None
|
|
|
|
... self._delitem_name = None
|
|
|
|
... def __setitem__(self, name, val):
|
|
|
|
... self._delitem_name = None
|
|
|
|
... self._setitem_name = name
|
|
|
|
... self._setitem_val = val
|
|
|
|
... def __repr__(self):
|
|
|
|
... if self._setitem_name is not None:
|
|
|
|
... return f"A[{self._setitem_name}]={self._setitem_val}"
|
|
|
|
... elif self._delitem_name is not None:
|
|
|
|
... return f"delA[{self._delitem_name}]"
|
|
|
|
... def __getitem__(self, name):
|
|
|
|
... return ParameterisedA(name)
|
|
|
|
... def __delitem__(self, name):
|
|
|
|
... self._setitem_name = None
|
|
|
|
... self._delitem_name = name
|
|
|
|
...
|
|
|
|
>>> class ParameterisedA:
|
|
|
|
... def __init__(self, name):
|
|
|
|
... self._name = name
|
|
|
|
... def __repr__(self):
|
|
|
|
... return f"A[{self._name}]"
|
|
|
|
... def __iter__(self):
|
|
|
|
... for p in self._name:
|
|
|
|
... yield p
|
|
|
|
>>> class B:
|
|
|
|
... def __iter__(self):
|
|
|
|
... yield StarredB()
|
|
|
|
... def __repr__(self):
|
|
|
|
... return "B"
|
|
|
|
>>> class StarredB:
|
|
|
|
... def __repr__(self):
|
|
|
|
... return "StarredB"
|
|
|
|
>>> A = AClass()
|
|
|
|
>>> b = B()
|
|
|
|
|
|
|
|
Slices that are supposed to work, starring our custom B class
|
|
|
|
|
|
|
|
>>> A[*b]
|
|
|
|
A[(StarredB,)]
|
|
|
|
>>> A[*b] = 1; A
|
|
|
|
A[(StarredB,)]=1
|
|
|
|
>>> del A[*b]; A
|
|
|
|
delA[(StarredB,)]
|
|
|
|
|
|
|
|
>>> A[*b, *b]
|
|
|
|
A[(StarredB, StarredB)]
|
|
|
|
>>> A[*b, *b] = 1; A
|
|
|
|
A[(StarredB, StarredB)]=1
|
|
|
|
>>> del A[*b, *b]; A
|
|
|
|
delA[(StarredB, StarredB)]
|
|
|
|
|
|
|
|
>>> A[b, *b]
|
|
|
|
A[(B, StarredB)]
|
|
|
|
>>> A[b, *b] = 1; A
|
|
|
|
A[(B, StarredB)]=1
|
|
|
|
>>> del A[b, *b]; A
|
|
|
|
delA[(B, StarredB)]
|
|
|
|
|
|
|
|
>>> A[*b, b]
|
|
|
|
A[(StarredB, B)]
|
|
|
|
>>> A[*b, b] = 1; A
|
|
|
|
A[(StarredB, B)]=1
|
|
|
|
>>> del A[*b, b]; A
|
|
|
|
delA[(StarredB, B)]
|
|
|
|
|
|
|
|
>>> A[b, b, *b]
|
|
|
|
A[(B, B, StarredB)]
|
|
|
|
>>> A[b, b, *b] = 1; A
|
|
|
|
A[(B, B, StarredB)]=1
|
|
|
|
>>> del A[b, b, *b]; A
|
|
|
|
delA[(B, B, StarredB)]
|
|
|
|
|
|
|
|
>>> A[*b, b, b]
|
|
|
|
A[(StarredB, B, B)]
|
|
|
|
>>> A[*b, b, b] = 1; A
|
|
|
|
A[(StarredB, B, B)]=1
|
|
|
|
>>> del A[*b, b, b]; A
|
|
|
|
delA[(StarredB, B, B)]
|
|
|
|
|
|
|
|
>>> A[b, *b, b]
|
|
|
|
A[(B, StarredB, B)]
|
|
|
|
>>> A[b, *b, b] = 1; A
|
|
|
|
A[(B, StarredB, B)]=1
|
|
|
|
>>> del A[b, *b, b]; A
|
|
|
|
delA[(B, StarredB, B)]
|
|
|
|
|
|
|
|
>>> A[b, b, *b, b]
|
|
|
|
A[(B, B, StarredB, B)]
|
|
|
|
>>> A[b, b, *b, b] = 1; A
|
|
|
|
A[(B, B, StarredB, B)]=1
|
|
|
|
>>> del A[b, b, *b, b]; A
|
|
|
|
delA[(B, B, StarredB, B)]
|
|
|
|
|
|
|
|
>>> A[b, *b, b, b]
|
|
|
|
A[(B, StarredB, B, B)]
|
|
|
|
>>> A[b, *b, b, b] = 1; A
|
|
|
|
A[(B, StarredB, B, B)]=1
|
|
|
|
>>> del A[b, *b, b, b]; A
|
|
|
|
delA[(B, StarredB, B, B)]
|
|
|
|
|
|
|
|
>>> A[A[b, *b, b]]
|
|
|
|
A[A[(B, StarredB, B)]]
|
|
|
|
>>> A[A[b, *b, b]] = 1; A
|
|
|
|
A[A[(B, StarredB, B)]]=1
|
|
|
|
>>> del A[A[b, *b, b]]; A
|
|
|
|
delA[A[(B, StarredB, B)]]
|
|
|
|
|
|
|
|
>>> A[*A[b, *b, b]]
|
|
|
|
A[(B, StarredB, B)]
|
|
|
|
>>> A[*A[b, *b, b]] = 1; A
|
|
|
|
A[(B, StarredB, B)]=1
|
|
|
|
>>> del A[*A[b, *b, b]]; A
|
|
|
|
delA[(B, StarredB, B)]
|
|
|
|
|
|
|
|
>>> A[b, ...]
|
|
|
|
A[(B, Ellipsis)]
|
|
|
|
>>> A[b, ...] = 1; A
|
|
|
|
A[(B, Ellipsis)]=1
|
|
|
|
>>> del A[b, ...]; A
|
|
|
|
delA[(B, Ellipsis)]
|
|
|
|
|
|
|
|
>>> A[*A[b, ...]]
|
|
|
|
A[(B, Ellipsis)]
|
|
|
|
>>> A[*A[b, ...]] = 1; A
|
|
|
|
A[(B, Ellipsis)]=1
|
|
|
|
>>> del A[*A[b, ...]]; A
|
|
|
|
delA[(B, Ellipsis)]
|
|
|
|
|
|
|
|
Slices that are supposed to work, starring a list
|
|
|
|
|
|
|
|
>>> l = [1, 2, 3]
|
|
|
|
|
|
|
|
>>> A[*l]
|
|
|
|
A[(1, 2, 3)]
|
|
|
|
>>> A[*l] = 1; A
|
|
|
|
A[(1, 2, 3)]=1
|
|
|
|
>>> del A[*l]; A
|
|
|
|
delA[(1, 2, 3)]
|
|
|
|
|
|
|
|
>>> A[*l, 4]
|
|
|
|
A[(1, 2, 3, 4)]
|
|
|
|
>>> A[*l, 4] = 1; A
|
|
|
|
A[(1, 2, 3, 4)]=1
|
|
|
|
>>> del A[*l, 4]; A
|
|
|
|
delA[(1, 2, 3, 4)]
|
|
|
|
|
|
|
|
>>> A[0, *l]
|
|
|
|
A[(0, 1, 2, 3)]
|
|
|
|
>>> A[0, *l] = 1; A
|
|
|
|
A[(0, 1, 2, 3)]=1
|
|
|
|
>>> del A[0, *l]; A
|
|
|
|
delA[(0, 1, 2, 3)]
|
|
|
|
|
|
|
|
>>> A[1:2, *l]
|
|
|
|
A[(slice(1, 2, None), 1, 2, 3)]
|
|
|
|
>>> A[1:2, *l] = 1; A
|
|
|
|
A[(slice(1, 2, None), 1, 2, 3)]=1
|
|
|
|
>>> del A[1:2, *l]; A
|
|
|
|
delA[(slice(1, 2, None), 1, 2, 3)]
|
|
|
|
|
|
|
|
>>> repr(A[1:2, *l]) == repr(A[1:2, 1, 2, 3])
|
|
|
|
True
|
|
|
|
|
|
|
|
Slices that are supposed to work, starring a tuple
|
|
|
|
|
|
|
|
>>> t = (1, 2, 3)
|
|
|
|
|
|
|
|
>>> A[*t]
|
|
|
|
A[(1, 2, 3)]
|
|
|
|
>>> A[*t] = 1; A
|
|
|
|
A[(1, 2, 3)]=1
|
|
|
|
>>> del A[*t]; A
|
|
|
|
delA[(1, 2, 3)]
|
|
|
|
|
|
|
|
>>> A[*t, 4]
|
|
|
|
A[(1, 2, 3, 4)]
|
|
|
|
>>> A[*t, 4] = 1; A
|
|
|
|
A[(1, 2, 3, 4)]=1
|
|
|
|
>>> del A[*t, 4]; A
|
|
|
|
delA[(1, 2, 3, 4)]
|
|
|
|
|
|
|
|
>>> A[0, *t]
|
|
|
|
A[(0, 1, 2, 3)]
|
|
|
|
>>> A[0, *t] = 1; A
|
|
|
|
A[(0, 1, 2, 3)]=1
|
|
|
|
>>> del A[0, *t]; A
|
|
|
|
delA[(0, 1, 2, 3)]
|
|
|
|
|
|
|
|
>>> A[1:2, *t]
|
|
|
|
A[(slice(1, 2, None), 1, 2, 3)]
|
|
|
|
>>> A[1:2, *t] = 1; A
|
|
|
|
A[(slice(1, 2, None), 1, 2, 3)]=1
|
|
|
|
>>> del A[1:2, *t]; A
|
|
|
|
delA[(slice(1, 2, None), 1, 2, 3)]
|
|
|
|
|
|
|
|
>>> repr(A[1:2, *t]) == repr(A[1:2, 1, 2, 3])
|
|
|
|
True
|
|
|
|
|
|
|
|
Starring an expression (rather than a name) in a slice
|
|
|
|
|
|
|
|
>>> def returns_list():
|
|
|
|
... return [1, 2, 3]
|
|
|
|
|
|
|
|
>>> A[returns_list()]
|
|
|
|
A[[1, 2, 3]]
|
|
|
|
>>> A[returns_list()] = 1; A
|
|
|
|
A[[1, 2, 3]]=1
|
|
|
|
>>> del A[returns_list()]; A
|
|
|
|
delA[[1, 2, 3]]
|
|
|
|
|
|
|
|
>>> A[returns_list(), 4]
|
|
|
|
A[([1, 2, 3], 4)]
|
|
|
|
>>> A[returns_list(), 4] = 1; A
|
|
|
|
A[([1, 2, 3], 4)]=1
|
|
|
|
>>> del A[returns_list(), 4]; A
|
|
|
|
delA[([1, 2, 3], 4)]
|
|
|
|
|
|
|
|
>>> A[*returns_list()]
|
|
|
|
A[(1, 2, 3)]
|
|
|
|
>>> A[*returns_list()] = 1; A
|
|
|
|
A[(1, 2, 3)]=1
|
|
|
|
>>> del A[*returns_list()]; A
|
|
|
|
delA[(1, 2, 3)]
|
|
|
|
|
|
|
|
>>> A[*returns_list(), 4]
|
|
|
|
A[(1, 2, 3, 4)]
|
|
|
|
>>> A[*returns_list(), 4] = 1; A
|
|
|
|
A[(1, 2, 3, 4)]=1
|
|
|
|
>>> del A[*returns_list(), 4]; A
|
|
|
|
delA[(1, 2, 3, 4)]
|
|
|
|
|
|
|
|
>>> A[0, *returns_list()]
|
|
|
|
A[(0, 1, 2, 3)]
|
|
|
|
>>> A[0, *returns_list()] = 1; A
|
|
|
|
A[(0, 1, 2, 3)]=1
|
|
|
|
>>> del A[0, *returns_list()]; A
|
|
|
|
delA[(0, 1, 2, 3)]
|
|
|
|
|
|
|
|
>>> A[*returns_list(), *returns_list()]
|
|
|
|
A[(1, 2, 3, 1, 2, 3)]
|
|
|
|
>>> A[*returns_list(), *returns_list()] = 1; A
|
|
|
|
A[(1, 2, 3, 1, 2, 3)]=1
|
|
|
|
>>> del A[*returns_list(), *returns_list()]; A
|
|
|
|
delA[(1, 2, 3, 1, 2, 3)]
|
|
|
|
|
|
|
|
Using both a starred object and a start:stop in a slice
|
|
|
|
(See also tests in test_syntax confirming that starring *inside* a start:stop
|
|
|
|
is *not* valid syntax.)
|
|
|
|
|
|
|
|
>>> A[1:2, *b]
|
|
|
|
A[(slice(1, 2, None), StarredB)]
|
|
|
|
>>> A[*b, 1:2]
|
|
|
|
A[(StarredB, slice(1, 2, None))]
|
|
|
|
>>> A[1:2, *b, 1:2]
|
|
|
|
A[(slice(1, 2, None), StarredB, slice(1, 2, None))]
|
|
|
|
>>> A[*b, 1:2, *b]
|
|
|
|
A[(StarredB, slice(1, 2, None), StarredB)]
|
|
|
|
|
|
|
|
>>> A[1:, *b]
|
|
|
|
A[(slice(1, None, None), StarredB)]
|
|
|
|
>>> A[*b, 1:]
|
|
|
|
A[(StarredB, slice(1, None, None))]
|
|
|
|
>>> A[1:, *b, 1:]
|
|
|
|
A[(slice(1, None, None), StarredB, slice(1, None, None))]
|
|
|
|
>>> A[*b, 1:, *b]
|
|
|
|
A[(StarredB, slice(1, None, None), StarredB)]
|
|
|
|
|
|
|
|
>>> A[:1, *b]
|
|
|
|
A[(slice(None, 1, None), StarredB)]
|
|
|
|
>>> A[*b, :1]
|
|
|
|
A[(StarredB, slice(None, 1, None))]
|
|
|
|
>>> A[:1, *b, :1]
|
|
|
|
A[(slice(None, 1, None), StarredB, slice(None, 1, None))]
|
|
|
|
>>> A[*b, :1, *b]
|
|
|
|
A[(StarredB, slice(None, 1, None), StarredB)]
|
|
|
|
|
|
|
|
>>> A[:, *b]
|
|
|
|
A[(slice(None, None, None), StarredB)]
|
|
|
|
>>> A[*b, :]
|
|
|
|
A[(StarredB, slice(None, None, None))]
|
|
|
|
>>> A[:, *b, :]
|
|
|
|
A[(slice(None, None, None), StarredB, slice(None, None, None))]
|
|
|
|
>>> A[*b, :, *b]
|
|
|
|
A[(StarredB, slice(None, None, None), StarredB)]
|
|
|
|
|
|
|
|
*args annotated as starred expression
|
|
|
|
|
|
|
|
>>> def f1(*args: *b): pass
|
|
|
|
>>> f1.__annotations__
|
|
|
|
{'args': StarredB}
|
|
|
|
|
|
|
|
>>> def f2(*args: *b, arg1): pass
|
|
|
|
>>> f2.__annotations__
|
|
|
|
{'args': StarredB}
|
|
|
|
|
|
|
|
>>> def f3(*args: *b, arg1: int): pass
|
|
|
|
>>> f3.__annotations__
|
|
|
|
{'args': StarredB, 'arg1': <class 'int'>}
|
|
|
|
|
|
|
|
>>> def f4(*args: *b, arg1: int = 2): pass
|
|
|
|
>>> f4.__annotations__
|
|
|
|
{'args': StarredB, 'arg1': <class 'int'>}
|
|
|
|
|
|
|
|
>>> def f5(*args: *b = (1,)): pass
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
SyntaxError: invalid syntax
|
|
|
|
"""
|
|
|
|
|
|
|
|
__test__ = {'doctests' : doctests}
|
|
|
|
|
2023-09-04 06:41:58 -03:00
|
|
|
def load_tests(loader, tests, pattern):
|
|
|
|
tests.addTest(doctest.DocTestSuite())
|
|
|
|
return tests
|
|
|
|
|
2022-03-26 13:55:35 -03:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2023-09-04 06:41:58 -03:00
|
|
|
unittest.main()
|