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

Disable artifact-related methods in handler + deco #1734

Merged
merged 4 commits into from
Apr 12, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Disabled `neptune command-line tool` ([#1718](https://github.com/neptune-ai/neptune-client/pull/1718))
- Disabled deleting fields in `Handler` ([#1729](https://github.com/neptune-ai/neptune-client/pull/1729))
- Removed `AbstractNeptuneObject` ([#1725](https://github.com/neptune-ai/neptune-client/pull/1725))
- Disabled artifact-related methods in `Handler` ([#1734](https://github.com/neptune-ai/neptune-client/pull/1734))

### Changes
- Stop sending `X-Neptune-LegacyClient` header ([#1715](https://github.com/neptune-ai/neptune-client/pull/1715))
Expand Down
51 changes: 30 additions & 21 deletions src/neptune/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from typing import (
TYPE_CHECKING,
Any,
Callable,
Collection,
Dict,
Iterable,
Expand Down Expand Up @@ -73,6 +74,13 @@
from neptune.objects import NeptuneObject


def feature_temporarily_unavailable(_: Callable[..., Any]) -> Callable[..., Any]:
def wrapper(*_, **__):
raise NeptuneUnsupportedFunctionalityException()

return wrapper


def validate_path_not_protected(target_path: str, handler: "Handler"):
path_protection_exception = handler._PROTECTED_PATHS.get(target_path)
if path_protection_exception:
Expand Down Expand Up @@ -468,25 +476,6 @@ def add(self, values: Union[str, Iterable[str]], *, wait: bool = False) -> None:
self._container.set_attribute(self._path, attr)
attr.add(values, wait=wait)

def _delete_item(self, path: str = None, *, wait: bool = False) -> None:
with self._container.lock():
handler = self
if path:
verify_type("path", path, str)
handler = self[path]
path = join_paths(self._path, path)
# extra check: check_protected_paths decorator does not catch flow with non-null path
validate_path_not_protected(path, self)
else:
path = self._path

attribute = self._container.get_attribute(path)
if isinstance(attribute, Namespace):
for child_path in list(attribute):
handler.pop(child_path, wait=wait)
else:
self._container._pop_impl(parse_path(path), wait=wait)

@check_protected_paths
def remove(self, values: Union[str, Iterable[str]], *, wait: bool = False) -> None:
"""Removes the provided tags from the set.
Expand Down Expand Up @@ -650,6 +639,7 @@ def download_last(self, destination: str = None) -> None:
"""
return self._pass_call_to_attr(function_name="download_last", destination=destination)

@feature_temporarily_unavailable
def fetch_hash(self) -> str:
"""Fetches the hash of an artifact.

Expand All @@ -666,6 +656,7 @@ def fetch_extension(self) -> str:
"""
return self._pass_call_to_attr(function_name="fetch_extension")

@feature_temporarily_unavailable
def fetch_files_list(self) -> List[ArtifactFileData]:
"""Fetches the list of files in an artifact and their metadata.

Expand Down Expand Up @@ -714,6 +705,7 @@ def list_fileset_files(self, path: Optional[str] = None) -> List[FileEntry]:
def _pass_call_to_attr(self, function_name, **kwargs):
return getattr(self._get_attribute(), function_name)(**kwargs)

@feature_temporarily_unavailable
@check_protected_paths
def track_files(self, path: str, *, destination: str = None, wait: bool = False) -> None:
"""Creates an artifact tracking some files.
Expand All @@ -730,11 +722,28 @@ def track_files(self, path: str, *, destination: str = None, wait: bool = False)
attr.track_files(path=path, destination=destination, wait=wait)

def __delitem__(self, path) -> None:
raise NeptuneUnsupportedFunctionalityException()
self.pop(path)

@feature_temporarily_unavailable
@check_protected_paths
def pop(self, path: str = None, *, wait: bool = False) -> None:
raise NeptuneUnsupportedFunctionalityException()
with self._container.lock():
handler = self
if path:
verify_type("path", path, str)
handler = self[path]
path = join_paths(self._path, path)
# extra check: check_protected_paths decorator does not catch flow with non-null path
validate_path_not_protected(path, self)
else:
path = self._path

attribute = self._container.get_attribute(path)
if isinstance(attribute, Namespace):
for child_path in list(attribute):
handler.pop(child_path, wait=wait)
else:
self._container._pop_impl(parse_path(path), wait=wait)


class ExtendUtils:
Expand Down
2 changes: 2 additions & 0 deletions tests/e2e/standard/test_artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import pytest

from neptune.exceptions import NeptuneUnsupportedFunctionalityException
from neptune.objects import NeptuneObject
from tests.e2e.base import (
AVAILABLE_CONTAINERS,
Expand All @@ -34,6 +35,7 @@
)


@pytest.mark.xfail(reason="Artifact methods disabled", strict=True, raises=NeptuneUnsupportedFunctionalityException)
class TestArtifacts(BaseE2ETest):
@pytest.mark.parametrize("container", AVAILABLE_CONTAINERS, indirect=True)
def test_local_creation(self, container: NeptuneObject):
Expand Down
8 changes: 7 additions & 1 deletion tests/unit/neptune/new/attributes/atoms/test_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import uuid
from unittest.mock import Mock

import pytest
from _pytest.monkeypatch import MonkeyPatch
from mock import (
MagicMock,
Expand All @@ -27,7 +28,10 @@

from neptune import Run
from neptune.attributes.atoms.artifact import Artifact
from neptune.exceptions import NeptuneUnhandledArtifactTypeException
from neptune.exceptions import (
NeptuneUnhandledArtifactTypeException,
NeptuneUnsupportedFunctionalityException,
)
from neptune.internal.artifacts.types import (
ArtifactDriver,
ArtifactDriversMap,
Expand Down Expand Up @@ -106,10 +110,12 @@ def tearDown(self):
self.exp.stop()
self.monkeypatch.undo()

@pytest.mark.xfail(reason="Artifact methods disabled", strict=True, raises=NeptuneUnsupportedFunctionalityException)
def test_fetch_hash(self):
fetched_hash = self.exp[self.path_str].fetch_hash()
self.assertEqual(self.artifact_hash, fetched_hash)

@pytest.mark.xfail(reason="Artifact methods disabled", strict=True, raises=NeptuneUnsupportedFunctionalityException)
def test_fetch_files_list(self):
fetched_hash = self.exp[self.path_str].fetch_files_list()
self.assertEqual(self.artifact_files, fetched_hash)
Expand Down
1 change: 1 addition & 0 deletions tests/unit/neptune/new/test_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ def setUpClass(cls) -> None:
os.environ[PROJECT_ENV_NAME] = "organization/project"
os.environ[API_TOKEN_ENV_NAME] = ANONYMOUS_API_TOKEN

@pytest.mark.xfail(reason="Artifact methods disabled", strict=True, raises=NeptuneUnsupportedFunctionalityException)
def test_artifacts(self):
with init_run(mode="debug", flush_period=0.5) as exp:
exp["art1"].track_files("s3://path/to/tracking/file", destination="/some/destination")
Expand Down
Loading