pytest-dev / py

Python development support library (note: maintenance only)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

py.path.move() across disks fails on Windows in Python 3.4

pytestbot opened this issue · comments

Attempting to move() a file via py.path in Windows across disks fails in Python 3.4.3 (it works in Python 2.7.11).

(venv34) PS E:\src\python\py> python
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import py.path
>>> pth = py.path.local(r'e:\tmp\testing.txt')
>>> pth.move(py.path.local(r'c:\tmp\testing3.txt'))
Traceback (most recent call last):
  File "E:\src\python\py\py\_error.py", line 81, in checked_call
    cls = self._geterrnoclass(_winerrnomap[errno])
KeyError: 18

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "E:\src\python\py\py\_path\common.py", line 162, in move
    self.rename(target)
  File "E:\src\python\py\py\_path\local.py", line 443, in rename
    return py.error.checked_call(os.rename, self.strpath, target)
  File "E:\src\python\py\py\_error.py", line 83, in checked_call
    raise value
  File "E:\src\python\py\py\_error.py", line 64, in checked_call
    return func(*args, **kwargs)
OSError: [WinError 17] The system cannot move the file to a different disk drive: 'e:\\tmp\\testing.txt' -> 'c:\\tmp\\testing3.txt'
>>> py.__version__
'1.4.32.dev1'

Original comment by lvtstx

I've created a pull request.

Original comment by @smsearcy

@lvtstx, that makes sense about the different subclasses. I had forgotten to clarify that the reason it was trying to move to a different disk drive was because it was use %TEMP%.

I have the error on Windows 8.1, good to see that the errno is consistent across a couple different Windows versions. Perhaps a pull request is in order?

As an aside, I've been working around this by using devpi upload --no-vcs.

Original comment by lvtstx

I'm also affected by this bug, it breaks devpi upload on windows 7 with python 3.5 when the project is located on a volume different from the one where %TEMP% is, apparently.

Adding this line to py._error._winerrnomap fixes the issue for me:

#!python

    18: errno.EXDEV,

@smsearcy, the reason common.PathBase.move() does not use shutil.move() is probably because not all the subclasses of common.PathBase implement the sub-operations rename, copy and remove the same way.

Original comment by @smsearcy

The debugger confirms that errno = 18, winerror = 17, and strerror = 'The system cannot move the file to a different disk drive'.

According to pywin32 Windows error code 17 is ERROR_NOT_SAME_DEVICE but checked_call() is using the attribute errno instead of winerror to look up the error codes.

I'm concerned about creating a new bug if changes were made to the error codes (mapping errno 18 to EXDEV). Is there a reason why common.move() does not call shutil.move()? It appears this function will just end up attempting to replicate that logic.

I think this issue can be closed. lvtstx's PR was merged and as of py 1.4.34 (on Python 3.5.2) py.path.move() is working on Windows 8 across different drives.

@smsearcy thanks for the heads up