mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 10:26:02 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			329 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			329 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import doctest
 | |
| import unittest
 | |
| 
 | |
| 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}
 | |
| 
 | |
| def load_tests(loader, tests, pattern):
 | |
|     tests.addTest(doctest.DocTestSuite())
 | |
|     return tests
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     unittest.main()
 | 
