-
-
Notifications
You must be signed in to change notification settings - Fork 34.5k
bpo-43224: Draft implementation of PEP 646 #30398
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
Changes from 1 commit
64abc0a
b725671
ea329b9
681dc4e
69f575f
095a620
6713748
038b8f0
f028339
38c17d3
9991937
9017d22
07ed599
74e5252
6cb3aa5
daef59b
3c2a7e7
456156a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
E.g. tuple[*tuple[int, str]].
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,8 +11,17 @@ typedef struct { | |||||||
| PyObject *args; | ||||||||
| PyObject *parameters; | ||||||||
| PyObject* weakreflist; | ||||||||
| // Whether we're a starred type, e.g. *tuple[int]. | ||||||||
| // Only supported for `tuple`. | ||||||||
| int starred; | ||||||||
| } gaobject; | ||||||||
|
|
||||||||
| typedef struct { | ||||||||
| PyObject_HEAD | ||||||||
| PyObject *obj; /* Set to NULL when iterator is exhausted */ | ||||||||
| int exhausted; | ||||||||
|
mrahtz marked this conversation as resolved.
Outdated
|
||||||||
| } gaiterobject; | ||||||||
|
|
||||||||
| static void | ||||||||
| ga_dealloc(PyObject *self) | ||||||||
| { | ||||||||
|
|
@@ -118,12 +127,17 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p) | |||||||
| static PyObject * | ||||||||
| ga_repr(PyObject *self) | ||||||||
| { | ||||||||
| gaobject *alias = (gaobject *)self; | ||||||||
| gaobject *alias = (gaobject *) self; | ||||||||
| Py_ssize_t len = PyTuple_GET_SIZE(alias->args); | ||||||||
|
|
||||||||
| _PyUnicodeWriter writer; | ||||||||
| _PyUnicodeWriter_Init(&writer); | ||||||||
|
|
||||||||
| if (alias->starred) { | ||||||||
| if (_PyUnicodeWriter_WriteASCIIString(&writer, "*", 1) < 0) { | ||||||||
| goto error; | ||||||||
| } | ||||||||
| } | ||||||||
| if (ga_repr_item(&writer, alias->origin) < 0) { | ||||||||
| goto error; | ||||||||
| } | ||||||||
|
|
@@ -626,6 +640,65 @@ static PyNumberMethods ga_as_number = { | |||||||
| .nb_or = _Py_union_type_or, // Add __or__ function | ||||||||
| }; | ||||||||
|
|
||||||||
| static PyObject * | ||||||||
| ga_iternext(gaiterobject *gi) { | ||||||||
| gaobject *alias = (gaobject *) gi->obj; | ||||||||
|
|
||||||||
| if (gi->exhausted) { | ||||||||
| gi->obj = NULL; | ||||||||
| return NULL; | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like you could potentially be missing a decref here for
Suggested change
If I'm just shooting my mouth off, then just please ignore what I said :). One way to test for refleaks is to run the tests with the refleak hunter (requires a debug build):
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, super nice about the refleak hunter - I had no idea that was a thing! And good catch about the decref too. One thing I'm unsure about is where we should do it, though. Reading https://docs.python.org/3/c-api/gcsupport.html, am I right in thinking that the iterator object
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Friendly poke :) |
||||||||
| } | ||||||||
| gi->exhausted = 1; | ||||||||
|
|
||||||||
| gaobject *starred_tuple = PyObject_GC_New(gaobject, &Py_GenericAliasType); | ||||||||
| starred_tuple->origin = alias->origin; | ||||||||
| starred_tuple->args = alias->args; | ||||||||
| starred_tuple->parameters = alias->parameters; | ||||||||
| starred_tuple->weakreflist = alias->weakreflist; | ||||||||
|
mrahtz marked this conversation as resolved.
Outdated
|
||||||||
| starred_tuple->starred = 1; | ||||||||
| Py_INCREF(alias->args); | ||||||||
| // We may not have any parameters to deal with - e.g. `*tuple[int]` | ||||||||
| if (alias->parameters != NULL) { | ||||||||
| Py_INCREF(alias->parameters); | ||||||||
| } | ||||||||
| _PyObject_GC_TRACK(starred_tuple); | ||||||||
| return (PyObject *) starred_tuple; | ||||||||
| } | ||||||||
|
|
||||||||
| static void | ||||||||
| ga_iter_dealloc(gaiterobject *gi) { | ||||||||
| _PyObject_GC_UNTRACK(gi); | ||||||||
| Py_XDECREF(gi->obj); | ||||||||
| PyObject_GC_Del(gi); | ||||||||
| } | ||||||||
|
|
||||||||
| PyTypeObject Py_GenericAliasIterType = { | ||||||||
|
mrahtz marked this conversation as resolved.
Outdated
|
||||||||
| PyVarObject_HEAD_INIT(&PyType_Type, 0) | ||||||||
| .tp_name = "generic_alias_iter", | ||||||||
| .tp_basicsize = sizeof(gaiterobject), | ||||||||
| .tp_iternext = (iternextfunc)ga_iternext, | ||||||||
| .tp_dealloc = (destructor)ga_iter_dealloc, | ||||||||
| .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, | ||||||||
| }; | ||||||||
|
|
||||||||
| static PyObject * | ||||||||
| ga_iter(PyObject *self) { | ||||||||
| gaobject *alias = (gaobject *) self; | ||||||||
| if ((PyTypeObject *) alias->origin != &PyTuple_Type) { | ||||||||
| PyErr_SetString(PyExc_TypeError, "Only tuple types can be unpacked with *"); | ||||||||
| return NULL; | ||||||||
| } | ||||||||
|
|
||||||||
| gaiterobject *gi = PyObject_GC_New(gaiterobject, &Py_GenericAliasIterType); | ||||||||
| if (gi == NULL) | ||||||||
| return NULL; | ||||||||
| gi->obj = self; | ||||||||
| gi->exhausted = 0; | ||||||||
| Py_INCREF(self); | ||||||||
| _PyObject_GC_TRACK(gi); | ||||||||
| return (PyObject *) gi; | ||||||||
| } | ||||||||
|
|
||||||||
| // TODO: | ||||||||
| // - argument clinic? | ||||||||
| // - __doc__? | ||||||||
|
|
@@ -654,6 +727,7 @@ PyTypeObject Py_GenericAliasType = { | |||||||
| .tp_new = ga_new, | ||||||||
| .tp_free = PyObject_GC_Del, | ||||||||
| .tp_getset = ga_properties, | ||||||||
| .tp_iter = (getiterfunc)ga_iter, | ||||||||
| }; | ||||||||
|
|
||||||||
| PyObject * | ||||||||
|
|
||||||||
Uh oh!
There was an error while loading. Please reload this page.