summaryrefslogtreecommitdiff
path: root/Modules/_sre.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-11-21 16:35:08 +0100
committerVictor Stinner <victor.stinner@gmail.com>2016-11-21 16:35:08 +0100
commitb44fb128ae5d9562f00a944e2d22392235073a69 (patch)
treea02c44010193373a6766920250f2bfbd1af03f21 /Modules/_sre.c
parenta2f7ee8b26e00124c0587932364b26635af84c45 (diff)
downloadcpython-git-b44fb128ae5d9562f00a944e2d22392235073a69.tar.gz
Implement rich comparison for _sre.SRE_Pattern
Issue #28727: Regular expression patterns, _sre.SRE_Pattern objects created by re.compile(), become comparable (only x==y and x!=y operators). This change should fix the issue #18383: don't duplicate warning filters when the warnings module is reloaded (thing usually only done in unit tests).
Diffstat (limited to 'Modules/_sre.c')
-rw-r--r--Modules/_sre.c73
1 files changed, 67 insertions, 6 deletions
diff --git a/Modules/_sre.c b/Modules/_sre.c
index 69c7bc0de6..c1e9fa6e6b 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -1506,14 +1506,12 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags,
self->groups = groups;
- Py_XINCREF(groupindex);
+ Py_INCREF(groupindex);
self->groupindex = groupindex;
- Py_XINCREF(indexgroup);
+ Py_INCREF(indexgroup);
self->indexgroup = indexgroup;
- self->weakreflist = NULL;
-
if (!_validate(self)) {
Py_DECREF(self);
return NULL;
@@ -2649,6 +2647,69 @@ pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_
return (PyObject*) scanner;
}
+static Py_hash_t
+pattern_hash(PatternObject *self)
+{
+ Py_hash_t hash, hash2;
+
+ hash = PyObject_Hash(self->pattern);
+ if (hash == -1) {
+ return -1;
+ }
+
+ hash2 = _Py_HashBytes(self->code, sizeof(self->code[0]) * self->codesize);
+ hash ^= hash2;
+
+ hash ^= self->flags;
+ hash ^= self->isbytes;
+ hash ^= self->codesize;
+
+ if (hash == -1) {
+ hash = -2;
+ }
+ return hash;
+}
+
+static PyObject*
+pattern_richcompare(PyObject *lefto, PyObject *righto, int op)
+{
+ PatternObject *left, *right;
+ int cmp;
+
+ if (op != Py_EQ && op != Py_NE) {
+ Py_RETURN_NOTIMPLEMENTED;
+ }
+
+ if (Py_TYPE(lefto) != &Pattern_Type || Py_TYPE(righto) != &Pattern_Type) {
+ Py_RETURN_NOTIMPLEMENTED;
+ }
+ left = (PatternObject *)lefto;
+ right = (PatternObject *)righto;
+
+ cmp = (left->flags == right->flags
+ && left->isbytes == right->isbytes
+ && left->codesize && right->codesize);
+ if (cmp) {
+ /* Compare the code and the pattern because the same pattern can
+ produce different codes depending on the locale used to compile the
+ pattern when the re.LOCALE flag is used. Don't compare groups,
+ indexgroup nor groupindex: they are derivated from the pattern. */
+ cmp = (memcmp(left->code, right->code,
+ sizeof(left->code[0]) * left->codesize) == 0);
+ }
+ if (cmp) {
+ cmp = PyObject_RichCompareBool(left->pattern, right->pattern,
+ Py_EQ);
+ if (cmp < 0) {
+ return NULL;
+ }
+ }
+ if (op == Py_NE) {
+ cmp = !cmp;
+ }
+ return PyBool_FromLong(cmp);
+}
+
#include "clinic/_sre.c.h"
static PyMethodDef pattern_methods[] = {
@@ -2693,7 +2754,7 @@ static PyTypeObject Pattern_Type = {
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
- 0, /* tp_hash */
+ (hashfunc)pattern_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
@@ -2703,7 +2764,7 @@ static PyTypeObject Pattern_Type = {
pattern_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
- 0, /* tp_richcompare */
+ pattern_richcompare, /* tp_richcompare */
offsetof(PatternObject, weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */