Darren Weber
Darren Weber

Reputation: 1675

How to check that two python pathlib.Path have the same parents?

With two Path objects that share the same parent paths, how do you compare them to assert that they do in fact share the same parents?

>>> list(Path(input).parents)
[PosixPath('/usr/src/app'), PosixPath('/usr/src'), PosixPath('/usr'), PosixPath('/')]
>>> list(Path(output).parents)
[PosixPath('/usr/src/app'), PosixPath('/usr/src'), PosixPath('/usr'), PosixPath('/')]
>>> Path(input).parents == Path(output).parents
False

# huh?

Although the following works, it seems awkward to cast it to a List:

>>> list(Path(input).parents) == list(Path(output).parents)
True

Upvotes: 3

Views: 4994

Answers (1)

Ant
Ant

Reputation: 590

Path.parents actually returns a helper object which enables indexed access and efficient iteration over the path elements (of type pathlib._PathParents). As a result your comparison is failing because it is trying to compare these two helper objects rather than their contents.

The docs are somewhat misleading in this sense:

Path.parents: An immutable sequence providing access to the logical ancestors of the path

...to actually answer the question, you have options:

As pointed out in comments you can simply compare the parents:

Path(input).parent == Path(output).parent

This works in many cases but will not match if the path isn't of the same form - i.e. when .. appears in the path, or symlinks are present.

The Path(...).samefile(...) method provides a good way to avoid these issues, but be warned that using Path(...).parent.samefile(...) can still be a problem due to to parent calculation ignoring ...

Using the form Path(...).resolve().parent.samefile(...) is the most comprehensive way I've found of avoiding all of these issues.

For this particular question it would look like:

Path(input).resolve().parent.samefile(Path(output).resolve().parent)

Upvotes: 4

Related Questions