how to determine whether pathname1 is below bathname2

2010-07-11 Thread Gelonida
Hi,

I wanted to figure out whether a given path name is below another path name.

Surprisingly this turned out to be more difficult than initially
anticipated:

Let's assume I want to find out, whether path1 is below path2


First I thought about checking whether
path1 starts with path2

For this I had to
- convert path1 / path2 to absolute paths
- I had to normalize the path name

Further this would still fail for
path1='/tmp/dir11' and path2='/tmp/dir1'


next option would be to split both absolute and normalized
paths by os.sep and check whether the path2's split list
starts with path1's split list.

That should work but is also not really nice.


finally I came up with:

#
import os
def is_below_dir(fname,topdir):
relpath = os.path.relpath(fname,topdir)
return not relpath.startswith('..'+os.sep)

print is_below_dir(path1,path2)
#
The basic idea is, if the path name of path1
relative to path2 does NOT start with '..', then
it must be below path2


Does anybody see pitfalls with that solution?
Is there by any chance a function, that I overlooked,
which does already what I'd like to do?



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: how to determine whether pathname1 is below bathname2

2010-07-11 Thread Thomas Jollans
On 07/11/2010 03:37 PM, Gelonida wrote:
 #
 import os
 def is_below_dir(fname,topdir):
 relpath = os.path.relpath(fname,topdir)
 return not relpath.startswith('..'+os.sep)
 
 print is_below_dir(path1,path2)
 #
 The basic idea is, if the path name of path1
 relative to path2 does NOT start with '..', then
 it must be below path2
 
 
 Does anybody see pitfalls with that solution?
 Is there by any chance a function, that I overlooked,
 which does already what I'd like to do?

It probably won't work on Windows because it isolates volumes (drive
letters). What does, for example, os.path.relpath do when
you pass r'c:\foo\bar', r'y:\drive\letters\are\silly' ? I see two
reasonably correct options:

either raise an exception (there is no relative path) or return the
absolute path, which doesn't start with ..

On UNIX, the only potential problem I see is that it may or may not do
what you expect when symlinks are involved somewhere.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: how to determine whether pathname1 is below bathname2

2010-07-11 Thread Gelonida
Hi Thomas,

Thomas Jollans wrote:
 On 07/11/2010 03:37 PM, Gelonida wrote:
 #
 import os
 def is_below_dir(fname,topdir):
 relpath = os.path.relpath(fname,topdir)
 return not relpath.startswith('..'+os.sep)

 print is_below_dir(path1,path2)
 #
 The basic idea is, if the path name of path1
 relative to path2 does NOT start with '..', then
 it must be below path2


 Does anybody see pitfalls with that solution?
 Is there by any chance a function, that I overlooked,
 which does already what I'd like to do?
 
 It probably won't work on Windows because it isolates volumes (drive
 letters). What does, for example, os.path.relpath do when
 you pass r'c:\foo\bar', r'y:\drive\letters\are\silly' ? I see two
 reasonably correct options:
Thanks, Indeed. different drives raise an ecception.
I could catch the ValueError and let it just return False

 
 either raise an exception (there is no relative path) or return the
 absolute path, which doesn't start with ..
 
 On UNIX, the only potential problem I see is that it may or may not do
 what you expect when symlinks are involved somewhere.

Also true. In my case I'd prefer it would not follow, but
it doesn't really matter.


So my function in order to be portable
had now to look like:
#
import os
def is_below_dir(fname,topdir):
try:
   relpath = os.path.relpath(fname,topdir)
except ValueError:
return False
return not relpath.startswith('..'+os.sep)

print is_below_dir(path1,path2)
#

if I wanted to folow symlinks, then had to apply
os.path.realpath() on
fname AND on topdir


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: how to determine whether pathname1 is below bathname2

2010-07-11 Thread Dan Stromberg
You could probably:

cd to dir1
getcwd

cd to dir2
getcwd

repeat
   cd ..
   getcwd
   if getcwd == dir1's cwd, then under
until at /

cd to dir1
repeat
   cd ..
   getcwd
   if getcwd == dir2's cwd, then under
until at /

This should deal with symlinks and junctions, as long as you aren't worried
about permissions issues on directories.

On Sun, Jul 11, 2010 at 7:34 AM, Gelonida gelon...@gmail.com wrote:

 Hi Thomas,

 Thomas Jollans wrote:
  On 07/11/2010 03:37 PM, Gelonida wrote:
  #
  import os
  def is_below_dir(fname,topdir):
  relpath = os.path.relpath(fname,topdir)
  return not relpath.startswith('..'+os.sep)
 
  print is_below_dir(path1,path2)
  #
  The basic idea is, if the path name of path1
  relative to path2 does NOT start with '..', then
  it must be below path2
 
 
  Does anybody see pitfalls with that solution?
  Is there by any chance a function, that I overlooked,
  which does already what I'd like to do?
 
  It probably won't work on Windows because it isolates volumes (drive
  letters). What does, for example, os.path.relpath do when
  you pass r'c:\foo\bar', r'y:\drive\letters\are\silly' ? I see two
  reasonably correct options:
 Thanks, Indeed. different drives raise an ecception.
 I could catch the ValueError and let it just return False

 
  either raise an exception (there is no relative path) or return the
  absolute path, which doesn't start with ..
 
  On UNIX, the only potential problem I see is that it may or may not do
  what you expect when symlinks are involved somewhere.

 Also true. In my case I'd prefer it would not follow, but
 it doesn't really matter.


 So my function in order to be portable
 had now to look like:
 #
 import os
 def is_below_dir(fname,topdir):
 try:
relpath = os.path.relpath(fname,topdir)
 except ValueError:
return False
 return not relpath.startswith('..'+os.sep)

 print is_below_dir(path1,path2)
 #

 if I wanted to folow symlinks, then had to apply
 os.path.realpath() on
 fname AND on topdir


 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list