-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Workaround for Windows Containers #2574
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,17 @@ | |
UF_HIDDEN = getattr(stat, 'UF_HIDDEN', 32768) | ||
|
||
|
||
def exists(path): | ||
"""Replacement for `os.path.exists` which works for host mapped volumes | ||
on Windows containers | ||
""" | ||
try: | ||
os.lstat(path) | ||
except OSError: | ||
return False | ||
return True | ||
|
||
|
||
def url_path_join(*pieces): | ||
"""Join components of url into a relative url | ||
|
||
|
@@ -58,26 +69,25 @@ def url2path(url): | |
pieces = [ unquote(p) for p in url.split('/') ] | ||
path = os.path.join(*pieces) | ||
return path | ||
|
||
def url_escape(path): | ||
"""Escape special characters in a URL path | ||
|
||
Turns '/foo bar/' into '/foo%20bar/' | ||
""" | ||
parts = py3compat.unicode_to_str(path, encoding='utf8').split('/') | ||
return u'/'.join([quote(p) for p in parts]) | ||
|
||
def url_unescape(path): | ||
"""Unescape special characters in a URL path | ||
|
||
Turns '/foo%20bar/' into '/foo bar/' | ||
""" | ||
return u'/'.join([ | ||
py3compat.str_to_unicode(unquote(p), encoding='utf8') | ||
for p in py3compat.unicode_to_str(path, encoding='utf8').split('/') | ||
]) | ||
|
||
_win32_FILE_ATTRIBUTE_HIDDEN = 0x02 | ||
|
||
def is_file_hidden_win(abs_path, stat_res=None): | ||
"""Is a file hidden? | ||
|
@@ -98,22 +108,15 @@ def is_file_hidden_win(abs_path, stat_res=None): | |
if os.path.basename(abs_path).startswith('.'): | ||
return True | ||
|
||
# check that dirs can be listed | ||
if os.path.isdir(abs_path): | ||
# can't trust os.access on Windows because it seems to always return True | ||
try: | ||
os.stat(abs_path) | ||
except OSError: | ||
# stat may fail on Windows junctions or non-user-readable dirs | ||
return True | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed checking for a broken symlink as I think it's better to let the user know and have them deal with it rather than pretend it doesn't exist |
||
|
||
win32_FILE_ATTRIBUTE_HIDDEN = 0x02 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Made the module level global local to this function as it isn't used elsewhere |
||
try: | ||
attrs = ctypes.windll.kernel32.GetFileAttributesW( | ||
py3compat.cast_unicode(abs_path)) | ||
py3compat.cast_unicode(abs_path) | ||
) | ||
except AttributeError: | ||
pass | ||
else: | ||
if attrs > 0 and attrs & _win32_FILE_ATTRIBUTE_HIDDEN: | ||
if attrs > 0 and attrs & win32_FILE_ATTRIBUTE_HIDDEN: | ||
return True | ||
|
||
return False | ||
|
@@ -164,12 +167,12 @@ def is_file_hidden_posix(abs_path, stat_res=None): | |
|
||
def is_hidden(abs_path, abs_root=''): | ||
"""Is a file hidden or contained in a hidden directory? | ||
|
||
This will start with the rightmost path element and work backwards to the | ||
given root to see if a path is hidden or in a hidden directory. Hidden is | ||
determined by either name starting with '.' or the UF_HIDDEN flag as | ||
determined by either name starting with '.' or the UF_HIDDEN flag as | ||
reported by stat. | ||
|
||
Parameters | ||
---------- | ||
abs_path : unicode | ||
|
@@ -191,12 +194,12 @@ def is_hidden(abs_path, abs_root=''): | |
# is_file_hidden() already checked the file, so start from its parent dir | ||
path = os.path.dirname(abs_path) | ||
while path and path.startswith(abs_root) and path != abs_root: | ||
if not os.path.exists(path): | ||
if not exists(path): | ||
path = os.path.dirname(path) | ||
continue | ||
try: | ||
# may fail on Windows junctions | ||
st = os.stat(path) | ||
st = os.lstat(path) | ||
except OSError: | ||
return True | ||
if getattr(st, 'st_flags', 0) & UF_HIDDEN: | ||
|
@@ -244,7 +247,7 @@ def to_os_path(path, root=''): | |
|
||
def to_api_path(os_path, root=''): | ||
"""Convert a filesystem path to an API path | ||
|
||
If given, root will be removed from the path. | ||
root must be a filesystem path already. | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prior to version 3.2
os.symlink
which is required for this test only existed for unix. This enables testing on Python 3 for Windows as all supported versions have this functionality now.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
os.symlink
exists now, but I think that in most situations it still raises a permission error, because normal users don't have the right to create symlinks. So I suspect that when we next do a build on Windows, this might fail.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wondered if that might be the case but I figured if the tests passed on appveyor it would be fine.
That was based on the assumption that most normal Windows users probably wouldn't be running the tests. In that case it would only affect a Windows developer trying to run the tests without admin privileges where it would fail with a permission error. I think that having some testing on Windows/appveyor is probably worth any hassle that might cause?
OT: In the future it should be possible for developers without admin privileges to create symlinks on Windows 10 - https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/#oWkhfiQvGP6wte4V.97
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, nice. I guess our build servers have got the 'creators update' and therefore are able to create symlinks. :-)