fix os.path.samefile backport on py2 + Windows

os.path.samefile is available everywhere but Windows + py2.
Backporting the py3 implementation doesn't work because
`os.stat` on Windows py2 returns 0 for st_ino and st_dev,
which will always be equal.

In this case, use case-insensitive path comparison, plus full-stat comparison (times included).
This commit is contained in:
Min RK 2016-09-16 12:53:56 +02:00
parent 03af493062
commit f96feb5e8b
2 changed files with 21 additions and 10 deletions

View File

@ -24,9 +24,14 @@ from . import tz
from notebook.utils import (
is_hidden,
to_api_path,
same_file,
)
try:
from os.path import samefile
except ImportError:
# windows + py2
from notebook.utils import samefile_simple as samefile
_script_exporter = None
@ -123,7 +128,7 @@ class FileContentsManager(FileManagerMixin, ContentsManager):
self.log.error("Post-save hook failed o-n %s", os_path, exc_info=True)
raise web.HTTPError(500, u'Unexpected error while running post hook save: %s' % e)
@validate('root_dir')
@validate('root_dir')
def _validate_root_dir(self, proposal):
"""Do a bit of validation of the root_dir."""
value = proposal['value']
@ -469,7 +474,7 @@ class FileContentsManager(FileManagerMixin, ContentsManager):
old_os_path = self._get_os_path(old_path)
# Should we proceed with the move?
if os.path.exists(new_os_path) and not same_file(old_os_path, new_os_path):
if os.path.exists(new_os_path) and not samefile(old_os_path, new_os_path):
raise web.HTTPError(409, u'File already exists: %s' % new_path)
# Move the file

View File

@ -141,11 +141,16 @@ def is_hidden(abs_path, abs_root=''):
return False
def same_file(path, other_path):
def samefile_simple(path, other_path):
"""
Check if path and other_path are hard links to the same file. This is a
utility implementation of Python's os.path.samefile which is not available
with Python 2.x and Windows.
Fill in for os.path.samefile when it is unavailable (Windows+py2).
Do a case-insensitive string comparison in this case
plus comparing the full stat result (including times)
because Windows + py2 doesn't support the stat fields
needed for identifying if it's the same file (st_ino, st_dev).
Only to be used if os.path.samefile is not available.
Parameters
-----------
@ -158,12 +163,13 @@ def same_file(path, other_path):
"""
path_stat = os.stat(path)
other_path_stat = os.stat(other_path)
return (path_stat.st_ino == other_path_stat.st_ino and
path_stat.st_dev == other_path_stat.st_dev)
return (path.lower() == other_path.lower()
and path_stat == other_path_stat)
def to_os_path(path, root=''):
"""Convert an API path to a filesystem path
If given, root will be prepended to the path.
root must be a filesystem path already.
"""