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

Support passing additional search paths via package_dirs argument #13

Merged
merged 6 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions src/resolve_robotics_uri_py/resolve_robotics_uri_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,31 @@ def pathlist_list_to_string(path_list: Iterable[str | pathlib.Path]) -> str:
# ===================


def resolve_robotics_uri(uri: str) -> pathlib.Path:
def resolve_robotics_uri(
uri: str, package_dirs: list[str] | None = None
) -> pathlib.Path:
"""
Resolve a robotics URI to an absolute filename.

Args:
uri: The URI to resolve.
package_dirs: A list of additional paths to look for the file.

Returns:
The absolute filename corresponding to the URI.

Raises:
FileNotFoundError: If no file corresponding to the URI is found.

Note:
In case `package_dirs` is not provided, the function will look for the file in the
default search paths specified by the environment variables in `SupportedEnvVars`.

If a given model searches for the meshes in `package://ModelName/meshes/mesh.stl`, and the
actual mesh is in `/usr/local/share/ModelName/meshes/mesh.stl`, the `package_dirs` should
contain `/usr/local/share`.
"""
package_dirs = package_dirs if isinstance(package_dirs, list) else [package_dirs]

# If the URI has no scheme, use by default file:// which maps the resolved input
# path to a URI with empty authority
Expand All @@ -104,8 +116,8 @@ def resolve_robotics_uri(uri: str) -> pathlib.Path:

if uri.startswith("file:"):
# Strip the scheme from the URI
uri = uri.replace(f"file://", "")
uri = uri.replace(f"file:", "")
uri = uri.replace("file://", "")
uri = uri.replace("file:", "")

# Create the file path, resolving symlinks and '..'
uri_file_path = pathlib.Path(uri).resolve()
Expand Down Expand Up @@ -145,7 +157,11 @@ def resolve_robotics_uri(uri: str) -> pathlib.Path:
model_filenames = []

# Search the resource in the path from the env variables
for folder in set(get_search_paths_from_envs(SupportedEnvVars)):
for folder in set(get_search_paths_from_envs(SupportedEnvVars)) | {
path
for directory in package_dirs
if directory and (path := pathlib.Path(directory)).exists()
}:

# Join the folder from environment variable and the URI path
candidate_file_name = folder / uri_path
Expand Down Expand Up @@ -181,11 +197,18 @@ def main():
)
)
parser.add_argument("uri", metavar="URI", type=str, help="URI to resolve")
parser.add_argument(
"--package_dirs",
metavar="PATH",
type=str,
help="Additional paths to look for the file",
default=None,
)

args = parser.parse_args()

try:
result = resolve_robotics_uri(args.uri)
result = resolve_robotics_uri(args.uri, args.package_dirs)
except FileNotFoundError as e:
print(e, file=sys.stderr)
sys.exit(1)
Expand Down
24 changes: 23 additions & 1 deletion test/test_resolve_robotics_uri_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,29 @@ def test_scheme_file():
assert path_of_file == temp_name

# Try to find an existing file (the Python executable) without any file:/ scheme
path_of_python_executable = resolve_robotics_uri_py.resolve_robotics_uri(sys.executable)
path_of_python_executable = resolve_robotics_uri_py.resolve_robotics_uri(
sys.executable
)
assert path_of_python_executable == pathlib.Path(sys.executable)


def test_additional_search_path():

import tempfile
import pathlib
import resolve_robotics_uri_py

clear_env_vars()

uri = "model://my_model"

with tempfile.TemporaryDirectory() as temp_dir:

temp_dir_path = pathlib.Path(temp_dir).resolve()
temp_dir_path.mkdir(exist_ok=True)
top_level = temp_dir_path / "my_model"
top_level.touch(exist_ok=True)

# Test resolving a URI with an additional search path
result = resolve_robotics_uri_py.resolve_robotics_uri(uri, temp_dir)
assert result == temp_dir_path / "my_model"
Loading