-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
bpo-34284: Nonsensical exception message when calling __new__
on non-instantiable objects
#8576
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
Conversation
Please don't combine patches for two issues in one PR |
20180ab
to
9125689
Compare
That was unintentional. Fixed. |
Objects/typeobject.c
Outdated
@@ -5885,12 +5885,24 @@ tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds) | |||
staticbase = staticbase->tp_base; | |||
/* If staticbase is NULL now, it is a really weird type. | |||
In the spirit of backwards compatibility (?), just shut up. */ | |||
char extra[10] = "normal"; |
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 seems to be dead code
Also, I disagree with this method of fixing it, as I explained on the BPO issue |
Lib/test/test_types.py
Outdated
object.__new__(type(sys.flags)) | ||
message = 'object.__new__(sys.flags) is not safe' | ||
self.assertEqual(str(cm.exception), message) | ||
|
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.
Can you add a test for tuple.__new__(type(sys.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.
That's easy, but I'm still not sure what is the right behavior here. I need time to read through bpo-31506 to comprehend the problem.
Discussion on the BPO issue seems to be suggesting a different method of fixing |
9955e4d
to
06f3144
Compare
I think that this patch makes the "if(type->tp_new == null)" check in type_call unnecessary |
This also seems like it won't fix the bug for |
Thanks for your comments.
Exactly, there is more than one reason why I know that there is still work to do. I need to write some tests, check all places where Now I just want to now that I'm following the right path. |
@@ -0,0 +1 @@ | |||
NullNew for old extension types instead of just 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.
This NEWS entry could be worded clearer
c86689b
to
2460e02
Compare
More changes:
|
I'm also not sure what to do with all that |
2460e02
to
a64abba
Compare
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 bug I initially reported would continue to appear for all types whose tp_new == NULL
, which is why I suggested removing checks for that case: better to fail louder then let a cryptic error-handling bug go unnoticed. (Although I don't expect such a change to happen) Yes, this change could just happen, but that will still leave the potential for buggy types and make the code (in my opinion -- I expect to be disagreed with here) less clean. Also, the test you added testing sys.flags
should probably also test the other types you fixed and live in test_sys
Less ambitious tests for this were already there, so it makes perfect sense. Fixed. |
fc8857a
to
d018573
Compare
|
|
Now we can remove that --- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -912,12 +912,10 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *obj;
- if (type->tp_new == NULL) {
- PyErr_Format(PyExc_TypeError,
- "cannot create '%.100s' instances",
- type->tp_name);
- return NULL;
- }
+ /* tp_new cannot be NULL,
+ if you want to prevent class instantiation
+ use PyType_NullNew as tp_new instead */
+ assert(type->tp_new != NULL); The Python test suite still passes with that change. However, in that case, we should update docs as well. The current behavior is documented at least here:
What about custom user types? Is it OK to break C API between major releases? Sholdn't we depreceate it first? I need advice. |
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.
Also, the title of this PR should probably be changed
f71475d
to
2302b69
Compare
__new__
on some sys objects__new__
on objects with tp_new == NULL
__new__
on objects with tp_new == NULL
__new__
on non-instantiable objects
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 PR adds a new public PyType_NullNew
API.
I doubt if we need it, the problem can be solved by with static
private functions
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
@asvetlov, thanks for the review. First, I'm still looking for an answer for #8576 (comment). Should we allow Second, if we don't expose |
Allowing From my understanding all you need is:
The error text can be discussed and tuned but you've got my idea. |
@asvetlov Why should trying to instantiate Not providing a |
Sorry, I have to re-read the thread to get restore the PR context first. |
https://bugs.python.org/issue34284