You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Trailing slash in sys.path cause import failure #45634
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee='https://github.com/brettcannon'closed_at=<Date2007-11-07.17:46:51.011>created_at=<Date2007-10-18.12:47:42.621>labels= ['interpreter-core', 'type-bug']
title='Trailing slash in sys.path cause import failure'updated_at=<Date2007-11-07.17:46:51.010>user='https://bugs.python.org/guillaumegirard'
where the file bar.py is present in ../bar/ will return an import error
"No module named bar". Remove the trailing slash and the bar.py is
imported correctly. The problem is identical with backslash. This code
works in Python 2.4.
Not a very serious bug, but it breaks programs working with Python 2.4.
Only in win32, in Linux it behaves ok (I put a /tmp/w.py that prints 'w'):
Python 2.5.1 (r251:54863, May 2 2007, 16:56:35)
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.append("/tmp/")
>>> import w
w
>>>
Here is a patch that solves the problem. However the patch is against
the py3k sources and I like somebody to review and test it. I don't have
enough disk space in my VMWare box to test it against the trunk or 2.5.
Reason for the problem: Windows' stat doesn't like trailing slashes.
Fixed patch. Georg pointed out that PyArg_ParseTuple("s") returns a
reference to the internal data of the PyString object. The new version
copies the path to a fixed width buffer before it mangles the trailing
slashes.
The new patch applies against the trunk.
Brett, you are the import master. Can you review the patch, please?
I see several problems with this, but there's light at the end of the
tunnel.
(1) Don't use s#; it will allow null bytes in the string, which we don't
want.
(2) Put the entire trailing slash removal inside #ifdef MS_WINDOWS.
(3) Careful! It seems the code you wrote would transform "C:/" into
"C:" which isn't the same thing (the latter refers to the current
directory on the C drive, while the former is the root of the C drive).
(1) Don't use s#; it will allow null bytes in the string, which we don't
want.
(2) Put the entire trailing slash removal inside #ifdef MS_WINDOWS.
Done aand done
(3) Careful! It seems the code you wrote would transform "C:/" into
"C:" which isn't the same thing (the latter refers to the current
directory on the C drive, while the former is the root of the C drive).
Oh, good catch! I haven't thought of C:/
Howdoyoulike#ifdefMS_WINDOWS/* Remove trailing / and \ - Windows' stat doesn't like them - but * keep the trailing slash of C:/ */Py_ssize_ti;
charmangled[MAXPATHLEN+1];
if (pathlen>MAXPATHLEN) {
PyErr_SetString(PyExc_OverflowError,
"path is too long");
return-1;
}
strcpy(mangled, path);
for (i=pathlen-1; i>3; i--) {
if (mangled[i] !='/'&&mangled[i] !='\\') {
break;
}
mangled[i] ='\0';
}
rv=stat(mangled, &statbuf);
#elserv=stat(path, &statbuf);
#endif
Isn't it easier to handle this at the Python level? There probably
already is code for parsing Windows paths. (Hm, maybe we have it in C
too somewhere?)
I've a final offer before I declare the bug as SEP (someone else's problem):
pseudo code
#ifdefMS_WINDOWSrv=stat(...)
if (rv==error)
checkfor*one*trailign / or \ andremoveitrv=stat(...)
if (rv==error)
giveup#endif
It should fix the case when somebody adds a directory with a trailing /
or \ on Windows. More complex cases are still broken but that's really
not my concern. ;)
Brett Cannon wrote:
> Modules/getpath.c:joinpath() I think does what you want in C.
I don't see how it is going to help us.
I've a final offer before I declare the bug as SEP (someone else's problem):
pseudo code
#ifdef MS_WINDOWS
rv = stat(...)
if (rv == error)
check for *one* trailign / or \ and remove it
rv = stat(...)
if (rv == error)
give up
#endif
It should fix the case when somebody adds a directory with a trailing /
or \ on Windows. More complex cases are still broken but that's really
not my concern. ;)
Activity
guillaumegirard commentedon Oct 18, 2007
On win32, the following code:
where the file bar.py is present in ../bar/ will return an import error
"No module named bar". Remove the trailing slash and the bar.py is
imported correctly. The problem is identical with backslash. This code
works in Python 2.4.
Not a very serious bug, but it breaks programs working with Python 2.4.
facundobatista commentedon Nov 1, 2007
Only in win32, in Linux it behaves ok (I put a /tmp/w.py that prints 'w'):
tiran commentedon Nov 1, 2007
I was able to reproduce the bug on Windows with Python 2.6 and 3.0. I've
added an unit test to both versions.
tiran commentedon Nov 1, 2007
Here is a patch that solves the problem. However the patch is against
the py3k sources and I like somebody to review and test it. I don't have
enough disk space in my VMWare box to test it against the trunk or 2.5.
Reason for the problem: Windows' stat doesn't like trailing slashes.
tiran commentedon Nov 1, 2007
Fixed patch. Georg pointed out that PyArg_ParseTuple("s") returns a
reference to the internal data of the PyString object. The new version
copies the path to a fixed width buffer before it mangles the trailing
slashes.
The new patch applies against the trunk.
Brett, you are the import master. Can you review the patch, please?
brettcannon commentedon Nov 2, 2007
I will have a look when I can.
gvanrossum commentedon Nov 6, 2007
I see several problems with this, but there's light at the end of the
tunnel.
(1) Don't use s#; it will allow null bytes in the string, which we don't
want.
(2) Put the entire trailing slash removal inside #ifdef MS_WINDOWS.
(3) Careful! It seems the code you wrote would transform "C:/" into
"C:" which isn't the same thing (the latter refers to the current
directory on the C drive, while the former is the root of the C drive).
tiran commentedon Nov 6, 2007
Guido van Rossum wrote:
Done aand done
Oh, good catch! I haven't thought of C:/
i > 3 should take care of C:/ and C:\
Christian
gvanrossum commentedon Nov 6, 2007
But the C: is optional. You will need to do more parsing. Some more
examples (all with slashes; but backslashes work the same):
//share/ -> //share/
//share/x/ -> //share/x
/x/ -> /x
/ -> /
// -> // (probably illegal but doesn't matter)
C:/ -> C:/
x/ -> x
C:x/ -> C:x
Isn't it easier to handle this at the Python level? There probably
already is code for parsing Windows paths. (Hm, maybe we have it in C
too somewhere?)
tiran commentedon Nov 6, 2007
Another patch that uses os.path.normpath.
gvanrossum commentedon Nov 6, 2007
Sorry, I really don't like to be importing os.path in order to be able
to process the path used for an import.
brettcannon commentedon Nov 6, 2007
On 11/6/07, Guido van Rossum <report@bugs.python.org> wrote:
Modules/getpath.c:joinpath() I think does what you want in C.
tiran commentedon Nov 7, 2007
Brett Cannon wrote:
I don't see how it is going to help us.
I've a final offer before I declare the bug as SEP (someone else's problem):
pseudo code
It should fix the case when somebody adds a directory with a trailing /
or \ on Windows. More complex cases are still broken but that's really
not my concern. ;)
Christian
gvanrossum commentedon Nov 7, 2007
Works for me!
On Nov 7, 2007 6:08 AM, Christian Heimes <report@bugs.python.org> wrote:
tiran commentedon Nov 7, 2007
I've checked in a fix in r58903 (py3k branch).