Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1d75a79

Browse files
committed
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.
1 parent 68add2e commit 1d75a79

5 files changed

Lines changed: 435 additions & 18 deletions

File tree

Doc/ref/ref3.tex

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,11 +1042,12 @@ \subsection{Emulating sequence and mapping types\label{sequence-types}}
10421042
sequence or to emulate a mapping; the difference is that for a
10431043
sequence, the allowable keys should be the integers \var{k} for which
10441044
\code{0 <= \var{k} < \var{N}} where \var{N} is the length of the
1045-
sequence, and the method \method{__getslice__()} (see below) should be
1046-
defined. It is also recommended that mappings provide methods
1047-
\method{keys()}, \method{values()}, \method{items()},
1048-
\method{has_key()}, \method{get()}, \method{clear()}, \method{copy()},
1049-
and \method{update()} behaving similar to those for
1045+
sequence, or slice objects, which define a range of items. (For backwards
1046+
compatibility, the method \method{__getslice__()} (see below) can also be
1047+
defined to handle simple, but not extended slices.) It is also recommended
1048+
that mappings provide methods \method{keys()}, \method{values()},
1049+
\method{items()}, \method{has_key()}, \method{get()}, \method{clear()},
1050+
\method{copy()}, and \method{update()} behaving similar to those for
10501051
Python's standard dictionary objects; mutable sequences should provide
10511052
methods \method{append()}, \method{count()}, \method{index()},
10521053
\method{insert()}, \method{pop()}, \method{remove()}, \method{reverse()}
@@ -1141,22 +1142,30 @@ \subsection{Additional methods for emulation of sequence types
11411142
No guarantee is made that indexes adjusted this way are not still
11421143
negative. Indexes which are greater than the length of the sequence
11431144
are not modified.
1145+
This method is deprecated. If no \method{__getslice__()} is found, a slice
1146+
object is created instead, and passed to \method{__getitem__()} instead.
11441147
\end{methoddesc}
11451148

11461149
\begin{methoddesc}[sequence object]{__setslice__}{self, i, j, sequence}
11471150
Called to implement assignment to \code{\var{self}[\var{i}:\var{j}]}.
11481151
Same notes for \var{i} and \var{j} as for \method{__getslice__()}.
1152+
1153+
This method is deprecated. If no \method{__setslice__()} is found, a slice
1154+
object is created instead, and passed to \method{__setitem__()} instead.
11491155
\end{methoddesc}
11501156

11511157
\begin{methoddesc}[sequence object]{__delslice__}{self, i, j}
11521158
Called to implement deletion of \code{\var{self}[\var{i}:\var{j}]}.
11531159
Same notes for \var{i} and \var{j} as for \method{__getslice__()}.
1160+
This method is deprecated. If no \method{__delslice__()} is found, a slice
1161+
object is created instead, and passed to \method{__delitem__()} instead.
11541162
\end{methoddesc}
11551163

1156-
Notice that these methods are only invoked when a single slice with a
1157-
single colon is used. For slice operations involving extended slice
1158-
notation, \method{__getitem__()}, \method{__setitem__()}
1159-
or\method{__delitem__()} is called.
1164+
Notice that these methods are only invoked when a single slice with a single
1165+
colon is used, and the slice method is available. For slice operations
1166+
involving extended slice notation, or in absence of the slice methods,
1167+
\method{__getitem__()}, \method{__setitem__()} or \method{__delitem__()} is
1168+
called with a slice object as argument.
11601169

11611170

11621171
\subsection{Emulating numeric types\label{numeric-types}}

Lib/test/output/test_class

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
test_class
2+
__init__: ()
3+
__coerce__: (1,)
4+
__add__: (1,)
5+
__coerce__: (1,)
6+
__radd__: (1,)
7+
__coerce__: (1,)
8+
__sub__: (1,)
9+
__coerce__: (1,)
10+
__rsub__: (1,)
11+
__coerce__: (1,)
12+
__mul__: (1,)
13+
__coerce__: (1,)
14+
__rmul__: (1,)
15+
__coerce__: (1,)
16+
__div__: (1,)
17+
__coerce__: (1,)
18+
__rdiv__: (1,)
19+
__coerce__: (1,)
20+
__mod__: (1,)
21+
__coerce__: (1,)
22+
__rmod__: (1,)
23+
__coerce__: (1,)
24+
__divmod__: (1,)
25+
__coerce__: (1,)
26+
__rdivmod__: (1,)
27+
__coerce__: (1,)
28+
__pow__: (1,)
29+
__coerce__: (1,)
30+
__rpow__: (1,)
31+
__coerce__: (1,)
32+
__rshift__: (1,)
33+
__coerce__: (1,)
34+
__rrshift__: (1,)
35+
__coerce__: (1,)
36+
__lshift__: (1,)
37+
__coerce__: (1,)
38+
__rlshift__: (1,)
39+
__coerce__: (1,)
40+
__and__: (1,)
41+
__coerce__: (1,)
42+
__rand__: (1,)
43+
__coerce__: (1,)
44+
__or__: (1,)
45+
__coerce__: (1,)
46+
__ror__: (1,)
47+
__coerce__: (1,)
48+
__xor__: (1,)
49+
__coerce__: (1,)
50+
__rxor__: (1,)
51+
__contains__: (1,)
52+
__getitem__: (1,)
53+
__setitem__: (1, 1)
54+
__delitem__: (1,)
55+
__getslice__: (0, 42)
56+
__setslice__: (0, 42, 'The Answer')
57+
__delslice__: (0, 42)
58+
__getitem__: (slice(2, 1024, 10),)
59+
__setitem__: (slice(2, 1024, 10), 'A lot')
60+
__delitem__: (slice(2, 1024, 10),)
61+
__getitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100),)
62+
__setitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100), 'Strange')
63+
__delitem__: ((slice(None, 42, None), Ellipsis, slice(None, 24, None), 24, 100),)
64+
__getitem__: (slice(0, 42, None),)
65+
__setitem__: (slice(0, 42, None), 'The Answer')
66+
__delitem__: (slice(0, 42, None),)
67+
__neg__: ()
68+
__pos__: ()
69+
__abs__: ()
70+
__int__: ()
71+
__long__: ()
72+
__float__: ()
73+
__oct__: ()
74+
__hex__: ()
75+
__hash__: ()
76+
__repr__: ()
77+
__str__: ()
78+
__coerce__: (1,)
79+
__cmp__: (1,)
80+
__coerce__: (1,)
81+
__cmp__: (1,)
82+
__coerce__: (1,)
83+
__cmp__: (1,)
84+
__coerce__: (1,)
85+
__cmp__: (1,)
86+
__coerce__: (1,)
87+
__cmp__: (1,)
88+
__coerce__: (1,)
89+
__cmp__: (1,)
90+
__coerce__: (1,)
91+
__cmp__: (1,)
92+
__coerce__: (1,)
93+
__cmp__: (1,)
94+
__coerce__: (1,)
95+
__cmp__: (1,)
96+
__coerce__: (1,)
97+
__cmp__: (1,)
98+
__del__: ()
99+
__getattr__: ('spam',)
100+
__setattr__: ('eggs', 'spam, spam, spam and ham')
101+
__delattr__: ('cardinal',)

