Skip to content

Commit

Permalink
Validate input and lightly mount (#1537)
Browse files Browse the repository at this point in the history
* Validate input and lightly mount
  • Loading branch information
guarin committed May 15, 2024
1 parent 90c5d9f commit 3484416
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 3 deletions.
42 changes: 42 additions & 0 deletions lightly/api/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from typing import Sequence
from urllib import parse

from lightly.data import _helpers


def get_server(
paths: Sequence[Path],
Expand Down Expand Up @@ -50,6 +52,46 @@ def send_response_only(self, code, message=None):
return HTTPServer((host, port), _LocalDatasourceRequestHandler)


def validate_input_mount(input_mount: Path) -> None:
"""Validates that the input mount is a directory and contains files."""
input_mount = input_mount.resolve()
if not input_mount.exists():
raise ValueError(
f"Path for 'input_mount' argument '{input_mount}' does not exist."
)
if not input_mount.is_dir():
raise ValueError(
f"Path for 'input_mount' argument '{input_mount}' is not a directory."
)
if not _dir_contains_image_or_video(path=input_mount):
raise ValueError(
f"Path for 'input_mount' argument '{input_mount}' does not contain any "
"images or videos. Please verify that this is the correct directory. See "
"our docs on lightly-serve for more information: "
"https://docs.lightly.ai/docs/local-storage#optional-after-run-view-local-data-in-lightly-platform"
)


def validate_lightly_mount(lightly_mount: Path) -> None:
lightly_mount = lightly_mount.resolve()
"""Validates that the Lightly mount is a directory."""
if not lightly_mount.exists():
raise ValueError(
f"Path for 'lightly_mount' argument '{lightly_mount}' does not exist."
)
if not lightly_mount.is_dir():
raise ValueError(
f"Path for 'lightly_mount' argument '{lightly_mount}' is not a directory."
)


def _dir_contains_image_or_video(path: Path) -> bool:
extensions = set(_helpers.IMG_EXTENSIONS + _helpers.VIDEO_EXTENSIONS)
return any(
p for p in path.rglob("**/*") if p.is_file() and p.suffix.lower() in extensions
)


def _translate_path(path: str, directories: Sequence[Path]) -> str:
"""Translates a relative path to a file in the local datasource.
Expand Down
18 changes: 15 additions & 3 deletions lightly/cli/serve_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import hydra

from lightly.api import serve
from lightly.api.serve import validate_input_mount, validate_lightly_mount
from lightly.cli._helpers import fix_hydra_arguments
from lightly.utils.hipify import bcolors

Expand All @@ -28,15 +29,26 @@ def lightly_serve(cfg):
"""
if not cfg.input_mount:
print("Please provide a valid input mount. Use --help for more information.")
print(
"Please provide a valid 'input_mount' argument. Use --help for more "
"information."
)
sys.exit(1)

if not cfg.lightly_mount:
print("Please provide a valid Lightly mount. Use --help for more information.")
print(
"Please provide a valid 'lightly_mount' argument. Use --help for more "
"information."
)
sys.exit(1)

input_mount = Path(cfg.input_mount)
validate_input_mount(input_mount=input_mount)
lightly_mount = Path(cfg.lightly_mount)
validate_lightly_mount(lightly_mount=lightly_mount)

httpd = serve.get_server(
paths=[Path(cfg.input_mount), Path(cfg.lightly_mount)],
paths=[input_mount, lightly_mount],
host=cfg.host,
port=cfg.port,
)
Expand Down
62 changes: 62 additions & 0 deletions tests/api/test_serve.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,70 @@
from pathlib import Path

import pytest

from lightly.api import serve


def test_validate_input_mount(tmp_path: Path) -> None:
(tmp_path / "image.png").touch()
serve.validate_input_mount(input_mount=tmp_path)


def test_validate_input_mount__not_exist(tmp_path: Path) -> None:
with pytest.raises(
ValueError,
match=f"Path for 'input_mount' argument '{tmp_path}/not-existant' does not exist.",
):
serve.validate_input_mount(input_mount=tmp_path / "not-existant")


def test_validate_input_mount__not_directory(tmp_path: Path) -> None:
(tmp_path / "file.txt").touch()
with pytest.raises(
ValueError,
match=f"Path for 'input_mount' argument '{tmp_path}/file.txt' is not a directory.",
):
serve.validate_input_mount(input_mount=tmp_path / "file.txt")


def test_validate_input_mount__no_files(tmp_path: Path) -> None:
with pytest.raises(
ValueError,
match=(
f"Path for 'input_mount' argument '{tmp_path}' does not contain any images "
"or videos"
),
):
serve.validate_input_mount(input_mount=tmp_path)


def test_validate_lightly_mount(tmp_path: Path) -> None:
serve.validate_lightly_mount(lightly_mount=tmp_path)


def test_validate_lightly_mount__not_exist(tmp_path: Path) -> None:
with pytest.raises(
ValueError,
match=(
f"Path for 'lightly_mount' argument '{tmp_path}/not-existant' does not "
"exist."
),
):
serve.validate_lightly_mount(lightly_mount=tmp_path / "not-existant")


def test_validate_lightly_mount__not_directory(tmp_path: Path) -> None:
(tmp_path / "file.txt").touch()
with pytest.raises(
ValueError,
match=(
f"Path for 'lightly_mount' argument '{tmp_path}/file.txt' is not a "
"directory."
),
):
serve.validate_lightly_mount(lightly_mount=tmp_path / "file.txt")


def test__translate_path(tmp_path: Path) -> None:
tmp_file = tmp_path / "hello/world.txt"
assert serve._translate_path(path="/hello/world.txt", directories=[]) == ""
Expand Down

0 comments on commit 3484416

Please sign in to comment.