-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-43977: Use tp_flags for collection matching #25723
bpo-43977: Use tp_flags for collection matching #25723
Conversation
…tandard builtin classes.
dfc4105
to
d265dcc
Compare
d265dcc
to
ddef5fb
Compare
… Mapping to be special.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I've left a few comments.
We should also remove the map_abc
and seq_abc
members from the PyInterpreterState
struct in Include/internal/pycore_interp.h
and Python/pystate.c
.
@@ -499,6 +523,11 @@ _abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass) | |||
/* Invalidate negative cache */ | |||
get_abc_state(module)->abc_invalidation_counter++; | |||
|
|||
if (PyType_Check(subclass) && PyType_Check(self) && | |||
!PyType_HasFeature((PyTypeObject *)subclass, Py_TPFLAGS_IMMUTABLETYPE)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
Modules/_abc.c
Outdated
if (_PyDict_DelItemId(cls->tp_dict, &PyId___flags__) < 0) { | ||
return NULL; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we deleting __flags__
here? It looks like it will get overwritten anyways:
>>> class C:
... __flags__ = "Spam"
...
>>> C.__flags__
284160
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The __flags__
set in Sequence
is in Sequence.__dict__
, but normally __flags__
is a descriptor.
So, it is probably safest to delete it. I suspect it doesn't matter much in practice.
Modules/_abc.c
Outdated
@@ -446,6 +449,27 @@ _abc__abc_init(PyObject *module, PyObject *self) | |||
return NULL; | |||
} | |||
Py_DECREF(data); | |||
if (PyType_Check(self)) { | |||
PyTypeObject *cls = (PyTypeObject *)self; | |||
PyObject *flags = _PyDict_GetItemIdWithError(cls->tp_dict, &PyId___flags__); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, this whole mechanism makes me a bit uncomfortable. I'm not aware of any case where writing to __flags__
in Pythonland actually works like this.
But I can't really think of anything better, so I guess it's fine. Maybe we could just use a name like _abc_tpflags
or something instead of __flags__
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, it is just a name. I like using a dunder name, as it is a special thing. __abc_tpflags__
perhaps?
Use tp_flags on the class object to determine if the subject is a sequence | ||
or mapping when pattern matching. Avoids the need to import collections.abc | ||
when pattern matching. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some markup to make this a bit richer:
Use tp_flags on the class object to determine if the subject is a sequence | |
or mapping when pattern matching. Avoids the need to import collections.abc | |
when pattern matching. | |
Use :c:member:`~PyTypeObject.tp_flags` on the class object to determine if the subject is a sequence | |
or mapping when pattern matching. Avoids the need to import :mod:`collections.abc` | |
when pattern matching. |
Lib/_collections_abc.py
Outdated
@@ -793,6 +793,7 @@ def __isub__(self, it): | |||
|
|||
### MAPPINGS ### | |||
|
|||
TPFLAGS_MAPPING = 1 << 6 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is public and can be relied upon, it needs to be added to the docs for collections.abc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be internal. I'll hide it.
Py_TPFLAGS_SEQUENCE
andPy_TPFLAGS_MAPPING
MATCH_SEQUENCE
andMATCH_MAPPING
to avoid importingcollections.abc
when matching.https://bugs.python.org/issue43977