mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Apply SF patch #101029: call __getitem__ with a proper slice object if there
is no __getslice__ available. Also does the same for C extension types. Includes rudimentary documentation (it could use a cross reference to the section on slice objects, I couldn't figure out how to do that) and a test suite for all Python __hooks__ I could think of, including the new behaviour.
This commit is contained in:
parent
68add2e938
commit
1d75a79c00
5 changed files with 435 additions and 18 deletions
101
Lib/test/output/test_class
Normal file
101
Lib/test/output/test_class
Normal file
|
@ -0,0 +1,101 @@
|
|||
test_class
|
||||
__init__: ()
|
||||
__coerce__: (1,)
|
||||
__add__: (1,)
|
||||
__coerce__: (1,)
|
||||
__radd__: (1,)
|
||||
__coerce__: (1,)
|
||||
__sub__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rsub__: (1,)
|
||||
__coerce__: (1,)
|
||||
__mul__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rmul__: (1,)
|
||||
__coerce__: (1,)
|
||||
__div__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rdiv__: (1,)
|
||||
__coerce__: (1,)
|
||||
__mod__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rmod__: (1,)
|
||||
__coerce__: (1,)
|
||||
__divmod__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rdivmod__: (1,)
|
||||
__coerce__: (1,)
|
||||
__pow__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rpow__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rshift__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rrshift__: (1,)
|
||||
__coerce__: (1,)
|
||||
__lshift__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rlshift__: (1,)
|
||||
__coerce__: (1,)
|
||||
__and__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rand__: (1,)
|
||||
__coerce__: (1,)
|
||||
__or__: (1,)
|
||||
__coerce__: (1,)
|
||||
__ror__: (1,)
|
||||
__coerce__: (1,)
|
||||
__xor__: (1,)
|
||||
__coerce__: (1,)
|
||||
__rxor__: (1,)
|
||||
__contains__: (1,)
|
||||
__getitem__: (1,)
|
||||
__setitem__: (1, 1)
|
||||
__delitem__: (1,)
|
||||
__getslice__: (0, 42)
|
||||
__setslice__: (0, 42, 'The Answer')
|
||||
__delslice__: (0, 42)
|
||||
__getitem__: (slice(2, 1024, 10),)
|
||||
__setitem__: (slice(2, 1024, 10), 'A lot')
|
||||
__delitem__: (slice(2, 1024, 10),)
|
||||
__getitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100),)
|
||||
__setitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100), 'Strange')
|
||||
__delitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100),)
|
||||
__getitem__: (slice(0, 42, None),)
|
||||
__setitem__: (slice(0, 42, None), 'The Answer')
|
||||
__delitem__: (slice(0, 42, None),)
|
||||
__neg__: ()
|
||||
__pos__: ()
|
||||
__abs__: ()
|
||||
__int__: ()
|
||||
__long__: ()
|
||||
__float__: ()
|
||||
__oct__: ()
|
||||
__hex__: ()
|
||||
__hash__: ()
|
||||
__repr__: ()
|
||||
__str__: ()
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__coerce__: (1,)
|
||||
__cmp__: (1,)
|
||||
__del__: ()
|
||||
__getattr__: ('spam',)
|
||||
__setattr__: ('eggs', 'spam, spam, spam and ham')
|
||||
__delattr__: ('cardinal',)
|
219
Lib/test/test_class.py
Normal file
219
Lib/test/test_class.py
Normal file
|
@ -0,0 +1,219 @@
|
|||
"Test the functionality of Python classes implementing operators."
|
||||
|
||||
|
||||
testmeths = [
|
||||
|
||||
# Binary operations
|
||||
"add",
|
||||
"radd",
|
||||
"sub",
|
||||
"rsub",
|
||||
"mul",
|
||||
"rmul",
|
||||
"div",
|
||||
"rdiv",
|
||||
"mod",
|
||||
"rmod",
|
||||
"divmod",
|
||||
"rdivmod",
|
||||
"pow",
|
||||
"rpow",
|
||||
"rshift",
|
||||
"rrshift",
|
||||
"lshift",
|
||||
"rlshift",
|
||||
"and",
|
||||
"rand",
|
||||
"or",
|
||||
"ror",
|
||||
"xor",
|
||||
"rxor",
|
||||
|
||||
# List/dict operations
|
||||
"contains",
|
||||
"getitem",
|
||||
"getslice",
|
||||
"setitem",
|
||||
"setslice",
|
||||
"delitem",
|
||||
"delslice",
|
||||
|
||||
# Unary operations
|
||||
"neg",
|
||||
"pos",
|
||||
"abs",
|
||||
"int",
|
||||
"long",
|
||||
"float",
|
||||
"oct",
|
||||
"hex",
|
||||
|
||||
# generic operations
|
||||
"init",
|
||||
"del",
|
||||
]
|
||||
|
||||
# These need to return something other than None
|
||||
# "coerce",
|
||||
# "hash",
|
||||
# "str",
|
||||
# "repr",
|
||||
|
||||
# These are separate because they can influence the test of other methods.
|
||||
# "getattr",
|
||||
# "setattr",
|
||||
# "delattr",
|
||||
|
||||
class AllTests:
|
||||
def __coerce__(self, *args):
|
||||
print "__coerce__:", args
|
||||
return (self,) + args
|
||||
|
||||
def __hash__(self, *args):
|
||||
print "__hash__:", args
|
||||
return id(self)
|
||||
|
||||
def __str__(self, *args):
|
||||
print "__str__:", args
|
||||
return "AllTests"
|
||||
|
||||
def __repr__(self, *args):
|
||||
print "__repr__:", args
|
||||
return "AllTests"
|
||||
|
||||
def __cmp__(self, *args):
|
||||
print "__cmp__:", args
|
||||
return 0
|
||||
|
||||
for method in testmeths:
|
||||
exec("""def __%(method)s__(self, *args):
|
||||
print "__%(method)s__:", args
|
||||
"""%locals(), AllTests.__dict__);
|
||||
|
||||
# this also tests __init__ of course.
|
||||
testme = AllTests()
|
||||
|
||||
# Binary operations
|
||||
|
||||
testme + 1
|
||||
1 + testme
|
||||
|
||||
testme - 1
|
||||
1 - testme
|
||||
|
||||
testme * 1
|
||||
1 * testme
|
||||
|
||||
testme / 1
|
||||
1 / testme
|
||||
|
||||
testme % 1
|
||||
1 % testme
|
||||
|
||||
divmod(testme,1)
|
||||
divmod(1, testme)
|
||||
|
||||
testme ** 1
|
||||
1 ** testme
|
||||
|
||||
testme >> 1
|
||||
1 >> testme
|
||||
|
||||
testme << 1
|
||||
1 << testme
|
||||
|
||||
testme & 1
|
||||
1 & testme
|
||||
|
||||
testme | 1
|
||||
1 | testme
|
||||
|
||||
testme ^ 1
|
||||
1 ^ testme
|
||||
|
||||
|
||||
# List/dict operations
|
||||
|
||||
1 in testme
|
||||
|
||||
testme[1]
|
||||
testme[1] = 1
|
||||
del testme[1]
|
||||
|
||||
testme[:42]
|
||||
testme[:42] = "The Answer"
|
||||
del testme[:42]
|
||||
|
||||
testme[2:1024:10]
|
||||
testme[2:1024:10] = "A lot"
|
||||
del testme[2:1024:10]
|
||||
|
||||
testme[:42, ..., :24:, 24, 100]
|
||||
testme[:42, ..., :24:, 24, 100] = "Strange"
|
||||
del testme[:42, ..., :24:, 24, 100]
|
||||
|
||||
|
||||
# Now remove the slice hooks to see if converting normal slices to slice
|
||||
# object works.
|
||||
|
||||
del AllTests.__getslice__
|
||||
del AllTests.__setslice__
|
||||
del AllTests.__delslice__
|
||||
|
||||
testme[:42]
|
||||
testme[:42] = "The Answer"
|
||||
del testme[:42]
|
||||
|
||||
|
||||
# Unary operations
|
||||
|
||||
-testme
|
||||
+testme
|
||||
abs(testme)
|
||||
int(testme)
|
||||
long(testme)
|
||||
float(testme)
|
||||
oct(testme)
|
||||
hex(testme)
|
||||
|
||||
|
||||
# And the rest...
|
||||
|
||||
hash(testme)
|
||||
repr(testme)
|
||||
str(testme)
|
||||
|
||||
testme == 1
|
||||
testme < 1
|
||||
testme > 1
|
||||
testme <> 1
|
||||
testme != 1
|
||||
1 == testme
|
||||
1 < testme
|
||||
1 > testme
|
||||
1 <> testme
|
||||
1 != testme
|
||||
|
||||
# This test has to be last (duh.)
|
||||
|
||||
del testme
|
||||
|
||||
|
||||
# Interfering tests
|
||||
|
||||
class ExtraTests:
|
||||
def __getattr__(self, *args):
|
||||
print "__getattr__:", args
|
||||
return "SomeVal"
|
||||
|
||||
def __setattr__(self, *args):
|
||||
print "__setattr__:", args
|
||||
|
||||
def __delattr__(self, *args):
|
||||
print "__delattr__:", args
|
||||
|
||||
testme = ExtraTests()
|
||||
testme.spam
|
||||
testme.eggs = "spam, spam, spam and ham"
|
||||
del testme.cardinal
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue