Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-31249: Add some test for ButlerURI.join() #550

Merged
merged 1 commit into from
Jul 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 23 additions & 5 deletions python/lsst/daf/butler/core/_butlerUri/_butlerUri.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,19 +551,37 @@ def join(self, path: Union[str, ButlerURI]) -> ButlerURI:
may be this never becomes a problem but datastore templates assume
POSIX separator is being used.

Currently, if the join path is given as an absolute scheme-less
URI it will be returned as an absolute ``file:`` URI even if the
URI it is being joined to is non-file.
If an absolute `ButlerURI` is given for ``path`` is is assumed that
this should be returned directly. Giving a ``path`` of an absolute
scheme-less URI is not allowed for safety reasons as it may indicate
a mistake in the calling code.

Raises
------
ValueError
Raised if the ``path`` is an absolute scheme-less URI. In that
situation it is unclear whether the intent is to return a
``file`` URI or it was a mistake and a relative scheme-less URI
was meant.
"""
# If we have a full URI in path we will use it directly
# but without forcing to absolute so that we can trap the
# expected option of relative path.
path_uri = ButlerURI(path, forceAbsolute=False)
if path_uri.scheme:
# Check for scheme so can distinguish explicit URIs from
# absolute scheme-less URIs.
return path_uri

# Force back to string
path = path_uri.path
if path_uri.isabs():
# Absolute scheme-less path.
raise ValueError(f"Can not join absolute scheme-less {path_uri!r} to another URI.")

# If this was originally a ButlerURI extract the unquoted path from it.
# Otherwise we use the string we were given to allow "#" to appear
# in the filename if given as a plain string.
if not isinstance(path, str):
path = path_uri.unquoted_path

new = self.dirname() # By definition a directory URI

Expand Down
25 changes: 25 additions & 0 deletions tests/test_uri.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,31 @@ def testRootURI(self):
self.assertEqual(uri.root_uri().geturl(), "https://www.notexist.com:8080/")
self.assertEqual(uri2.root_uri().geturl(), "s3://www.notexist.com/")

def testJoin(self):
"""Test .join method."""

root_str = "s3://bucket/hsc/payload/"
root = ButlerURI(root_str)

self.assertEqual(root.join("b/test.txt").geturl(), f"{root_str}b/test.txt")
add_dir = root.join("b/c/d/")
self.assertTrue(add_dir.isdir())
self.assertEqual(add_dir.geturl(), f"{root_str}b/c/d/")

quote_example = "b&c.t@x#t"
needs_quote = root.join(quote_example)
self.assertEqual(needs_quote.unquoted_path, f"/hsc/payload/{quote_example}")

other = ButlerURI("file://localhost/test.txt")
self.assertEqual(root.join(other), other)
self.assertEqual(other.join("b/new.txt").geturl(), "file://localhost/b/new.txt")

joined = ButlerURI("s3://bucket/hsc/payload/").join(ButlerURI("test.qgraph", forceAbsolute=False))
self.assertEqual(joined, ButlerURI("s3://bucket/hsc/payload/test.qgraph"))

with self.assertRaises(ValueError):
ButlerURI("s3://bucket/hsc/payload/").join(ButlerURI("test.qgraph"))


@unittest.skipIf(not boto3, "Warning: boto3 AWS SDK not found!")
@mock_s3
Expand Down