Find a relative path below a known root

Find a relative path below a known root

When a program already knows a root directory, Path.relative_to can express a descendant without repeating that root. The temporary fixture creates project/src/api.py. Calling file_path.relative_to(root) removes the project portion and returns the relative path src/api.py. This is useful when a manifest, log entry, or comparison should be scoped to a known project rather than expose an absolute location.

The assertions check both directions relevant to the controlled fixture: the derived path has the expected components, and joining it to this root recreates the original path. as_posix() is used only for output, giving forward slashes on every platform and avoiding the randomly generated temporary-directory name.

pathlib was introduced in Python 3.4, and this exact recipe requires Python 3.5+ because it calls Path.write_text. With the default walk_up=False, relative_to raises ValueError when the candidate does not begin with the supplied root. The operation is lexical: it does not inspect the filesystem. Symlinks or unresolved .. components can therefore make lexical ancestry differ from resolved ancestry; resolve paths first if that distinction matters. The example creates no symlinks, so it does not establish symlink policy. The official relative_to documentation describes both the failure behavior and lexical limitation. Path.write_text documents its Python 3.5 introduction, and TemporaryDirectory provides the disposable fixture root.

AI-assistance disclosure: AI helped draft this educational article.

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as directory:
    root = Path(directory) / "project"
    file_path = root / "src" / "api.py"
    file_path.parent.mkdir(parents=True)
    file_path.write_text("pass\n", encoding="utf-8")

    relative = file_path.relative_to(root)

    assert relative == Path("src/api.py")
    assert root / relative == file_path

    print(relative.as_posix())
src/api.py

Comments

Popular posts from this blog

Compare Two Text Files in Python Without Modifying Them

Seven CSV Quality Checks to Run Before Importing Data

Explain why SQLite transactions cannot make an HTTP call atomic