https://github.com/python/cpython/commit/c17238251fdf72861dfadcd581c77332b639bcb0
commit: c17238251fdf72861dfadcd581c77332b639bcb0
branch: main
author: Eric Snow <[email protected]>
committer: ericsnowcurrently <[email protected]>
date: 2025-04-28T12:41:32-06:00
summary:
gh-132775: Add _PyModule_GetFilenameObject() and _PyModule_GetFilenameUTF8()
(gh-132979)
They are derived from the existing `PyModule_GetFilenameObject().
They are used by a later change related to pickle and handling __main__.
files:
M Include/internal/pycore_moduleobject.h
M Objects/moduleobject.c
diff --git a/Include/internal/pycore_moduleobject.h
b/Include/internal/pycore_moduleobject.h
index 9bb282a13a9659..b170d7bce702c6 100644
--- a/Include/internal/pycore_moduleobject.h
+++ b/Include/internal/pycore_moduleobject.h
@@ -47,6 +47,12 @@ static inline PyObject* _PyModule_GetDict(PyObject *mod) {
return dict; // borrowed reference
}
+extern PyObject * _PyModule_GetFilenameObject(PyObject *);
+extern Py_ssize_t _PyModule_GetFilenameUTF8(
+ PyObject *module,
+ char *buffer,
+ Py_ssize_t maxlen);
+
PyObject* _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int
suppress);
PyObject* _Py_module_getattro(PyObject *m, PyObject *name);
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 16f1b2cacd4f83..f363ef173cbd46 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -607,32 +607,51 @@ PyModule_GetName(PyObject *m)
}
PyObject*
-PyModule_GetFilenameObject(PyObject *mod)
+_PyModule_GetFilenameObject(PyObject *mod)
{
+ // We return None to indicate "not found" or "bogus".
if (!PyModule_Check(mod)) {
PyErr_BadArgument();
return NULL;
}
PyObject *dict = ((PyModuleObject *)mod)->md_dict; // borrowed reference
if (dict == NULL) {
- goto error;
+ // The module has been tampered with.
+ Py_RETURN_NONE;
}
PyObject *fileobj;
- if (PyDict_GetItemRef(dict, &_Py_ID(__file__), &fileobj) <= 0) {
- // error or not found
- goto error;
+ int res = PyDict_GetItemRef(dict, &_Py_ID(__file__), &fileobj);
+ if (res < 0) {
+ return NULL;
+ }
+ if (res == 0) {
+ // __file__ isn't set. There are several reasons why this might
+ // be so, most of them valid reasons. If it's the __main__
+ // module then we're running the REPL or with -c. Otherwise
+ // it's a namespace package or other module with a loader that
+ // isn't disk-based. It could also be that a user created
+ // a module manually but without manually setting __file__.
+ Py_RETURN_NONE;
}
if (!PyUnicode_Check(fileobj)) {
Py_DECREF(fileobj);
- goto error;
+ Py_RETURN_NONE;
}
return fileobj;
+}
-error:
- if (!PyErr_Occurred()) {
+PyObject*
+PyModule_GetFilenameObject(PyObject *mod)
+{
+ PyObject *fileobj = _PyModule_GetFilenameObject(mod);
+ if (fileobj == NULL) {
+ return NULL;
+ }
+ if (fileobj == Py_None) {
PyErr_SetString(PyExc_SystemError, "module filename missing");
+ return NULL;
}
- return NULL;
+ return fileobj;
}
const char *
@@ -648,6 +667,37 @@ PyModule_GetFilename(PyObject *m)
return utf8;
}
+Py_ssize_t
+_PyModule_GetFilenameUTF8(PyObject *mod, char *buffer, Py_ssize_t maxlen)
+{
+ // We "return" an empty string for an invalid module
+ // and for a missing, empty, or invalid filename.
+ assert(maxlen >= 0);
+ Py_ssize_t size = -1;
+ PyObject *filenameobj = _PyModule_GetFilenameObject(mod);
+ if (filenameobj == NULL) {
+ return -1;
+ }
+ if (filenameobj == Py_None) {
+ // It is missing or invalid.
+ buffer[0] = '\0';
+ size = 0;
+ }
+ else {
+ const char *filename = PyUnicode_AsUTF8AndSize(filenameobj, &size);
+ assert(size >= 0);
+ if (size > maxlen) {
+ size = -1;
+ PyErr_SetString(PyExc_ValueError, "__file__ too long");
+ }
+ else {
+ (void)strcpy(buffer, filename);
+ }
+ }
+ Py_DECREF(filenameobj);
+ return size;
+}
+
PyModuleDef*
PyModule_GetDef(PyObject* m)
{
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]