@@ -2016,7 +2016,8 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level)
20162016{
20172017 static PyObject * namestr = NULL ;
20182018 static PyObject * pathstr = NULL ;
2019- PyObject * modname , * modpath , * modules , * parent ;
2019+ static PyObject * pkgstr = NULL ;
2020+ PyObject * pkgname , * modname , * modpath , * modules , * parent ;
20202021
20212022 if (globals == NULL || !PyDict_Check (globals ) || !level )
20222023 return Py_None ;
@@ -2031,44 +2032,103 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level)
20312032 if (pathstr == NULL )
20322033 return NULL ;
20332034 }
2035+ if (pkgstr == NULL ) {
2036+ pkgstr = PyUnicode_InternFromString ("__package__" );
2037+ if (pkgstr == NULL )
2038+ return NULL ;
2039+ }
20342040
20352041 * buf = '\0' ;
20362042 * p_buflen = 0 ;
2037- modname = PyDict_GetItem (globals , namestr );
2038- if (modname == NULL || !PyUnicode_Check (modname ))
2039- return Py_None ;
2043+ pkgname = PyDict_GetItem (globals , pkgstr );
20402044
2041- modpath = PyDict_GetItem ( globals , pathstr );
2042- if ( modpath != NULL ) {
2043- Py_ssize_t len = PyUnicode_GET_SIZE ( modname ) ;
2044- if (len > MAXPATHLEN ) {
2045+ if (( pkgname != NULL ) && ( pkgname != Py_None )) {
2046+ /* __package__ is set, so use it */
2047+ Py_ssize_t len ;
2048+ if (! PyUnicode_Check ( pkgname ) ) {
20452049 PyErr_SetString (PyExc_ValueError ,
2046- "Module name too long " );
2050+ "__package__ set to non-string " );
20472051 return NULL ;
20482052 }
2049- strcpy (buf , PyUnicode_AsString (modname ));
2050- }
2051- else {
2052- char * start = PyUnicode_AsString (modname );
2053- char * lastdot = strrchr (start , '.' );
2054- size_t len ;
2055- if (lastdot == NULL && level > 0 ) {
2053+ len = PyUnicode_GET_SIZE (pkgname );
2054+ if (len == 0 ) {
2055+ if (level > 0 ) {
2056+ PyErr_SetString (PyExc_ValueError ,
2057+ "Attempted relative import in non-package" );
2058+ return NULL ;
2059+ }
2060+ return Py_None ;
2061+ }
2062+ if (len > MAXPATHLEN ) {
20562063 PyErr_SetString (PyExc_ValueError ,
2057- "Attempted relative import in non-package " );
2064+ "Package name too long " );
20582065 return NULL ;
20592066 }
2060- if (lastdot == NULL )
2067+ strcpy (buf , PyUnicode_AsString (pkgname ));
2068+ } else {
2069+ /* __package__ not set, so figure it out and set it */
2070+ modname = PyDict_GetItem (globals , namestr );
2071+ if (modname == NULL || !PyUnicode_Check (modname ))
20612072 return Py_None ;
2062- len = lastdot - start ;
2063- if (len >= MAXPATHLEN ) {
2064- PyErr_SetString (PyExc_ValueError ,
2065- "Module name too long" );
2066- return NULL ;
2073+
2074+ modpath = PyDict_GetItem (globals , pathstr );
2075+ if (modpath != NULL ) {
2076+ /* __path__ is set, so modname is already the package name */
2077+ Py_ssize_t len = PyUnicode_GET_SIZE (modname );
2078+ int error ;
2079+ if (len > MAXPATHLEN ) {
2080+ PyErr_SetString (PyExc_ValueError ,
2081+ "Module name too long" );
2082+ return NULL ;
2083+ }
2084+ strcpy (buf , PyUnicode_AsString (modname ));
2085+ error = PyDict_SetItem (globals , pkgstr , modname );
2086+ if (error ) {
2087+ PyErr_SetString (PyExc_ValueError ,
2088+ "Could not set __package__" );
2089+ return NULL ;
2090+ }
2091+ } else {
2092+ /* Normal module, so work out the package name if any */
2093+ char * start = PyUnicode_AsString (modname );
2094+ char * lastdot = strrchr (start , '.' );
2095+ size_t len ;
2096+ int error ;
2097+ if (lastdot == NULL && level > 0 ) {
2098+ PyErr_SetString (PyExc_ValueError ,
2099+ "Attempted relative import in non-package" );
2100+ return NULL ;
2101+ }
2102+ if (lastdot == NULL ) {
2103+ error = PyDict_SetItem (globals , pkgstr , Py_None );
2104+ if (error ) {
2105+ PyErr_SetString (PyExc_ValueError ,
2106+ "Could not set __package__" );
2107+ return NULL ;
2108+ }
2109+ return Py_None ;
2110+ }
2111+ len = lastdot - start ;
2112+ if (len >= MAXPATHLEN ) {
2113+ PyErr_SetString (PyExc_ValueError ,
2114+ "Module name too long" );
2115+ return NULL ;
2116+ }
2117+ strncpy (buf , start , len );
2118+ buf [len ] = '\0' ;
2119+ pkgname = PyUnicode_FromString (buf );
2120+ if (pkgname == NULL ) {
2121+ return NULL ;
2122+ }
2123+ error = PyDict_SetItem (globals , pkgstr , pkgname );
2124+ Py_DECREF (pkgname );
2125+ if (error ) {
2126+ PyErr_SetString (PyExc_ValueError ,
2127+ "Could not set __package__" );
2128+ return NULL ;
2129+ }
20672130 }
2068- strncpy (buf , start , len );
2069- buf [len ] = '\0' ;
20702131 }
2071-
20722132 while (-- level > 0 ) {
20732133 char * dot = strrchr (buf , '.' );
20742134 if (dot == NULL ) {
0 commit comments