mirror of
https://github.com/python/cpython.git
synced 2025-12-04 08:34:25 +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
|
|
@ -1042,11 +1042,12 @@ objects. The first set of methods is used either to emulate a
|
||||||
sequence or to emulate a mapping; the difference is that for a
|
sequence or to emulate a mapping; the difference is that for a
|
||||||
sequence, the allowable keys should be the integers \var{k} for which
|
sequence, the allowable keys should be the integers \var{k} for which
|
||||||
\code{0 <= \var{k} < \var{N}} where \var{N} is the length of the
|
\code{0 <= \var{k} < \var{N}} where \var{N} is the length of the
|
||||||
sequence, and the method \method{__getslice__()} (see below) should be
|
sequence, or slice objects, which define a range of items. (For backwards
|
||||||
defined. It is also recommended that mappings provide methods
|
compatibility, the method \method{__getslice__()} (see below) can also be
|
||||||
\method{keys()}, \method{values()}, \method{items()},
|
defined to handle simple, but not extended slices.) It is also recommended
|
||||||
\method{has_key()}, \method{get()}, \method{clear()}, \method{copy()},
|
that mappings provide methods \method{keys()}, \method{values()},
|
||||||
and \method{update()} behaving similar to those for
|
\method{items()}, \method{has_key()}, \method{get()}, \method{clear()},
|
||||||
|
\method{copy()}, and \method{update()} behaving similar to those for
|
||||||
Python's standard dictionary objects; mutable sequences should provide
|
Python's standard dictionary objects; mutable sequences should provide
|
||||||
methods \method{append()}, \method{count()}, \method{index()},
|
methods \method{append()}, \method{count()}, \method{index()},
|
||||||
\method{insert()}, \method{pop()}, \method{remove()}, \method{reverse()}
|
\method{insert()}, \method{pop()}, \method{remove()}, \method{reverse()}
|
||||||
|
|
@ -1141,22 +1142,30 @@ If the instance does not implement the \method{__len__()} method, an
|
||||||
No guarantee is made that indexes adjusted this way are not still
|
No guarantee is made that indexes adjusted this way are not still
|
||||||
negative. Indexes which are greater than the length of the sequence
|
negative. Indexes which are greater than the length of the sequence
|
||||||
are not modified.
|
are not modified.
|
||||||
|
This method is deprecated. If no \method{__getslice__()} is found, a slice
|
||||||
|
object is created instead, and passed to \method{__getitem__()} instead.
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
\begin{methoddesc}[sequence object]{__setslice__}{self, i, j, sequence}
|
\begin{methoddesc}[sequence object]{__setslice__}{self, i, j, sequence}
|
||||||
Called to implement assignment to \code{\var{self}[\var{i}:\var{j}]}.
|
Called to implement assignment to \code{\var{self}[\var{i}:\var{j}]}.
|
||||||
Same notes for \var{i} and \var{j} as for \method{__getslice__()}.
|
Same notes for \var{i} and \var{j} as for \method{__getslice__()}.
|
||||||
|
|
||||||
|
This method is deprecated. If no \method{__setslice__()} is found, a slice
|
||||||
|
object is created instead, and passed to \method{__setitem__()} instead.
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
\begin{methoddesc}[sequence object]{__delslice__}{self, i, j}
|
\begin{methoddesc}[sequence object]{__delslice__}{self, i, j}
|
||||||
Called to implement deletion of \code{\var{self}[\var{i}:\var{j}]}.
|
Called to implement deletion of \code{\var{self}[\var{i}:\var{j}]}.
|
||||||
Same notes for \var{i} and \var{j} as for \method{__getslice__()}.
|
Same notes for \var{i} and \var{j} as for \method{__getslice__()}.
|
||||||
|
This method is deprecated. If no \method{__delslice__()} is found, a slice
|
||||||
|
object is created instead, and passed to \method{__delitem__()} instead.
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
Notice that these methods are only invoked when a single slice with a
|
Notice that these methods are only invoked when a single slice with a single
|
||||||
single colon is used. For slice operations involving extended slice
|
colon is used, and the slice method is available. For slice operations
|
||||||
notation, \method{__getitem__()}, \method{__setitem__()}
|
involving extended slice notation, or in absence of the slice methods,
|
||||||
or\method{__delitem__()} is called.
|
\method{__getitem__()}, \method{__setitem__()} or \method{__delitem__()} is
|
||||||
|
called with a slice object as argument.
|
||||||
|
|
||||||
|
|
||||||
\subsection{Emulating numeric types\label{numeric-types}}
|
\subsection{Emulating numeric types\label{numeric-types}}
|
||||||
|
|
|
||||||
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
|
||||||
|
|
||||||
|
|
@ -876,10 +876,29 @@ PySequence_GetItem(PyObject *s, int i)
|
||||||
return type_error("unindexable object");
|
return type_error("unindexable object");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sliceobj_from_intint(int i, int j)
|
||||||
|
{
|
||||||
|
PyObject *start, *end, *slice;
|
||||||
|
start = PyInt_FromLong((long)i);
|
||||||
|
if (!start)
|
||||||
|
return NULL;
|
||||||
|
end = PyInt_FromLong((long)j);
|
||||||
|
if (!end) {
|
||||||
|
Py_DECREF(start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
slice = PySlice_New(start, end, NULL);
|
||||||
|
Py_DECREF(start);
|
||||||
|
Py_DECREF(end);
|
||||||
|
return slice;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PySequence_GetSlice(PyObject *s, int i1, int i2)
|
PySequence_GetSlice(PyObject *s, int i1, int i2)
|
||||||
{
|
{
|
||||||
PySequenceMethods *m;
|
PySequenceMethods *m;
|
||||||
|
PyMappingMethods *mp;
|
||||||
|
|
||||||
if (!s) return null_error();
|
if (!s) return null_error();
|
||||||
|
|
||||||
|
|
@ -897,6 +916,14 @@ PySequence_GetSlice(PyObject *s, int i1, int i2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m->sq_slice(s, i1, i2);
|
return m->sq_slice(s, i1, i2);
|
||||||
|
} else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_subscript) {
|
||||||
|
PyObject *res;
|
||||||
|
PyObject *slice = sliceobj_from_intint(i1, i2);
|
||||||
|
if (!slice)
|
||||||
|
return NULL;
|
||||||
|
res = mp->mp_subscript(s, slice);
|
||||||
|
Py_DECREF(slice);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return type_error("unsliceable object");
|
return type_error("unsliceable object");
|
||||||
|
|
@ -960,6 +987,7 @@ int
|
||||||
PySequence_SetSlice(PyObject *s, int i1, int i2, PyObject *o)
|
PySequence_SetSlice(PyObject *s, int i1, int i2, PyObject *o)
|
||||||
{
|
{
|
||||||
PySequenceMethods *m;
|
PySequenceMethods *m;
|
||||||
|
PyMappingMethods *mp;
|
||||||
|
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
null_error();
|
null_error();
|
||||||
|
|
@ -980,7 +1008,16 @@ PySequence_SetSlice(PyObject *s, int i1, int i2, PyObject *o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m->sq_ass_slice(s, i1, i2, o);
|
return m->sq_ass_slice(s, i1, i2, o);
|
||||||
|
} else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_ass_subscript) {
|
||||||
|
int res;
|
||||||
|
PyObject *slice = sliceobj_from_intint(i1, i2);
|
||||||
|
if (!slice)
|
||||||
|
return -1;
|
||||||
|
res = mp->mp_ass_subscript(s, slice, o);
|
||||||
|
Py_DECREF(slice);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_error("object doesn't support slice assignment");
|
type_error("object doesn't support slice assignment");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -971,6 +971,27 @@ instance_item(PyInstanceObject *inst, int i)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sliceobj_from_intint(int i, int j)
|
||||||
|
{
|
||||||
|
PyObject *start, *end, *res;
|
||||||
|
|
||||||
|
start = PyInt_FromLong((long)i);
|
||||||
|
if (!start)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
end = PyInt_FromLong((long)j);
|
||||||
|
if (!end) {
|
||||||
|
Py_DECREF(start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
res = PySlice_New(start, end, NULL);
|
||||||
|
Py_DECREF(start);
|
||||||
|
Py_DECREF(end);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
instance_slice(PyInstanceObject *inst, int i, int j)
|
instance_slice(PyInstanceObject *inst, int i, int j)
|
||||||
{
|
{
|
||||||
|
|
@ -980,9 +1001,19 @@ instance_slice(PyInstanceObject *inst, int i, int j)
|
||||||
if (getslicestr == NULL)
|
if (getslicestr == NULL)
|
||||||
getslicestr = PyString_InternFromString("__getslice__");
|
getslicestr = PyString_InternFromString("__getslice__");
|
||||||
func = instance_getattr(inst, getslicestr);
|
func = instance_getattr(inst, getslicestr);
|
||||||
|
|
||||||
|
if (func == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
|
|
||||||
|
if (getitemstr == NULL)
|
||||||
|
getitemstr = PyString_InternFromString("__getitem__");
|
||||||
|
func = instance_getattr(inst, getitemstr);
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
arg = Py_BuildValue("(N)", sliceobj_from_intint(i, j));
|
||||||
|
} else
|
||||||
arg = Py_BuildValue("(ii)", i, j);
|
arg = Py_BuildValue("(ii)", i, j);
|
||||||
|
|
||||||
if (arg == NULL) {
|
if (arg == NULL) {
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1038,19 +1069,39 @@ instance_ass_slice(PyInstanceObject *inst, int i, int j, PyObject *value)
|
||||||
delslicestr =
|
delslicestr =
|
||||||
PyString_InternFromString("__delslice__");
|
PyString_InternFromString("__delslice__");
|
||||||
func = instance_getattr(inst, delslicestr);
|
func = instance_getattr(inst, delslicestr);
|
||||||
|
if (func == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
|
if (delitemstr == NULL)
|
||||||
|
delitemstr =
|
||||||
|
PyString_InternFromString("__delitem__");
|
||||||
|
func = instance_getattr(inst, delitemstr);
|
||||||
|
if (func == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
arg = Py_BuildValue("(N)",
|
||||||
|
sliceobj_from_intint(i, j));
|
||||||
|
} else
|
||||||
|
arg = Py_BuildValue("(ii)", i, j);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (setslicestr == NULL)
|
if (setslicestr == NULL)
|
||||||
setslicestr =
|
setslicestr =
|
||||||
PyString_InternFromString("__setslice__");
|
PyString_InternFromString("__setslice__");
|
||||||
func = instance_getattr(inst, setslicestr);
|
func = instance_getattr(inst, setslicestr);
|
||||||
}
|
if (func == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
|
if (setitemstr == NULL)
|
||||||
|
setitemstr =
|
||||||
|
PyString_InternFromString("__setitem__");
|
||||||
|
func = instance_getattr(inst, setitemstr);
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (value == NULL)
|
|
||||||
arg = Py_BuildValue("(ii)", i, j);
|
arg = Py_BuildValue("(NO)",
|
||||||
else
|
sliceobj_from_intint(i, j), value);
|
||||||
|
} else
|
||||||
arg = Py_BuildValue("(iiO)", i, j, value);
|
arg = Py_BuildValue("(iiO)", i, j, value);
|
||||||
|
}
|
||||||
if (arg == NULL) {
|
if (arg == NULL) {
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue