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': } >>> def f4(*args: *b, arg1: int = 2): pass >>> f4.__annotations__ {'args': StarredB, 'arg1': } >>> def f5(*args: *b = (1,)): pass Traceback (most recent call last): ... SyntaxError: invalid syntax """ __test__ = {'doctests' : doctests} def test_main(verbose=False): from test import support from test import test_pep646_syntax support.run_doctest(test_pep646_syntax, verbose) if __name__ == "__main__": test_main(verbose=True)