[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-14 Thread Daniel Plachotich

Daniel Plachotich added the comment:

Looks good to me.
Without the fix, the test fails on Windows 7 as expected.

--

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-10 Thread Daniel Plachotich

Daniel Plachotich added the comment:

Yes, it's probably a better solution. If had been more careful, I wouldn't have 
scribbled so much text here :) .

But is there any sense in adding Windows-specific test with EACCES since the 
problem with errno may affect other platforms as well (at least in theory)? 
It's not a Windows-only issue.

--

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-09 Thread Daniel Plachotich

Daniel Plachotich added the comment:

You mean msg254341? As I mentioned recently, it still will raise an exception
in case of EROFS, ENOSPC and possibly other values, which, as in the case
with Windows, can be quite unexpected depending on platform and circumstances.

Of course there is no practical sense to continue when, for example, FS is
read-only (EROFS), but I think makedirs must be predictable: it should
first check and only then try to create, as it stated in the docstring.
When exist_ok=True and directory really exists, a user doesn't expect any
exceptions from the internally used mkdir, because it simply shouldn't be
called in this case.

By the way, why 3.2 and 3.3 were removed from the list? exist_ok was introduced 
in 3.2.

--

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-09 Thread Daniel Plachotich

Daniel Plachotich added the comment:

Maybe the solution is to leave OSError catching after the conditional
(probably with some additional comments):

   if not (exist_ok and path.isdir(name)):
  try:
  mkdir(name, mode)
  except OSError as e:
  if not exist_ok or e.errno != errno.EEXIST or not path.isdir(name):
  raise

This should solve the problem. It also gives more or less guarantee
that errno will be EEXIST, while the current code will also raise an exception
on EROFS (read-only FS), ENOSPC (no space left) in addition to EACCES on Windows
(and possibly some other values on various systems - who knows?).

--

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-08 Thread Daniel Plachotich

New submission from Daniel Plachotich:

Since Windows 7 (or even Vista), Windows gives permission error(5, 
ERROR_ACCESS_DENIED
if you try to create a directory in a drive root with the same name as a drive 
itself,
even if you have administrative permissions. This behavior is not mentioned in 
Microsoft docs.

Here is an example session (Windows 7, admin):
d:\>IF EXIST . echo True
True
d:\>mkdir .
Access is denied.
d:\>mkdir dir
d:\>cd dir
d:\dir>mkdir .
A subdirectory or file . already exists.
d:\dir>cd ..
d:\>
d:\>py -3
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (In
tel)] on win32
>>> import os
>>> os.path.isdir('.')
True
>>> os.makedirs('.', exist_ok=True)
Traceback (most recent call last):
  File "", line 1, in 
  File "C:\Python34\lib\os.py", line 237, in makedirs
mkdir(name, mode)
PermissionError: [WinError 5] ...
>>> try:
...   os.mkdir('.')
... except OSError as e:
...   print(e.errno)
...
13

This means that if you want to write portable code, you still need to write 
like in Python 2:
if not os.path.isdir(path):
os.makedirs(path)
Which makes exist_ok useless.

The actual problem is in this line (Lib/os.py#l243):
if not exist_ok or e.errno != errno.EEXIST or not path.isdir(name):

Due the reasons described above, makedirs shouldn't rely on e.errno, so the 
right code will be:
if not (exist_ok and path.isdir(name)):

I think the issue is pretty serious to be backported.

--
components: Library (Lib)
messages: 254339
nosy: Daniel Plachotich
priority: normal
severity: normal
status: open
title: os.makedirs with exist_ok=True raises PermissionError on Windows 7^
type: behavior
versions: Python 3.2, Python 3.3, Python 3.4, Python 3.5, Python 3.6

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-08 Thread Daniel Plachotich

Daniel Plachotich added the comment:

Probably better solution:

if not (exist_ok and path.isdir(name) and
e.errno in (errno.EEXIST, errno.EACCES)):

--

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-08 Thread Daniel Plachotich

Daniel Plachotich added the comment:

Of course in examples I create '.' by hand, but in real code such things are
mostly automatic. Assume, for example, that you have a function for downloading
files:

def download_file(url, save_as):
  ...
  # Before saving, you must ensure that path exists:
  os.makedirs(os.path.dirname(save_as), exist_ok=True)
  ...

os.path.abspath is not a solution, because, as it was mentioned, mkdir with
adrive name gives the same result:
d:\>mkdir d:\\
Access is denied.

Anyway, skipping the calls must be a job of exist_ok=True, otherwise it has
any sense.

By the way, do not pay attention to my second message(msg254341): as I said
at first, mkdirs shouldn't use e.errno at all. Because, as said in docstring,
makedirs must first check whether a folder exists, and only then call mkdir.
But currently it works in reverse order, which, in essence, is the source
of the problem.

I don't know why it was done that way, because if you try "timeit"
"try->mkdir->except" vs "if not isdir->mkdir", you will see that the second
is much faster (x3 (!) times on Windows, x0.7 times on Linux (on ext4 partition)
on my machine).

So the best solution is the most straightforward - to replace try-except block 
with:
  if not path.isdir(name):
  mkdir(name, mode)

--

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-08 Thread Daniel Plachotich

Daniel Plachotich added the comment:

I meant x1.3 times faster on Linux :)

--

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25583] os.makedirs with exist_ok=True raises PermissionError on Windows 7^

2015-11-08 Thread Daniel Plachotich

Daniel Plachotich added the comment:

Of course, exist_ok must be taken into account:
if not (exist_ok and path.isdir(name)):
mkdir(name, mode)

--

___
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue25583>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com