The task is to implement a function root_relative_path(root : str, path : str) -> str
, which calculates the relative path with respect to root, with no intermediate ..
go beyond root
. e.g., root_relative_path('/abc', '/../def') == '/abc/def'
This question is different from How to calculate relative path in Python? because in this case, root_relative_path(root='/tmp/abc', path='/../def')
should return /tmp/abc/def
instead of /tmp/def
.
I was able to implement your root_relative_path function using a combination of the posixpath and the pathlib modules. The result is
/
, ./
, or ../
..
s.
from pathlib import Path
import posixpath
def root_relative_path(root : str, path : str) -> str:
''' Calculates the relative path with respect to the root.
Any ".."s in the relative path will be resolved,
but not in a way that would cause the relative path to go beyond the root. '''
# posixpath.normpath doesn't work as expected if the path doesn't start with a slash, so we make sure it does
if not path.startswith('/'):
path = '/' + path
# The normalization process includes resolving any ".."s
# we're only using posixpath for the relative portion of the path, the outcome will still be platform independent
path = posixpath.normpath(path)
# Remove the beginning slash so that we're not trying to join two absolute paths
path = path[1:]
joined = Path(root) / path
# Per the OPs requirements the result needed to be a string,
# But if you're allowed to use Pathlib objects, you could just return joined without converting it to a string
return str(joined)