Skip to content

Commit

Permalink
Added support for UNC paths and tests for UNC and posix paths
Browse files Browse the repository at this point in the history
Signed-off-by: Doug Halley <[email protected]>
  • Loading branch information
douglascomet committed Oct 25, 2023
1 parent 745e614 commit 90ca9f3
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
23 changes: 18 additions & 5 deletions src/py-opentimelineio/opentimelineio/url_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""Utilities for conversion between urls and file paths"""

import os
import sys

from urllib import (
parse as urlparse,
Expand Down Expand Up @@ -44,16 +45,20 @@ def filepath_from_url(urlstr):
Take an url and return a filepath.
URLs can either be encoded according to the `RFC 3986`_ standard or not.
Additionally, Windows mapped paths need to be accounted for when processing a
URL; however, there are `ongoing discussions`_ about how to best handle this within
Python. This function is meant to cover all of these scenarios in the interim.
Additionally, Windows mapped drive letter and UNC paths need to be accounted for
when processing URL(s); however, there are `ongoing discussions`_ about how to best
handle this within Python developer community. This function is meant to cover
these scenarios in the interim.
.. _RFC 3986: https://tools.ietf.org/html/rfc3986#section-2.1
.. _ongoing discussions: https://discuss.python.org/t/file-uris-in-python/15600
"""

# De-encode the URL
decoded_url_str = urlparse.unquote(urlstr)

# Parse provided URL
parsed_result = urlparse.urlparse(urlstr)
parsed_result = urlparse.urlparse(decoded_url_str)

# Convert the parsed URL to a path
filepath = Path(request.url2pathname(parsed_result.path))
Expand All @@ -62,10 +67,18 @@ def filepath_from_url(urlstr):
if PureWindowsPath(parsed_result.netloc).drive:
filepath = Path(parsed_result.netloc + parsed_result.path)

# Otherwise check if the specified index is a windows drive, then offset the path
# Check if the specified index is a windows drive, if it is then do nothing
elif PureWindowsPath(filepath.parts[0]).drive:
filepath = filepath

# Check if the specified index is a windows drive, then offset the path
elif PureWindowsPath(filepath.parts[1]).drive:
# Remove leading "/" if/when `request.url2pathname` yields "/S:/path/file.ext"
filepath = filepath.relative_to(filepath.root)

# Last resort, if using a "file" schema, then strip the "file:" prefix
elif parsed_result.scheme == 'file':
filepath = Path(decoded_url_str.strip('file:'))

# Convert "\" to "/" if needed
return filepath.as_posix()
25 changes: 21 additions & 4 deletions tests/test_url_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,16 @@
)

ENCODED_WINDOWS_URL = "file://localhost/S%3a/path/file.ext"
WINDOWS_URL = "file://S:/path/file.ext"
CORRECTED_WINDOWS_PATH = "S:/path/file.ext"
WINDOWS_DRIVE_URL = "file://S:/path/file.ext"
CORRECTED_WINDOWS_DRIVE_PATH = "S:/path/file.ext"

ENCODED_WINDOWS_UNC_URL = "file://unc/path/sub%20dir/file.ext"
WINDOWS_UNC_URL = "file://unc/path/sub dir/file.ext"
CORRECTED_WINDOWS_UNC_PATH = "//unc/path/sub dir/file.ext"

ENCODED_POSIX_URL = "file:///path/sub%20dir/file.ext"
POSIX_URL = "file:///path/sub dir/file.ext"
CORRECTED_POSIX_PATH = "/path/sub dir/file.ext"

class TestConversions(unittest.TestCase):
def test_roundtrip_abs(self):
Expand All @@ -56,9 +63,19 @@ def test_roundtrip_rel(self):
self.assertEqual(os.path.normpath(result), MEDIA_EXAMPLE_PATH_REL)

def test_windows_urls(self):
for url in (ENCODED_WINDOWS_URL, WINDOWS_URL):
for url in (ENCODED_WINDOWS_URL, WINDOWS_DRIVE_URL):
processed_url = otio.url_utils.filepath_from_url(url)
self.assertEqual(processed_url, CORRECTED_WINDOWS_DRIVE_PATH)

def test_windows_unc_urls(self):
for url in (ENCODED_WINDOWS_UNC_URL, WINDOWS_UNC_URL):
processed_url = otio.url_utils.filepath_from_url(url)
self.assertEqual(processed_url, CORRECTED_WINDOWS_UNC_PATH)

def test_posix_urls(self):
for url in (ENCODED_POSIX_URL, POSIX_URL):
processed_url = otio.url_utils.filepath_from_url(url)
self.assertEqual(processed_url, CORRECTED_WINDOWS_PATH)
self.assertEqual(processed_url, CORRECTED_POSIX_PATH)


if __name__ == "__main__":
Expand Down

0 comments on commit 90ca9f3

Please sign in to comment.