-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
gh-132775: Add _PyObject_GetXIDataWithFallback() #133482
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
base: main
Are you sure you want to change the base?
gh-132775: Add _PyObject_GetXIDataWithFallback() #133482
Conversation
e72c2af
to
cf17342
Compare
Python/crossinterp.c
Outdated
#ifdef Py_DEBUG | ||
Py_UNREACHABLE(); |
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 #ifdef
looks like a typo.
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.
It's there to make sure we abort on debug builds, but we have a fallback for non-debug builds.
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.
I'd prefer an explicit Py_FatalError()
then. I think I can see this usage only in crossinterp.c
(here, L1673, L1700).
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.
My intention is to not crash under normal usage, which is what Py_FatalError()
would do.
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.
ah, Py_FatalError()
instead of Py_UNREACHABLE()
? I'm okay with that. It really should be unreachable through.
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.
I strongly prefer that Py_UNREACHABLE()
be used when we care about the C compiler's optimization on non-debug builds (with no fallback). I won't be surprised even if it stops the abortion on debug builds in the future. Also, the double Py_DEBUG
checks seem unnatural to me.
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 fair. I'll switch it to explicitly Py_FatalError()
.
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.
done
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. This is off-topic, but would one of the coming PRs address #133107 (comment)?
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.
Yeah, I'll be addressing that.
04308b9
to
b9f1eea
Compare
b9f1eea
to
55ccaa0
Compare
EXCEPTION, | ||
OBJECT, |
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.
nit: indent. Also, cls
is undefined at L726, 732:
assert not hasattr(mod, func.__name__), (cls, getattr(mod, func.__name__))
# Currently the "extra" attrs are not preserved | ||
# (via __reduce__). | ||
self.assertIs(type(exc1), type(exc2)) | ||
#self.assert_exc_equal(grouped1, grouped2) |
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.
Is this still intentionally commented out? The assertion passed for me.
def assert_equal_or_equalish(self, obj, expected): | ||
cls = type(expected) | ||
if cls.__eq__ is not object.__eq__: | ||
# assert cls not in (types.MethodType, types.BuiltinMethodType, types.MethodWrapperType), cls |
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.
Ditto. See also:
L757:
# self.assert_roundtrip_equal(defs.TOP_FUNCTIONS)
L844, 997, 1463:
# UnicodeError: (None, msg, None, None, None),
Py_FatalError("unsupported xidata fallback option"); | ||
#endif | ||
_PyErr_SetString(tstate, PyExc_SystemError, | ||
"unsuppocted xidata fallback option"); |
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.
nit: unsuppo"c"ted
} | ||
|
||
int | ||
_PyObject_GetXIDataWithFallback(PyThreadState *tstate, |
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.
Could we replace the long name with _PyObject_GetXIData
? I feel the existing _PyObject_GetXIData
could be longer (e.g. _PyObject_GetXIDataNoFallback
), as it is unpopular at all in newer PRs.
UPDATE: No, _PyObject_GetXIData
should remain as-is.
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.
I'm not sure whether the fallback
parameter is needed. Does this function support the following?
- call
getdata.basic()
under the_PyXIDATA_FULL_FALLBACK
case - call
getdata.fallback()
under the_PyXIDATA_XIDATA_ONLY
case
UPDATE: Yes, they are necessary.
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.
I take back the questions in this topic. Sorry for the noise.
(I currently interpret getdata.fallback
as getdata.(with)fallback
that can pass an option to tuple's items, and WithFallback
as _PyFunction_GetXIData
and _PyPickle_GetXIData
.)
typedef struct { | ||
xidatafunc basic; | ||
xidatafbfunc fallback; | ||
} _PyXIData_getdata_t; |
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.
Does the layout imply that it would accept two functions in the future? If exclusive, is there any reason why it cannot be a void pointer (or xidatafunc) with a flag? (The C compilers could verify xidatafbfunc
at REGISTER_FALLBACK()
.)
E: No change request from me as long as there are only two options.
typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *); | ||
typedef int xidata_fallback_t; | ||
#define _PyXIDATA_XIDATA_ONLY (0) | ||
#define _PyXIDATA_FULL_FALLBACK (1) |
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.
Maybe flags like 0b111?
(This is based on gh-133481, thus only the last commit.)