Index: Lib/test/test_sys.py =================================================================== --- Lib/test/test_sys.py (revision 64299) +++ Lib/test/test_sys.py (working copy) @@ -526,6 +526,7 @@ h + len_typeobject + 41*p + 10*p + 3*p + 6*p) def test_specialtypes(self): + import re i = self.i l = self.l p = self.p @@ -537,6 +538,13 @@ # list self.check_sizeof([], h + l + p + l) self.check_sizeof([1, 2, 3], h + l + p + l + 3*l) + # sre scanner + scannersize = h + p +\ + 5*p + 2*l + self.align(i) + 2*l + 201*p + 2*l + 2*p + r = re.compile(r'') + samples = [r.scanner(''), r.scanner(r'[a-zA-Z_]\w*', 0, 5)] + for s in samples: + self.check_sizeof(s, scannersize) # unicode import math usize = math.log(sys.maxunicode + 1, 2) / 8 @@ -564,6 +572,23 @@ self.check_sizeof(32768L, h + self.align(2) + 2) self.check_sizeof(32768L*32768L-1, h + self.align(2) + 2) self.check_sizeof(32768L*32768L, h + self.align(2) + 4) + # regular expressions pattern + r = re.compile(r'') + basicsize = h + l + 3*p + self.align(4) + p + l + self.align(2) + self.check_sizeof(r, basicsize) + samples = [r'a', r'a'*100] + for s in samples: + self.check_sizeof(re.compile(s), basicsize + 8*2 + len(s)*4*2 - 2) + # regular expressions match + basicsize = h + 4*p + 4*l + samples = {'': ((0,0),),\ + '(The).(quick).(brown).*': ((0,0),(0,0), (0,0), (0,0))} + for s, r in samples.items(): + m = re.match(s, 'The quick brown fox') + self.check_sizeof(m, basicsize) + # trigger caching list of matching spans + m.regs + self.check_sizeof(m, basicsize + sys.getsizeof(r)) # string self.check_sizeof('', h + l + self.align(i + 1)) self.check_sizeof('abc', h + l + self.align(i + 1) + 3) Index: Modules/_sre.c =================================================================== --- Modules/_sre.c (revision 64299) +++ Modules/_sre.c (working copy) @@ -2539,6 +2539,19 @@ #endif } +static PyObject* +pattern_sizeof(PatternObject *self) { + Py_ssize_t res, codesize; + + res = 0; + codesize = self->codesize; + if (codesize > 0) + res = sizeof(SRE_CODE) * (codesize - 1); + res += sizeof(PatternObject); + + return PyInt_FromSsize_t(res); +} + PyDoc_STRVAR(pattern_match_doc, "match(string[, pos[, endpos]]) --> match object or None.\n\ Matches zero or more characters at the beginning of the string"); @@ -2575,6 +2588,9 @@ PyDoc_STRVAR(pattern_doc, "Compiled regular expression objects"); +PyDoc_STRVAR(pattern_sizeof_doc, +"P.__sizeof__() -> size of P in memory, in bytes"); + static PyMethodDef pattern_methods[] = { {"match", (PyCFunction) pattern_match, METH_VARARGS|METH_KEYWORDS, pattern_match_doc}, @@ -2595,6 +2611,8 @@ {"scanner", (PyCFunction) pattern_scanner, METH_VARARGS}, {"__copy__", (PyCFunction) pattern_copy, METH_NOARGS}, {"__deepcopy__", (PyCFunction) pattern_deepcopy, METH_O}, + {"__sizeof__", (PyCFunction) pattern_sizeof, METH_NOARGS, + pattern_sizeof_doc}, {NULL, NULL} }; @@ -3083,6 +3101,26 @@ #endif } +static PyObject * +match_sizeof(MatchObject *self) +{ + PyObject *res = NULL, *regssize = NULL; + + res = PyInt_FromSsize_t(sizeof(MatchObject)); + if (!res) + return NULL; + if (self->regs) { + regssize = PyObject_CallMethod(self->regs, "__sizeof__", NULL); + if (regssize == NULL) { + Py_DECREF(res); + return NULL; + } + res = PyNumber_Add(res, regssize); + Py_DECREF(regssize); + } + return res; +} + static PyMethodDef match_methods[] = { {"group", (PyCFunction) match_group, METH_VARARGS}, {"start", (PyCFunction) match_start, METH_VARARGS}, @@ -3093,6 +3131,7 @@ {"expand", (PyCFunction) match_expand, METH_O}, {"__copy__", (PyCFunction) match_copy, METH_NOARGS}, {"__deepcopy__", (PyCFunction) match_deepcopy, METH_O}, + {"__sizeof__", (PyCFunction) match_sizeof, METH_NOARGS}, {NULL, NULL} }; @@ -3312,9 +3351,16 @@ return match; } +static PyObject * +scanner_sizeof(ScannerObject *self) +{ + return PyInt_FromSsize_t(sizeof(ScannerObject)); +} + static PyMethodDef scanner_methods[] = { {"match", (PyCFunction) scanner_match, METH_NOARGS}, {"search", (PyCFunction) scanner_search, METH_NOARGS}, + {"__sizeof__", (PyCFunction) scanner_sizeof, METH_NOARGS}, {NULL, NULL} };