Issue2117

classification
Title: os.path.abspath fails on Windows
Type: behaviour Severity: normal
Components: Core, Library Versions: Jython 2.7
Milestone:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: jeff.allen Nosy List: jeff.allen
Priority: normal Keywords:

Created on 2014-03-05.22:44:04 by jeff.allen, last changed 2014-06-30.08:09:14 by jeff.allen.

Messages
msg8246 (view) Author: Jeff Allen (jeff.allen) Date: 2014-03-05.22:44:02
I discovered this while working on an apparently simple test failure in test_chdir. The problem seems to be mainly with our conversion to absolute paths, used everywhere in the os module, and some places in sys. We have a confusing mixture of Python and Java code that's just a bit too complicated to put right as part of the chdir test, so I'm parking it here.

java.io.File gets this right, and provides equivalents to abspath and realpath I think we could take advantage of directly. Or one could, once he had a really clear idea of the intended behaviour.

Examples for comparison follow. The Unix "current working directory" is complicated on Windows, which keeps a CWD for each drive letter. In a clean command window (in D:\hg\chdirtest) these initial cd commands set CWD on the drives mentioned, but don't make then the actual CWD for the window:

>cd c:\Users\Jeff\Documents
>cd e:\test
>python
Python 2.7.6 (default, Nov 10 2013, 19:24:24) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, os, os.path
>>> os.getcwd()
'D:\\hg\\chdirtest'
>>> os.path.abspath('aa')
'D:\\hg\\chdirtest\\aa'
>>> os.path.abspath('d:aa')
'D:\\hg\\chdirtest\\aa'
>>> os.path.abspath('c:aa')
'c:\\Users\\Jeff\\Documents\\aa'
>>> os.path.abspath('e:aa')
'e:\\test\\aa'
>>> os.path.abspath('c:\\aa')
'c:\\aa'
>>> os.chdir('e:')
>>> os.getcwd()
'e:\\test'
>>> os.chdir('d:\\hg')
>>> os.getcwd()
'd:\\hg'
>>> os.chdir('e:')
>>> os.getcwd()
'e:\\test'
>>> os.path.abspath('d:aa')
'd:\\hg\\aa'
>>> os.path.abspath('aa')
'e:\\test\\aa'
>>> os.chdir('d:\\hg')
>>> os.getcwd()
'd:\\hg'
>>> os.path.abspath('aa')
'd:\\hg\\aa'
>>>

The CPython code mirrors what the OS does in tracking the per drive CWD. Jython can't get the paths right at all when a drive letter is involved and doesn't understand the per drive CWD:

>cd c:\Users\Jeff\Documents
>cd e:\test
>..\jython-int\dist\bin\jython
Jython 2.7b1+ (default:78efc2f8c832, Mar 2 2014, 20:03:25)
[Java HotSpot(TM) 64-Bit Server VM (Sun Microsystems Inc.)] on java1.6.0_45
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, os, os.path
>>> os.getcwd()
'D:\\hg\\chdirtest'
>>> os.path.abspath('aa')
'D:\\hg\\chdirtest\\aa'
>>> os.path.abspath('d:aa')
'D:\\hg\\chdirtest\\d:aa'
>>> os.path.abspath('c:aa')
'D:\\hg\\chdirtest\\c:aa'
>>> os.path.abspath('e:aa')
'D:\\hg\\chdirtest\\e:aa'
>>> os.path.abspath('c:\\aa')
'c:\\aa'
>>> os.chdir('e:')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 20047] Unknown error: 20047: 'D:\\hg\\chdirtest\\e:'
>>> os.getcwd()
'D:\\hg\\chdirtest'
>>> os.chdir('d:\\hg')
>>> os.getcwd()
'd:\\hg'
>>> os.chdir('e:')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 20047] Unknown error: 20047: 'd:\\hg\\e:'
>>> os.getcwd()
'd:\\hg'
>>> os.chdir('c:\\Users\\Jeff\\Documents')
>>> os.path.abspath('d:aa')
'c:\\Users\\Jeff\\Documents\\d:aa'
>>> os.path.abspath('..')
'c:\\Users\\Jeff'

However, java.io.File makes a pretty good start:
>>> import java.io
>>> java.io.File('d:aa').getAbsolutePath()
u'd:\\hg\\chdirtest\\aa'
>>> java.io.File('e:bb').getAbsolutePath()
u'e:\\test\\bb'
>>>
msg8251 (view) Author: Jeff Allen (jeff.allen) Date: 2014-03-09.09:49:05
I couldn't solve my chdir failure without doing this (almost) properly. Now on my local repo, I have a version that works better.

Jython 2.7b1+ (default:f553f6a07fb5+, Mar 9 2014, 09:29:38)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.7.0_45
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, os, os.path, java.io
>>> os.getcwd()
'D:\\hg\\chdirtest'
>>> os.path.abspath('aa')
'D:\\hg\\chdirtest\\aa'
>>> os.path.abspath('d:aa')
'D:\\hg\\chdirtest\\aa'
>>> os.path.abspath('c:aa')
'c:\\Users\\Jeff\\Documents\\Eclipse\\jython-trunk\\dist\\aa'
>>> os.path.abspath('e:aa')
'e:\\test\\aa'
>>> os.path.abspath('c:\\aa')
'c:\\aa'
>>> sys.registry['user.dir']
u'D:\\hg\\chdirtest'
>>> os.chdir('e:')
>>> os.getcwd()
'e:\\test'
>>> sys.registry['user.dir']
u'D:\\hg\\chdirtest'
>>> os.chdir('c:..')
>>> os.getcwd()
'c:\\Users\\Jeff\\Documents\\Eclipse\\jython-trunk'
>>>

It does not, however, update the "real" current working directory on each drive, as CPython seems to. chdir only changes the CWD of the current PySystemState. The current directory of each drive remains what it was when Jython started. (In the presence of threads, this seems a safer idea anyway.)
msg8850 (view) Author: Jeff Allen (jeff.allen) Date: 2014-06-30.08:09:13
[Corrected note] http://hg.python.org/jython/rev/f553f6a07fb5 and http://hg.python.org/jython/rev/61ef07321554 cover this as well as I think I'm able to do it, that is, correct within Python, but doesn't change the real current directory at shell-level.
History
Date User Action Args
2014-06-30 08:09:14jeff.allensetmessages: + msg8850
2014-06-30 08:08:15jeff.allensetmessages: - msg8849
2014-06-29 21:43:02jeff.allensetstatus: open -> closed
resolution: fixed
messages: + msg8849
2014-03-09 09:49:06jeff.allensetassignee: jeff.allen
messages: + msg8251
2014-03-05 22:44:04jeff.allencreate