Discussion:
os.path.cansymlink(path)
anatoly techtonik
2014-07-24 16:51:08 UTC
Permalink
This is a live code from current virtualenv.py:

if hasattr(os, 'symlink'):
logger.info('Symlinking Python bootstrap modules')

This code is wrong, because OS support for
symlinks doesn't guarantee that mounted filesystem
can do this, resulting in OSError at runtime. So, the
proper check would be to check if specific path
supports symlinking.

The idea is:

os.path.cansymlink(path) - Return True if filesystem
of specified path can be symlinked.

Yes/No/Opinions?
--
anatoly t.
Geoffrey Spear
2014-07-24 17:33:28 UTC
Permalink
Post by anatoly techtonik
logger.info('Symlinking Python bootstrap modules')
This code is wrong, because OS support for
symlinks doesn't guarantee that mounted filesystem
can do this, resulting in OSError at runtime. So, the
proper check would be to check if specific path
supports symlinking.
os.path.cansymlink(path) - Return True if filesystem
of specified path can be symlinked.
Yes/No/Opinions?
Surely the third-party module you found that wrong code in has their
own communication channels?
Steven D'Aprano
2014-07-24 17:45:31 UTC
Permalink
[...]
Post by Geoffrey Spear
Surely the third-party module you found that wrong code in has their
own communication channels?
Anatoly is not asking for a fix for the (possibly) buggy code in
virtualenv, but suggesting an enhancement for the Python standard
library. That makes this the right place to ask the question.
--
Steven
dw+
2014-07-24 17:53:16 UTC
Permalink
Post by Geoffrey Spear
This code is wrong, because OS support for symlinks doesn't
guarantee that mounted filesystem can do this, resulting in OSError
at runtime. So, the proper check would be to check if specific path
supports symlinking.
os.path.cansymlink(path) - Return True if filesystem
of specified path can be symlinked.
Yes/No/Opinions?
-1, since there is no sane way to guarantee a FS operation will succeed
without trying it in most cases. Even if a filesystem (driver) supports
the operation, the filesystem (data) might be exhausted, e.g. inode
count, max directory entries, ... And if not that, then e.g. in the case
of NFS or CIFS, while the protocol might support the operation, there is
no mechanism for a particular server implementation to communicate that
it does not support it.

Even if none of this were true, it also introduces a race between a
program testing the state of the filesystem, and that state changing,
e.g. due to USB disconnect, or a lazy unmount succeeding, or..


David
Post by Geoffrey Spear
Surely the third-party module you found that wrong code in has their
own communication channels?
_______________________________________________
Python-ideas mailing list
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
Giampaolo Rodola'
2014-07-25 09:54:07 UTC
Permalink
-1 for me as well given the reasons mentioned above.
Post by dw+
Post by Geoffrey Spear
This code is wrong, because OS support for symlinks doesn't
guarantee that mounted filesystem can do this, resulting in OSError
at runtime. So, the proper check would be to check if specific path
supports symlinking.
os.path.cansymlink(path) - Return True if filesystem
of specified path can be symlinked.
Yes/No/Opinions?
-1, since there is no sane way to guarantee a FS operation will succeed
without trying it in most cases. Even if a filesystem (driver) supports
the operation, the filesystem (data) might be exhausted, e.g. inode
count, max directory entries, ... And if not that, then e.g. in the case
of NFS or CIFS, while the protocol might support the operation, there is
no mechanism for a particular server implementation to communicate that
it does not support it.
Even if none of this were true, it also introduces a race between a
program testing the state of the filesystem, and that state changing,
e.g. due to USB disconnect, or a lazy unmount succeeding, or..
David
Post by Geoffrey Spear
Surely the third-party module you found that wrong code in has their
own communication channels?
_______________________________________________
Python-ideas mailing list
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-ideas mailing list
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
anatoly techtonik
2014-07-25 10:17:13 UTC
Permalink
Post by dw+
This code is wrong, because OS support for symlinks doesn't
guarantee that mounted filesystem can do this, resulting in OSError
at runtime. So, the proper check would be to check if specific path
supports symlinking.
os.path.cansymlink(path) - Return True if filesystem
of specified path can be symlinked.
Yes/No/Opinions?
-1, since there is no sane way to guarantee a FS operation will succeed
without trying it in most cases.
Even if a filesystem (driver) supports
the operation, the filesystem (data) might be exhausted, e.g. inode
count, max directory entries, ... And if not that, then e.g. in the case
of NFS or CIFS, while the protocol might support the operation, there is
no mechanism for a particular server implementation to communicate that
it does not support it.
You do realize that high level program logic changes depending on the fact
that FS supports symlinks or not. It is not "an exceptional" case as you've
presented it.