Lib/test/test_class.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
"Test the functionality of Python classes implementing operators."
2+
3+
4+
testmeths = [
5+
6+
# Binary operations
7+
"add",
8+
"radd",
9+
"sub",
10+
"rsub",
11+
"mul",
12+
"rmul",
13+
"div",
14+
"rdiv",
15+
"mod",
16+
"rmod",
17+
"divmod",
18+
"rdivmod",
19+
"pow",
20+
"rpow",
21+
"rshift",
22+
"rrshift",
23+
"lshift",
24+
"rlshift",
25+
"and",
26+
"rand",
27+
"or",
28+
"ror",
29+
"xor",
30+
"rxor",
31+
32+
# List/dict operations
33+
"contains",
34+
"getitem",
35+
"getslice",
36+
"setitem",
37+
"setslice",
38+
"delitem",
39+
"delslice",
40+
41+
# Unary operations
42+
"neg",
43+
"pos",
44+
"abs",
45+
"int",
46+
"long",
47+
"float",
48+
"oct",
49+
"hex",
50+
51+
# generic operations
52+
"init",
53+
"del",
54+
]
55+
56+
# These need to return something other than None
57+
# "coerce",
58+
# "hash",
59+
# "str",
60+
# "repr",
61+
62+
# These are separate because they can influence the test of other methods.
63+
# "getattr",
64+
# "setattr",
65+
# "delattr",
66+
67+
class AllTests:
68+
def __coerce__(self, *args):
69+
print "__coerce__:", args
70+
return (self,) + args
71+
72+
def __hash__(self, *args):
73+
print "__hash__:", args
74+
return id(self)
75+
76+
def __str__(self, *args):
77+
print "__str__:", args
78+
return "AllTests"
79+
80+
def __repr__(self, *args):
81+
print "__repr__:", args
82+
return "AllTests"
83+
84+
def __cmp__(self, *args):
85+
print "__cmp__:", args
86+
return 0
87+
88+
for method in testmeths:
89+
exec("""def __%(method)s__(self, *args):
90+
print "__%(method)s__:", args
91+
"""%locals(), AllTests.__dict__);
92+
93+
# this also tests __init__ of course.
94+
testme = AllTests()
95+
96+
# Binary operations
97+
98+
testme + 1
99+
1 + testme
100+
101+
testme - 1
102+
1 - testme
103+
104+
testme * 1
105+
1 * testme
106+
107+
testme / 1
108+
1 / testme
109+
110+
testme % 1
111+
1 % testme
112+
113+
divmod(testme,1)
114+
divmod(1, testme)
115+
116+
testme ** 1
117+
1 ** testme
118+
119+
testme >> 1
120+
1 >> testme
121+
122+
testme << 1
123+
1 << testme
124+
125+
testme & 1
126+
1 & testme
127+
128+
testme | 1
129+
1 | testme
130+
131+
testme ^ 1
132+
1 ^ testme
133+
134+
135+
# List/dict operations
136+
137+
1 in testme
138+
139+
testme[1]
140+
testme[1] = 1
141+
del testme[1]
142+
143+
testme[:42]
144+
testme[:42] = "The Answer"
145+
del testme[:42]
146+
147+
testme[2:1024:10]
148+
testme[2:1024:10] = "A lot"
149+
del testme[2:1024:10]
150+
151+
testme[:42, ..., :24:, 24, 100]
152+
testme[:42, ..., :24:, 24, 100] = "Strange"
153+
del testme[:42, ..., :24:, 24, 100]
154+
155+
156+
# Now remove the slice hooks to see if converting normal slices to slice
157+
# object works.
158+
159+
del AllTests.__getslice__
160+
del AllTests.__setslice__
161+
del AllTests.__delslice__
162+
163+
testme[:42]
164+
testme[:42] = "The Answer"
165+
del testme[:42]
166+
167+
168+
# Unary operations
169+
170+
-testme
171+
+testme
172+
abs(testme)
173+
int(testme)
174+
long(testme)
175+
float(testme)
176+
oct(testme)
177+
hex(testme)
178+
179+
180+
# And the rest...
181+
182+
hash(testme)
183+
repr(testme)
184+
str(testme)
185+
186+
testme == 1
187+
testme < 1
188+
testme > 1
189+
testme <> 1
190+
testme != 1
191+
1 == testme
192+
1 < testme
193+
1 > testme
194+
1 <> testme
195+
1 != testme
196+
197+
# This test has to be last (duh.)
198+
199+
del testme
200+
201+
202+
# Interfering tests
203+
204+
class ExtraTests:
205+
def __getattr__(self, *args):
206+
print "__getattr__:", args
207+
return "SomeVal"
208+
209+
def __setattr__(self, *args):
210+
print "__setattr__:", args
211+
212+
def __delattr__(self, *args):
213+
print "__delattr__:", args
214+
215+
testme = ExtraTests()
216+
testme.spam
217+
testme.eggs = "spam, spam, spam and ham"
218+
del testme.cardinal
219+

0 commit comments

Comments
 (0)