diff --git a/ponyguruma/_highlevel.py b/ponyguruma/_highlevel.py index 6d74c29..a25e79c 100644 --- a/ponyguruma/_highlevel.py +++ b/ponyguruma/_highlevel.py @@ -22,14 +22,16 @@ class CalculatedProperty(object): def __init__(self, func): self.func = func - self.__name__ = func.func_name + self.__name__ = func.__name__ self.__doc__ = func.__doc__ def __get__(self, obj, type=None): if obj is None: return self - value = self.func(obj) - setattr(obj, self.__name__, value) + value = getattr(obj, "__" + self.__name__, None) + if value == None: + value = self.func(obj) + setattr(obj, "__" + self.__name__, value) return value def __repr__(self): @@ -178,7 +180,7 @@ def split(self, string, maxsplit=0, pos=0, endpos=-1, flat=False): result = [] startstring = string[:pos] n = 0 - push_match = (flag and result.append or result.extend) + push_match = (flat and result.append or result.extend) while 1: state = regexp_match(self, string, pos, endpos, False) if state is None: @@ -198,9 +200,6 @@ def split(self, string, maxsplit=0, pos=0, endpos=-1, flat=False): def __str__(self): return str(self.pattern) - def __unicode__(self): - return unicode(self.pattern) - def __repr__(self): return 'Regexp(%r)' % (self.pattern,) @@ -239,7 +238,7 @@ def groups(self): regexp ``r'(.)(.)(.)'`` matched against ``abc`` will return ``('a', 'b', 'c')`` but not ``('abc', 'a', 'b', 'c')``. """ - return tuple([self.group(x) for x in xrange(1, len(self.spans))]) + return tuple([self.group(x) for x in range(1, len(self.spans))]) groups = CalculatedProperty(groups) def groupdict(self): @@ -296,7 +295,7 @@ def span(self, group=0): named group, otherwise an integer. If you omit the value the span of the whole match is returned. """ - if isinstance(group, basestring): + if isinstance(group, str): group = self.groupnames[group] return self.spans[group] @@ -318,7 +317,7 @@ def group(self, group=0): """ Return the value of a single group. """ - if isinstance(group, basestring): + if isinstance(group, str): group = self.groupnames[group] return match_extract_group(self.state, group) @@ -377,9 +376,6 @@ def __nonzero__(self): # If this isn't defined, Python checks if __len__() != 0! return True - def __unicode__(self): - return unicode(self.group(0)) - def __str__(self): return str(self.group(0)) diff --git a/ponyguruma/_lowlevel.c b/ponyguruma/_lowlevel.c index 0b45941..38f1dc0 100644 --- a/ponyguruma/_lowlevel.c +++ b/ponyguruma/_lowlevel.c @@ -30,6 +30,20 @@ # error "unsupported Py_UNICODE_SIZE" #endif +#ifndef Py_TYPE + #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif + +#if PY_MAJOR_VERSION >= 3 + #define PyString_Check PyBytes_Check + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyString_FromStringAndSize PyBytes_FromStringAndSize + #define PyString_GET_SIZE PyBytes_GET_SIZE + #define PyInt_FromLong PyLong_FromLong + #define Py_InitModule3 PyModule_Create + #define PyString_AS_STRING _PyUnicode_AsString +#endif + typedef struct { PyObject_HEAD regex_t *regex; @@ -229,7 +243,7 @@ BaseRegexp_dealloc(BaseRegexp *self) if (self->regex) onig_free(self->regex); Py_XDECREF(self->pattern); - self->ob_type->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free((PyObject *)self); } /** @@ -266,8 +280,7 @@ static PyGetSetDef BaseRegexp_getsetters[] = { static PyTypeObject BaseRegexpType = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ + PyVarObject_HEAD_INIT(NULL, 0) "ponyguruma._lowlevel.BaseRegexp", /* tp_name */ sizeof(BaseRegexp), /* tp_basicsize */ 0, /* tp_itemsize */ @@ -287,7 +300,7 @@ static PyTypeObject BaseRegexpType = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "", /* tp_doc */ + 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ @@ -319,7 +332,7 @@ MatchState_dealloc(MatchState *self) Py_XDECREF(self->string); if (self->region) onig_region_free(self->region, 1); - self->ob_type->tp_free(self); + Py_TYPE(self)->tp_free(self); } @@ -359,8 +372,7 @@ static PyGetSetDef MatchState_getsetters[] = { static PyTypeObject MatchStateType = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ + PyVarObject_HEAD_INIT(NULL, 0) "ponyguruma._lowlevel.MatchState", /* tp_name */ sizeof(MatchState), /* tp_basicsize */ 0, /* tp_itemsize */ @@ -415,7 +427,7 @@ regexp_match(PyObject *self, PyObject *args) "object required"); return NULL; } - if (pos < 0) { + if ((int)pos < 0) { PyErr_SetString(PyExc_ValueError, "pos must be >= 0"); return NULL; } @@ -447,11 +459,11 @@ regexp_match(PyObject *self, PyObject *args) "string or unicode"); return NULL; } - if (endpos == -1) { + if ((int)endpos == -1) { endpos = (regexp->unicode ? PyUnicode_GET_SIZE(string) : PyString_GET_SIZE(string)); } - if (endpos < 0) { + if ((int)endpos < 0) { PyErr_SetString(PyExc_ValueError, "endpos must be >= -1, where " "-1 means the length of the string to match"); Py_DECREF(string); @@ -658,25 +670,41 @@ static PyMethodDef module_methods[] = { {NULL, NULL, 0, NULL} }; - -#ifndef PyMODINIT_FUNC -#define PyMODINIT_FUNC void +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "ponyguruma._lowlevel", /* m_name */ + "", /* m_doc */ + -1, /* m_size */ + module_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; #endif -PyMODINIT_FUNC -init_lowlevel(void) + +static PyObject * +moduleinit(void) { PyObject *module; - + if (init_python_syntax() < 0) - return; - + return NULL; + if (PyType_Ready(&BaseRegexpType) < 0 || PyType_Ready(&MatchStateType) < 0 ) - return; + return NULL; + +#if PY_MAJOR_VERSION >= 3 + module = PyModule_Create(&moduledef); +#else + module = Py_InitModule3("ponyguruma._lowlevel", + module_methods, ""); +#endif - module = Py_InitModule3("ponyguruma._lowlevel", module_methods, ""); if (!module) - return; + return NULL; RegexpError = PyErr_NewException("ponyguruma.RegexpError", NULL, NULL); Py_INCREF(RegexpError); @@ -695,4 +723,20 @@ init_lowlevel(void) onig_set_warn_func(on_regexp_warning); onig_set_verb_warn_func(on_regexp_warning); + + return module; } + +#if PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC +PyInit__lowlevel(void) +{ + return moduleinit(); +} +#else +PyMODINIT_FUNC +init_lowlevel(void) +{ + moduleinit(); +} +#endif diff --git a/ponyguruma/sre.py b/ponyguruma/sre.py index 41d1919..3d621a6 100644 --- a/ponyguruma/sre.py +++ b/ponyguruma/sre.py @@ -79,7 +79,7 @@ def groups(self, default=None): def groupdict(self, default=None): rv = Match.groupdict.__get__(self) if default is not None: - for name, value in rv.iteritems(): + for name, value in rv.items(): if value is None: rv[name] = default return rv diff --git a/ponyguruma/test_performance.py b/ponyguruma/test_performance.py index f4b822d..66b92ed 100644 --- a/ponyguruma/test_performance.py +++ b/ponyguruma/test_performance.py @@ -18,7 +18,7 @@ def r(t, rep=100000): s = time.time() - for x in xrange(rep): + for x in range(rep): t() return time.time() - s @@ -52,5 +52,5 @@ def t_match_onig_complex(): if __name__ == '__main__': for key in sorted(locals().keys()): if key.startswith('t_'): - print key[2:], - print r(locals()[key]) + print(key[2:]), + print(r(locals()[key])) diff --git a/ponyguruma/test_string.py b/ponyguruma/test_string.py index 07086ff..84e0d12 100644 --- a/ponyguruma/test_string.py +++ b/ponyguruma/test_string.py @@ -34,7 +34,7 @@ def xx(pattern, str_, from_, to, mem, not_): pattern, str_, from_, to)) else: errors.append("%r should match with %r" % (pattern, str_)) - except Exception, err: + except Exception as err: errors.append("got exception with pattern %r and string %r: %s" % (pattern, str_, err)) @@ -734,7 +734,6 @@ def n(pattern, str_): # <<< copied until here for entry in errors: - print entry - print - print "RESULTS:" - print "%d tests, %d failed." % (runs[0], len(errors)) + print(entry) + print("RESULTS:") + print("%d tests, %d failed." % (runs[0], len(errors))) diff --git a/ponyguruma/test_unicode.py b/ponyguruma/test_unicode.py index 74ef087..342e767 100644 --- a/ponyguruma/test_unicode.py +++ b/ponyguruma/test_unicode.py @@ -29,18 +29,18 @@ def xx(pattern, str_, from_, to, mem, not_): if not m: return else: - errors.append(u"%r should not match with %r" % (upattern, ustr)) + errors.append("%r should not match with %r" % (upattern, ustr)) else: if m: if m.span(mem) == (from_, to): return else: - errors.append(u"%r should match with %r from %s to %s" % ( + errors.append("%r should match with %r from %s to %s" % ( upattern, ustr, from_, to)) else: - errors.append(u"%r should match with %r" % (upattern, ustr)) - except Exception, err: - errors.append(u"got %s exception with pattern %r and string %r: %s" % + errors.append("%r should match with %r" % (upattern, ustr)) + except Exception as err: + errors.append("got %s exception with pattern %r and string %r: %s" % (err.__class__.__name__, upattern, ustr, err)) def x2(pattern, str_, from_, to): @@ -739,7 +739,6 @@ def n(pattern, str_): # <<< copied until here for entry in errors: - print entry - print - print "RESULTS:" - print "%d tests, %d failed." % (runs[0], len(errors)) + print(entry) + print("RESULTS:") + print("%d tests, %d failed." % (runs[0], len(errors))) diff --git a/setup.py b/setup.py old mode 100644 new mode 100755