This is not a replacement for os.symlink(), but doc link to this function will
help people avoid this trap and runtime errors in future.
--
anatoly t.
Chris Angelico
2014-07-25 10:53:02 UTC
Permalink
Post by anatoly techtonik
You do realize that high level program logic changes depending on the fact
that FS supports symlinks or not. It is not "an exceptional" case as you've
presented it.
There are plenty of other non-exceptional cases that are signalled
with exceptions. It's part of the EAFP model and its reliability. If
high level logic changes, it surely can be like this:

try:
os.symlink(whatever)
except OSError:
alternate_logic()

How would asking the path if it's symlinkable (by the way, do you ask
the source or destination?) improve that?

ChrisA

anatoly techtonik
2014-07-25 10:08:23 UTC
Permalink
Post by Geoffrey Spear
Post by anatoly techtonik
logger.info('Symlinking Python bootstrap modules')
This code is wrong, because OS support for
symlinks doesn't guarantee that mounted filesystem
can do this, resulting in OSError at runtime. So, the
proper check would be to check if specific path
supports symlinking.
os.path.cansymlink(path) - Return True if filesystem
of specified path can be symlinked.
Yes/No/Opinions?
Surely the third-party module you found that wrong code in has their
own communication channels?
I can't get how does this comment contributes to the idea. Care to
explain?
--
anatoly t.
Steven D'Aprano
2014-07-24 17:43:41 UTC
Permalink
Post by anatoly techtonik
logger.info('Symlinking Python bootstrap modules')
This code is wrong, because OS support for
symlinks doesn't guarantee that mounted filesystem
can do this, resulting in OSError at runtime. So, the
proper check would be to check if specific path
supports symlinking.
os.path.cansymlink(path) - Return True if filesystem
of specified path can be symlinked.
Yes/No/Opinions?
No. Even if the file system supports symlinks, doesn't mean that you can
create one. You may not have privileges to create the symlink, or some
other runtime error may occur.

Like most other file system operations, you should guard them with a
try...except, not "Look Before You Leap".
--
Steven
Oleg Broytman
2014-07-25 10:23:40 UTC
Permalink
Hi!
Post by anatoly techtonik
logger.info('Symlinking Python bootstrap modules')
This code is wrong, because OS support for
symlinks doesn't guarantee that mounted filesystem
can do this, resulting in OSError at runtime. So, the
proper check would be to check if specific path
supports symlinking.
os.path.cansymlink(path) - Return True if filesystem
of specified path can be symlinked.
Yes/No/Opinions?
Such function (if it would be a function) should return one of three
answer, not two. Something like:

None - I don't know if the OS/fs support symlinks because another
OSError occurred during test (perhaps not enough rights to write
to the path);
False- the path clearly doesn't support symlinks;
True - the path positively supports symlinks.

Implement the function in a module and publish the module at PyPI.
Warn users (in accompanying docs) that even if a path supports (or
doesn't support) symlinks this says nothing about any subpath of the
path because a subpath can be a mount of a different fs.

Oleg.
--
Oleg Broytman http://phdru.name/ phd-54Rvo0EEewRBDLzU/***@public.gmane.org
Programmers don't die, they just GOSUB without RETURN.
Loading...