symbian-qemu-0.9.1-12/python-2.6.1/Modules/operator.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 
       
     2 #include "Python.h"
       
     3 
       
     4 PyDoc_STRVAR(operator_doc,
       
     5 "Operator interface.\n\
       
     6 \n\
       
     7 This module exports a set of functions implemented in C corresponding\n\
       
     8 to the intrinsic operators of Python.  For example, operator.add(x, y)\n\
       
     9 is equivalent to the expression x+y.  The function names are those\n\
       
    10 used for special class methods; variants without leading and trailing\n\
       
    11 '__' are also provided for convenience.");
       
    12 
       
    13 #define spam1(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a1) { \
       
    14   return AOP(a1); }
       
    15 
       
    16 #define spam2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
       
    17   PyObject *a1, *a2; \
       
    18   if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
       
    19   return AOP(a1,a2); }
       
    20 
       
    21 #define spamoi(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
       
    22   PyObject *a1; int a2; \
       
    23   if(! PyArg_ParseTuple(a,"Oi:" #OP,&a1,&a2)) return NULL; \
       
    24   return AOP(a1,a2); }
       
    25 
       
    26 #define spam2n(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
       
    27   PyObject *a1, *a2; \
       
    28   if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
       
    29   if(-1 == AOP(a1,a2)) return NULL; \
       
    30   Py_INCREF(Py_None); \
       
    31   return Py_None; }
       
    32 
       
    33 #define spam3n(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
       
    34   PyObject *a1, *a2, *a3; \
       
    35   if(! PyArg_UnpackTuple(a,#OP,3,3,&a1,&a2,&a3)) return NULL; \
       
    36   if(-1 == AOP(a1,a2,a3)) return NULL; \
       
    37   Py_INCREF(Py_None); \
       
    38   return Py_None; }
       
    39 
       
    40 #define spami(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a1) { \
       
    41   long r; \
       
    42   if(-1 == (r=AOP(a1))) return NULL; \
       
    43   return PyBool_FromLong(r); }
       
    44 
       
    45 #define spami2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
       
    46   PyObject *a1, *a2; long r; \
       
    47   if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
       
    48   if(-1 == (r=AOP(a1,a2))) return NULL; \
       
    49   return PyInt_FromLong(r); }
       
    50 
       
    51 #define spamn2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
       
    52   PyObject *a1, *a2; Py_ssize_t r; \
       
    53   if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
       
    54   if(-1 == (r=AOP(a1,a2))) return NULL; \
       
    55   return PyInt_FromSsize_t(r); }
       
    56 
       
    57 #define spami2b(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
       
    58   PyObject *a1, *a2; long r; \
       
    59   if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
       
    60   if(-1 == (r=AOP(a1,a2))) return NULL; \
       
    61   return PyBool_FromLong(r); }
       
    62 
       
    63 #define spamrc(OP,A) static PyObject *OP(PyObject *s, PyObject *a) { \
       
    64   PyObject *a1, *a2; \
       
    65   if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
       
    66   return PyObject_RichCompare(a1,a2,A); }
       
    67 
       
    68 spami(isCallable       , PyCallable_Check)
       
    69 spami(isNumberType     , PyNumber_Check)
       
    70 spami(truth            , PyObject_IsTrue)
       
    71 spam2(op_add           , PyNumber_Add)
       
    72 spam2(op_sub           , PyNumber_Subtract)
       
    73 spam2(op_mul           , PyNumber_Multiply)
       
    74 spam2(op_div           , PyNumber_Divide)
       
    75 spam2(op_floordiv      , PyNumber_FloorDivide)
       
    76 spam2(op_truediv       , PyNumber_TrueDivide)
       
    77 spam2(op_mod           , PyNumber_Remainder)
       
    78 spam1(op_neg           , PyNumber_Negative)
       
    79 spam1(op_pos           , PyNumber_Positive)
       
    80 spam1(op_abs           , PyNumber_Absolute)
       
    81 spam1(op_inv           , PyNumber_Invert)
       
    82 spam1(op_invert        , PyNumber_Invert)
       
    83 spam2(op_lshift        , PyNumber_Lshift)
       
    84 spam2(op_rshift        , PyNumber_Rshift)
       
    85 spami(op_not_          , PyObject_Not)
       
    86 spam2(op_and_          , PyNumber_And)
       
    87 spam2(op_xor           , PyNumber_Xor)
       
    88 spam2(op_or_           , PyNumber_Or)
       
    89 spam2(op_iadd          , PyNumber_InPlaceAdd)
       
    90 spam2(op_isub          , PyNumber_InPlaceSubtract)
       
    91 spam2(op_imul          , PyNumber_InPlaceMultiply)
       
    92 spam2(op_idiv          , PyNumber_InPlaceDivide)
       
    93 spam2(op_ifloordiv     , PyNumber_InPlaceFloorDivide)
       
    94 spam2(op_itruediv      , PyNumber_InPlaceTrueDivide)
       
    95 spam2(op_imod          , PyNumber_InPlaceRemainder)
       
    96 spam2(op_ilshift       , PyNumber_InPlaceLshift)
       
    97 spam2(op_irshift       , PyNumber_InPlaceRshift)
       
    98 spam2(op_iand          , PyNumber_InPlaceAnd)
       
    99 spam2(op_ixor          , PyNumber_InPlaceXor)
       
   100 spam2(op_ior           , PyNumber_InPlaceOr)
       
   101 spami(isSequenceType   , PySequence_Check)
       
   102 spam2(op_concat        , PySequence_Concat)
       
   103 spamoi(op_repeat       , PySequence_Repeat)
       
   104 spam2(op_iconcat       , PySequence_InPlaceConcat)
       
   105 spamoi(op_irepeat      , PySequence_InPlaceRepeat)
       
   106 spami2b(op_contains     , PySequence_Contains)
       
   107 spami2b(sequenceIncludes, PySequence_Contains)
       
   108 spamn2(indexOf         , PySequence_Index)
       
   109 spamn2(countOf         , PySequence_Count)
       
   110 spami(isMappingType    , PyMapping_Check)
       
   111 spam2(op_getitem       , PyObject_GetItem)
       
   112 spam2n(op_delitem       , PyObject_DelItem)
       
   113 spam3n(op_setitem      , PyObject_SetItem)
       
   114 spamrc(op_lt           , Py_LT)
       
   115 spamrc(op_le           , Py_LE)
       
   116 spamrc(op_eq           , Py_EQ)
       
   117 spamrc(op_ne           , Py_NE)
       
   118 spamrc(op_gt           , Py_GT)
       
   119 spamrc(op_ge           , Py_GE)
       
   120 
       
   121 static PyObject*
       
   122 op_pow(PyObject *s, PyObject *a)
       
   123 {
       
   124 	PyObject *a1, *a2;
       
   125 	if (PyArg_UnpackTuple(a,"pow", 2, 2, &a1, &a2))
       
   126 		return PyNumber_Power(a1, a2, Py_None);
       
   127 	return NULL;
       
   128 }
       
   129 
       
   130 static PyObject*
       
   131 op_ipow(PyObject *s, PyObject *a)
       
   132 {
       
   133 	PyObject *a1, *a2;
       
   134 	if (PyArg_UnpackTuple(a,"ipow", 2, 2, &a1, &a2))
       
   135 		return PyNumber_InPlacePower(a1, a2, Py_None);
       
   136 	return NULL;
       
   137 }
       
   138 
       
   139 static PyObject *
       
   140 op_index(PyObject *s, PyObject *a)
       
   141 {
       
   142 	return PyNumber_Index(a);
       
   143 }
       
   144 
       
   145 static PyObject*
       
   146 is_(PyObject *s, PyObject *a)
       
   147 {
       
   148 	PyObject *a1, *a2, *result = NULL;
       
   149 	if (PyArg_UnpackTuple(a,"is_", 2, 2, &a1, &a2)) {
       
   150 		result = (a1 == a2) ? Py_True : Py_False;
       
   151 		Py_INCREF(result);
       
   152 	}
       
   153 	return result;
       
   154 }
       
   155 
       
   156 static PyObject*
       
   157 is_not(PyObject *s, PyObject *a)
       
   158 {
       
   159 	PyObject *a1, *a2, *result = NULL;
       
   160 	if (PyArg_UnpackTuple(a,"is_not", 2, 2, &a1, &a2)) {
       
   161 		result = (a1 != a2) ? Py_True : Py_False;
       
   162 		Py_INCREF(result);
       
   163 	}
       
   164 	return result;
       
   165 }
       
   166 
       
   167 static PyObject*
       
   168 op_getslice(PyObject *s, PyObject *a)
       
   169 {
       
   170         PyObject *a1;
       
   171         Py_ssize_t a2, a3;
       
   172 
       
   173         if (!PyArg_ParseTuple(a, "Onn:getslice", &a1, &a2, &a3))
       
   174                 return NULL;
       
   175         return PySequence_GetSlice(a1, a2, a3);
       
   176 }
       
   177 
       
   178 static PyObject*
       
   179 op_setslice(PyObject *s, PyObject *a)
       
   180 {
       
   181         PyObject *a1, *a4;
       
   182         Py_ssize_t a2, a3;
       
   183 
       
   184         if (!PyArg_ParseTuple(a, "OnnO:setslice", &a1, &a2, &a3, &a4))
       
   185                 return NULL;
       
   186 
       
   187         if (-1 == PySequence_SetSlice(a1, a2, a3, a4))
       
   188                 return NULL;
       
   189 
       
   190 	Py_RETURN_NONE;
       
   191 }
       
   192 
       
   193 static PyObject*
       
   194 op_delslice(PyObject *s, PyObject *a)
       
   195 {
       
   196         PyObject *a1;
       
   197         Py_ssize_t a2, a3;
       
   198 
       
   199         if (!PyArg_ParseTuple(a, "Onn:delslice", &a1, &a2, &a3))
       
   200                 return NULL;
       
   201 
       
   202         if (-1 == PySequence_DelSlice(a1, a2, a3))
       
   203                 return NULL;
       
   204 
       
   205 	Py_RETURN_NONE;
       
   206 }
       
   207 
       
   208 #undef spam1
       
   209 #undef spam2
       
   210 #undef spam1o
       
   211 #undef spam1o
       
   212 #define spam1(OP,DOC) {#OP, OP, METH_VARARGS, PyDoc_STR(DOC)},
       
   213 #define spam2(OP,ALTOP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, \
       
   214 			   {#ALTOP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, 
       
   215 #define spam1o(OP,DOC) {#OP, OP, METH_O, PyDoc_STR(DOC)},
       
   216 #define spam2o(OP,ALTOP,DOC) {#OP, op_##OP, METH_O, PyDoc_STR(DOC)}, \
       
   217 			   {#ALTOP, op_##OP, METH_O, PyDoc_STR(DOC)}, 
       
   218 
       
   219 static struct PyMethodDef operator_methods[] = {
       
   220 
       
   221 spam1o(isCallable,
       
   222  "isCallable(a) -- Same as callable(a).")
       
   223 spam1o(isNumberType,
       
   224  "isNumberType(a) -- Return True if a has a numeric type, False otherwise.")
       
   225 spam1o(isSequenceType,
       
   226  "isSequenceType(a) -- Return True if a has a sequence type, False otherwise.")
       
   227 spam1o(truth,
       
   228  "truth(a) -- Return True if a is true, False otherwise.")
       
   229 spam2(contains,__contains__,
       
   230  "contains(a, b) -- Same as b in a (note reversed operands).")
       
   231 spam1(sequenceIncludes,
       
   232  "sequenceIncludes(a, b) -- Same as b in a (note reversed operands; deprecated).")
       
   233 spam1(indexOf,
       
   234  "indexOf(a, b) -- Return the first index of b in a.")
       
   235 spam1(countOf,
       
   236  "countOf(a, b) -- Return the number of times b occurs in a.")
       
   237 spam1o(isMappingType,
       
   238  "isMappingType(a) -- Return True if a has a mapping type, False otherwise.")
       
   239 
       
   240 spam1(is_, "is_(a, b) -- Same as a is b.")
       
   241 spam1(is_not, "is_not(a, b) -- Same as a is not b.")
       
   242 spam2o(index, __index__, "index(a) -- Same as a.__index__()")
       
   243 spam2(add,__add__, "add(a, b) -- Same as a + b.")
       
   244 spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")
       
   245 spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")
       
   246 spam2(div,__div__, "div(a, b) -- Same as a / b when __future__.division is not in effect.")
       
   247 spam2(floordiv,__floordiv__, "floordiv(a, b) -- Same as a // b.")
       
   248 spam2(truediv,__truediv__, "truediv(a, b) -- Same as a / b when __future__.division is in effect.")
       
   249 spam2(mod,__mod__, "mod(a, b) -- Same as a % b.")
       
   250 spam2o(neg,__neg__, "neg(a) -- Same as -a.")
       
   251 spam2o(pos,__pos__, "pos(a) -- Same as +a.")
       
   252 spam2o(abs,__abs__, "abs(a) -- Same as abs(a).")
       
   253 spam2o(inv,__inv__, "inv(a) -- Same as ~a.")
       
   254 spam2o(invert,__invert__, "invert(a) -- Same as ~a.")
       
   255 spam2(lshift,__lshift__, "lshift(a, b) -- Same as a << b.")
       
   256 spam2(rshift,__rshift__, "rshift(a, b) -- Same as a >> b.")
       
   257 spam2o(not_,__not__, "not_(a) -- Same as not a.")
       
   258 spam2(and_,__and__, "and_(a, b) -- Same as a & b.")
       
   259 spam2(xor,__xor__, "xor(a, b) -- Same as a ^ b.")
       
   260 spam2(or_,__or__, "or_(a, b) -- Same as a | b.")
       
   261 spam2(iadd,__iadd__, "iadd(a, b) -- Same as a += b.")
       
   262 spam2(isub,__isub__, "isub(a, b) -- Same as a -= b.")
       
   263 spam2(imul,__imul__, "imul(a, b) -- Same as a *= b.")
       
   264 spam2(idiv,__idiv__, "idiv(a, b) -- Same as a /= b when __future__.division is not in effect.")
       
   265 spam2(ifloordiv,__ifloordiv__, "ifloordiv(a, b) -- Same as a //= b.")
       
   266 spam2(itruediv,__itruediv__, "itruediv(a, b) -- Same as a /= b when __future__.division is in effect.")
       
   267 spam2(imod,__imod__, "imod(a, b) -- Same as a %= b.")
       
   268 spam2(ilshift,__ilshift__, "ilshift(a, b) -- Same as a <<= b.")
       
   269 spam2(irshift,__irshift__, "irshift(a, b) -- Same as a >>= b.")
       
   270 spam2(iand,__iand__, "iand(a, b) -- Same as a &= b.")
       
   271 spam2(ixor,__ixor__, "ixor(a, b) -- Same as a ^= b.")
       
   272 spam2(ior,__ior__, "ior(a, b) -- Same as a |= b.")
       
   273 spam2(concat,__concat__,
       
   274  "concat(a, b) -- Same as a + b, for a and b sequences.")
       
   275 spam2(repeat,__repeat__,
       
   276  "repeat(a, b) -- Return a * b, where a is a sequence, and b is an integer.")
       
   277 spam2(iconcat,__iconcat__,
       
   278  "iconcat(a, b) -- Same as a += b, for a and b sequences.")
       
   279 spam2(irepeat,__irepeat__,
       
   280  "irepeat(a, b) -- Same as a *= b, where a is a sequence, and b is an integer.")
       
   281 spam2(getitem,__getitem__,
       
   282  "getitem(a, b) -- Same as a[b].")
       
   283 spam2(setitem,__setitem__,
       
   284  "setitem(a, b, c) -- Same as a[b] = c.")
       
   285 spam2(delitem,__delitem__,
       
   286  "delitem(a, b) -- Same as del a[b].")
       
   287 spam2(pow,__pow__, "pow(a, b) -- Same as a ** b.")
       
   288 spam2(ipow,__ipow__, "ipow(a, b) -- Same as a **= b.")
       
   289 spam2(getslice,__getslice__,
       
   290  "getslice(a, b, c) -- Same as a[b:c].")
       
   291 spam2(setslice,__setslice__,
       
   292 "setslice(a, b, c, d) -- Same as a[b:c] = d.")
       
   293 spam2(delslice,__delslice__,
       
   294 "delslice(a, b, c) -- Same as del a[b:c].")
       
   295 spam2(lt,__lt__, "lt(a, b) -- Same as a<b.")
       
   296 spam2(le,__le__, "le(a, b) -- Same as a<=b.")
       
   297 spam2(eq,__eq__, "eq(a, b) -- Same as a==b.")
       
   298 spam2(ne,__ne__, "ne(a, b) -- Same as a!=b.")
       
   299 spam2(gt,__gt__, "gt(a, b) -- Same as a>b.")
       
   300 spam2(ge,__ge__, "ge(a, b) -- Same as a>=b.")
       
   301 
       
   302 	{NULL,		NULL}		/* sentinel */
       
   303 
       
   304 };
       
   305 
       
   306 /* itemgetter object **********************************************************/
       
   307 
       
   308 typedef struct {
       
   309 	PyObject_HEAD
       
   310 	Py_ssize_t nitems;
       
   311 	PyObject *item;
       
   312 } itemgetterobject;
       
   313 
       
   314 static PyTypeObject itemgetter_type;
       
   315 
       
   316 static PyObject *
       
   317 itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
       
   318 {
       
   319 	itemgetterobject *ig;
       
   320 	PyObject *item;
       
   321 	Py_ssize_t nitems;
       
   322 
       
   323 	if (!_PyArg_NoKeywords("itemgetter()", kwds))
       
   324 		return NULL;
       
   325 
       
   326 	nitems = PyTuple_GET_SIZE(args);
       
   327 	if (nitems <= 1) {
       
   328 		if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &item))
       
   329 			return NULL;
       
   330 	} else 
       
   331 		item = args;
       
   332 
       
   333 	/* create itemgetterobject structure */
       
   334 	ig = PyObject_GC_New(itemgetterobject, &itemgetter_type);
       
   335 	if (ig == NULL) 
       
   336 		return NULL;	
       
   337 	
       
   338 	Py_INCREF(item);
       
   339 	ig->item = item;
       
   340 	ig->nitems = nitems;
       
   341 
       
   342 	PyObject_GC_Track(ig);
       
   343 	return (PyObject *)ig;
       
   344 }
       
   345 
       
   346 static void
       
   347 itemgetter_dealloc(itemgetterobject *ig)
       
   348 {
       
   349 	PyObject_GC_UnTrack(ig);
       
   350 	Py_XDECREF(ig->item);
       
   351 	PyObject_GC_Del(ig);
       
   352 }
       
   353 
       
   354 static int
       
   355 itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
       
   356 {
       
   357 	Py_VISIT(ig->item);
       
   358 	return 0;
       
   359 }
       
   360 
       
   361 static PyObject *
       
   362 itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw)
       
   363 {
       
   364 	PyObject *obj, *result;
       
   365 	Py_ssize_t i, nitems=ig->nitems;
       
   366 
       
   367 	if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))
       
   368 		return NULL;
       
   369 	if (nitems == 1)
       
   370 		return PyObject_GetItem(obj, ig->item);
       
   371 
       
   372 	assert(PyTuple_Check(ig->item));
       
   373 	assert(PyTuple_GET_SIZE(ig->item) == nitems);
       
   374 
       
   375 	result = PyTuple_New(nitems);
       
   376 	if (result == NULL)
       
   377 		return NULL;
       
   378 
       
   379 	for (i=0 ; i < nitems ; i++) {
       
   380 		PyObject *item, *val;
       
   381 		item = PyTuple_GET_ITEM(ig->item, i);
       
   382 		val = PyObject_GetItem(obj, item);
       
   383 		if (val == NULL) {
       
   384 			Py_DECREF(result);
       
   385 			return NULL;
       
   386 		}
       
   387 		PyTuple_SET_ITEM(result, i, val);
       
   388 	}
       
   389 	return result;
       
   390 }
       
   391 
       
   392 PyDoc_STRVAR(itemgetter_doc,
       
   393 "itemgetter(item, ...) --> itemgetter object\n\
       
   394 \n\
       
   395 Return a callable object that fetches the given item(s) from its operand.\n\
       
   396 After, f=itemgetter(2), the call f(r) returns r[2].\n\
       
   397 After, g=itemgetter(2,5,3), the call g(r) returns (r[2], r[5], r[3])");
       
   398 
       
   399 static PyTypeObject itemgetter_type = {
       
   400 	PyVarObject_HEAD_INIT(NULL, 0)
       
   401 	"operator.itemgetter",		/* tp_name */
       
   402 	sizeof(itemgetterobject),	/* tp_basicsize */
       
   403 	0,				/* tp_itemsize */
       
   404 	/* methods */
       
   405 	(destructor)itemgetter_dealloc,	/* tp_dealloc */
       
   406 	0,				/* tp_print */
       
   407 	0,				/* tp_getattr */
       
   408 	0,				/* tp_setattr */
       
   409 	0,				/* tp_compare */
       
   410 	0,				/* tp_repr */
       
   411 	0,				/* tp_as_number */
       
   412 	0,				/* tp_as_sequence */
       
   413 	0,				/* tp_as_mapping */
       
   414 	0,				/* tp_hash */
       
   415 	(ternaryfunc)itemgetter_call,	/* tp_call */
       
   416 	0,				/* tp_str */
       
   417 	PyObject_GenericGetAttr,	/* tp_getattro */
       
   418 	0,				/* tp_setattro */
       
   419 	0,				/* tp_as_buffer */
       
   420 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,	/* tp_flags */
       
   421 	itemgetter_doc,			/* tp_doc */
       
   422 	(traverseproc)itemgetter_traverse,	/* tp_traverse */
       
   423 	0,				/* tp_clear */
       
   424 	0,				/* tp_richcompare */
       
   425 	0,				/* tp_weaklistoffset */
       
   426 	0,				/* tp_iter */
       
   427 	0,				/* tp_iternext */
       
   428 	0,				/* tp_methods */
       
   429 	0,				/* tp_members */
       
   430 	0,				/* tp_getset */
       
   431 	0,				/* tp_base */
       
   432 	0,				/* tp_dict */
       
   433 	0,				/* tp_descr_get */
       
   434 	0,				/* tp_descr_set */
       
   435 	0,				/* tp_dictoffset */
       
   436 	0,				/* tp_init */
       
   437 	0,				/* tp_alloc */
       
   438 	itemgetter_new,			/* tp_new */
       
   439 	0,				/* tp_free */
       
   440 };
       
   441 
       
   442 
       
   443 /* attrgetter object **********************************************************/
       
   444 
       
   445 typedef struct {
       
   446 	PyObject_HEAD
       
   447 	Py_ssize_t nattrs;
       
   448 	PyObject *attr;
       
   449 } attrgetterobject;
       
   450 
       
   451 static PyTypeObject attrgetter_type;
       
   452 
       
   453 static PyObject *
       
   454 attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
       
   455 {
       
   456 	attrgetterobject *ag;
       
   457 	PyObject *attr;
       
   458 	Py_ssize_t nattrs;
       
   459 
       
   460 	if (!_PyArg_NoKeywords("attrgetter()", kwds))
       
   461 		return NULL;
       
   462 
       
   463 	nattrs = PyTuple_GET_SIZE(args);
       
   464 	if (nattrs <= 1) {
       
   465 		if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &attr))
       
   466 			return NULL;
       
   467 	} else 
       
   468 		attr = args;
       
   469 
       
   470 	/* create attrgetterobject structure */
       
   471 	ag = PyObject_GC_New(attrgetterobject, &attrgetter_type);
       
   472 	if (ag == NULL) 
       
   473 		return NULL;	
       
   474 	
       
   475 	Py_INCREF(attr);
       
   476 	ag->attr = attr;
       
   477 	ag->nattrs = nattrs;
       
   478 
       
   479 	PyObject_GC_Track(ag);
       
   480 	return (PyObject *)ag;
       
   481 }
       
   482 
       
   483 static void
       
   484 attrgetter_dealloc(attrgetterobject *ag)
       
   485 {
       
   486 	PyObject_GC_UnTrack(ag);
       
   487 	Py_XDECREF(ag->attr);
       
   488 	PyObject_GC_Del(ag);
       
   489 }
       
   490 
       
   491 static int
       
   492 attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
       
   493 {
       
   494 	Py_VISIT(ag->attr);
       
   495 	return 0;
       
   496 }
       
   497 
       
   498 static PyObject *
       
   499 dotted_getattr(PyObject *obj, PyObject *attr)
       
   500 {
       
   501 	char *s, *p;
       
   502 
       
   503 #ifdef Py_USING_UNICODE
       
   504 	if (PyUnicode_Check(attr)) {
       
   505 		attr = _PyUnicode_AsDefaultEncodedString(attr, NULL);
       
   506 		if (attr == NULL)
       
   507 			return NULL;
       
   508 	}
       
   509 #endif
       
   510 	
       
   511 	if (!PyString_Check(attr)) {
       
   512 		PyErr_SetString(PyExc_TypeError,
       
   513 				"attribute name must be a string");
       
   514 		return NULL;
       
   515 	}
       
   516 
       
   517 	s = PyString_AS_STRING(attr);
       
   518 	Py_INCREF(obj);
       
   519 	for (;;) {
       
   520 		PyObject *newobj, *str;
       
   521 		p = strchr(s, '.');
       
   522 		str = p ? PyString_FromStringAndSize(s, (p-s)) : 
       
   523 			  PyString_FromString(s);
       
   524 		if (str == NULL) {
       
   525 			Py_DECREF(obj);
       
   526 			return NULL;
       
   527 		}
       
   528 		newobj = PyObject_GetAttr(obj, str);
       
   529 		Py_DECREF(str);
       
   530 		Py_DECREF(obj);
       
   531 		if (newobj == NULL)
       
   532 			return NULL;
       
   533 		obj = newobj;
       
   534 		if (p == NULL) break;
       
   535 		s = p+1;
       
   536 	}
       
   537 
       
   538 	return obj;
       
   539 }
       
   540 
       
   541 static PyObject *
       
   542 attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
       
   543 {
       
   544 	PyObject *obj, *result;
       
   545 	Py_ssize_t i, nattrs=ag->nattrs;
       
   546 
       
   547 	if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))
       
   548 		return NULL;
       
   549 	if (ag->nattrs == 1)
       
   550 		return dotted_getattr(obj, ag->attr);
       
   551 
       
   552 	assert(PyTuple_Check(ag->attr));
       
   553 	assert(PyTuple_GET_SIZE(ag->attr) == nattrs);
       
   554 
       
   555 	result = PyTuple_New(nattrs);
       
   556 	if (result == NULL)
       
   557 		return NULL;
       
   558 
       
   559 	for (i=0 ; i < nattrs ; i++) {
       
   560 		PyObject *attr, *val;
       
   561 		attr = PyTuple_GET_ITEM(ag->attr, i);
       
   562 		val = dotted_getattr(obj, attr);
       
   563 		if (val == NULL) {
       
   564 			Py_DECREF(result);
       
   565 			return NULL;
       
   566 		}
       
   567 		PyTuple_SET_ITEM(result, i, val);
       
   568 	}
       
   569 	return result;
       
   570 }
       
   571 
       
   572 PyDoc_STRVAR(attrgetter_doc,
       
   573 "attrgetter(attr, ...) --> attrgetter object\n\
       
   574 \n\
       
   575 Return a callable object that fetches the given attribute(s) from its operand.\n\
       
   576 After, f=attrgetter('name'), the call f(r) returns r.name.\n\
       
   577 After, g=attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
       
   578 After, h=attrgetter('name.first', 'name.last'), the call h(r) returns\n\
       
   579 (r.name.first, r.name.last).");
       
   580 
       
   581 static PyTypeObject attrgetter_type = {
       
   582 	PyVarObject_HEAD_INIT(NULL, 0)
       
   583 	"operator.attrgetter",		/* tp_name */
       
   584 	sizeof(attrgetterobject),	/* tp_basicsize */
       
   585 	0,				/* tp_itemsize */
       
   586 	/* methods */
       
   587 	(destructor)attrgetter_dealloc,	/* tp_dealloc */
       
   588 	0,				/* tp_print */
       
   589 	0,				/* tp_getattr */
       
   590 	0,				/* tp_setattr */
       
   591 	0,				/* tp_compare */
       
   592 	0,				/* tp_repr */
       
   593 	0,				/* tp_as_number */
       
   594 	0,				/* tp_as_sequence */
       
   595 	0,				/* tp_as_mapping */
       
   596 	0,				/* tp_hash */
       
   597 	(ternaryfunc)attrgetter_call,	/* tp_call */
       
   598 	0,				/* tp_str */
       
   599 	PyObject_GenericGetAttr,	/* tp_getattro */
       
   600 	0,				/* tp_setattro */
       
   601 	0,				/* tp_as_buffer */
       
   602 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,	/* tp_flags */
       
   603 	attrgetter_doc,			/* tp_doc */
       
   604 	(traverseproc)attrgetter_traverse,	/* tp_traverse */
       
   605 	0,				/* tp_clear */
       
   606 	0,				/* tp_richcompare */
       
   607 	0,				/* tp_weaklistoffset */
       
   608 	0,				/* tp_iter */
       
   609 	0,				/* tp_iternext */
       
   610 	0,				/* tp_methods */
       
   611 	0,				/* tp_members */
       
   612 	0,				/* tp_getset */
       
   613 	0,				/* tp_base */
       
   614 	0,				/* tp_dict */
       
   615 	0,				/* tp_descr_get */
       
   616 	0,				/* tp_descr_set */
       
   617 	0,				/* tp_dictoffset */
       
   618 	0,				/* tp_init */
       
   619 	0,				/* tp_alloc */
       
   620 	attrgetter_new,			/* tp_new */
       
   621 	0,				/* tp_free */
       
   622 };
       
   623 
       
   624 
       
   625 /* methodcaller object **********************************************************/
       
   626 
       
   627 typedef struct {
       
   628 	PyObject_HEAD
       
   629 	PyObject *name;
       
   630 	PyObject *args;
       
   631 	PyObject *kwds;
       
   632 } methodcallerobject;
       
   633 
       
   634 static PyTypeObject methodcaller_type;
       
   635 
       
   636 static PyObject *
       
   637 methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
       
   638 {
       
   639 	methodcallerobject *mc;
       
   640 	PyObject *name, *newargs;
       
   641 
       
   642 	if (PyTuple_GET_SIZE(args) < 1) {
       
   643 		PyErr_SetString(PyExc_TypeError, "methodcaller needs at least "
       
   644 				"one argument, the method name");
       
   645 		return NULL;
       
   646 	}
       
   647 
       
   648 	/* create methodcallerobject structure */
       
   649 	mc = PyObject_GC_New(methodcallerobject, &methodcaller_type);
       
   650 	if (mc == NULL) 
       
   651 		return NULL;	
       
   652 
       
   653 	newargs = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
       
   654 	if (newargs == NULL) {
       
   655 		Py_DECREF(mc);
       
   656 		return NULL;
       
   657 	}
       
   658 	mc->args = newargs;
       
   659 
       
   660 	name = PyTuple_GET_ITEM(args, 0);
       
   661 	Py_INCREF(name);
       
   662 	mc->name = name;
       
   663 
       
   664 	Py_XINCREF(kwds);
       
   665 	mc->kwds = kwds;
       
   666 
       
   667 	PyObject_GC_Track(mc);
       
   668 	return (PyObject *)mc;
       
   669 }
       
   670 
       
   671 static void
       
   672 methodcaller_dealloc(methodcallerobject *mc)
       
   673 {
       
   674 	PyObject_GC_UnTrack(mc);
       
   675 	Py_XDECREF(mc->name);
       
   676 	Py_XDECREF(mc->args);
       
   677 	Py_XDECREF(mc->kwds);
       
   678 	PyObject_GC_Del(mc);
       
   679 }
       
   680 
       
   681 static int
       
   682 methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
       
   683 {
       
   684 	Py_VISIT(mc->args);
       
   685 	Py_VISIT(mc->kwds);
       
   686 	return 0;
       
   687 }
       
   688 
       
   689 static PyObject *
       
   690 methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
       
   691 {
       
   692 	PyObject *method, *obj, *result;
       
   693 
       
   694 	if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))
       
   695 		return NULL;
       
   696 	method = PyObject_GetAttr(obj, mc->name);
       
   697 	if (method == NULL)
       
   698 		return NULL;
       
   699 	result = PyObject_Call(method, mc->args, mc->kwds);
       
   700 	Py_DECREF(method);
       
   701 	return result;
       
   702 }
       
   703 
       
   704 PyDoc_STRVAR(methodcaller_doc,
       
   705 "methodcaller(name, ...) --> methodcaller object\n\
       
   706 \n\
       
   707 Return a callable object that calls the given method on its operand.\n\
       
   708 After, f = methodcaller('name'), the call f(r) returns r.name().\n\
       
   709 After, g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
       
   710 r.name('date', foo=1).");
       
   711 
       
   712 static PyTypeObject methodcaller_type = {
       
   713 	PyVarObject_HEAD_INIT(NULL, 0)
       
   714 	"operator.methodcaller",	/* tp_name */
       
   715 	sizeof(methodcallerobject),	/* tp_basicsize */
       
   716 	0,				/* tp_itemsize */
       
   717 	/* methods */
       
   718 	(destructor)methodcaller_dealloc, /* tp_dealloc */
       
   719 	0,				/* tp_print */
       
   720 	0,				/* tp_getattr */
       
   721 	0,				/* tp_setattr */
       
   722 	0,				/* tp_compare */
       
   723 	0,				/* tp_repr */
       
   724 	0,				/* tp_as_number */
       
   725 	0,				/* tp_as_sequence */
       
   726 	0,				/* tp_as_mapping */
       
   727 	0,				/* tp_hash */
       
   728 	(ternaryfunc)methodcaller_call,	/* tp_call */
       
   729 	0,				/* tp_str */
       
   730 	PyObject_GenericGetAttr,	/* tp_getattro */
       
   731 	0,				/* tp_setattro */
       
   732 	0,				/* tp_as_buffer */
       
   733 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
       
   734 	methodcaller_doc,			/* tp_doc */
       
   735 	(traverseproc)methodcaller_traverse,	/* tp_traverse */
       
   736 	0,				/* tp_clear */
       
   737 	0,				/* tp_richcompare */
       
   738 	0,				/* tp_weaklistoffset */
       
   739 	0,				/* tp_iter */
       
   740 	0,				/* tp_iternext */
       
   741 	0,				/* tp_methods */
       
   742 	0,				/* tp_members */
       
   743 	0,				/* tp_getset */
       
   744 	0,				/* tp_base */
       
   745 	0,				/* tp_dict */
       
   746 	0,				/* tp_descr_get */
       
   747 	0,				/* tp_descr_set */
       
   748 	0,				/* tp_dictoffset */
       
   749 	0,				/* tp_init */
       
   750 	0,				/* tp_alloc */
       
   751 	methodcaller_new,		/* tp_new */
       
   752 	0,				/* tp_free */
       
   753 };
       
   754 
       
   755 
       
   756 /* Initialization function for the module (*must* be called initoperator) */
       
   757 
       
   758 PyMODINIT_FUNC
       
   759 initoperator(void)
       
   760 {
       
   761 	PyObject *m;
       
   762         
       
   763 	/* Create the module and add the functions */
       
   764         m = Py_InitModule4("operator", operator_methods, operator_doc,
       
   765 		       (PyObject*)NULL, PYTHON_API_VERSION);
       
   766 	if (m == NULL)
       
   767 		return;
       
   768 
       
   769 	if (PyType_Ready(&itemgetter_type) < 0)
       
   770 		return;
       
   771 	Py_INCREF(&itemgetter_type);
       
   772 	PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type);
       
   773 
       
   774 	if (PyType_Ready(&attrgetter_type) < 0)
       
   775 		return;
       
   776 	Py_INCREF(&attrgetter_type);
       
   777 	PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type);
       
   778 
       
   779 	if (PyType_Ready(&methodcaller_type) < 0)
       
   780 		return;
       
   781 	Py_INCREF(&methodcaller_type);
       
   782 	PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type);
       
   783 }