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

[IO-1018][internal] Create Dataset meta method #621

Merged
merged 2 commits into from
Jun 27, 2023
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
95 changes: 92 additions & 3 deletions darwin/future/meta/objects/dataset.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import List, Optional, Tuple, Union

from darwin.future.core.datasets.create_dataset import create_dataset
from darwin.future.core.datasets.get_dataset import get_dataset
from darwin.future.core.datasets.remove_dataset import remove_dataset
from darwin.future.data_objects.dataset import Dataset
Expand All @@ -23,15 +24,50 @@ def get_dataset_by_id(self) -> Dataset:
# TODO: implement
raise NotImplementedError()

def create_dataset(self) -> Dataset:
# TODO: implement in IO-1018
raise NotImplementedError()
def create_dataset(self, slug: str) -> Tuple[Optional[List[Exception]], Optional[Dataset]]:
"""
Creates a new dataset for the given team

Parameters
----------
slug: str [a-b0-9-_]
The slug of the dataset to create

Returns
-------
Tuple[Optional[List[Exception]], Optional[Dataset]]
A tuple containing a list of exceptions and the dataset created

"""
exceptions = []
dataset: Optional[Dataset] = None

try:
self._validate_slug(slug)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not blocking but I feel like this has some crossover with the pydantic validation functions and we could reuse them.

dataset = create_dataset(self.client, slug)
except Exception as e:
exceptions.append(e)

return exceptions or None, dataset

def update_dataset(self) -> Dataset:
# TODO: implement in IO-1018
raise NotImplementedError()

def delete_dataset(self, dataset_id: Union[int, str]) -> Tuple[Optional[List[Exception]], int]:
"""
Deletes a dataset by id or slug

Parameters
----------
dataset_id: Union[int, str]
The id or slug of the dataset to delete

Returns
-------
Tuple[Optional[List[Exception]], int]
A tuple containing a list of exceptions and the number of datasets deleted
"""
exceptions = []
dataset_deleted = -1

Expand All @@ -48,6 +84,22 @@ def delete_dataset(self, dataset_id: Union[int, str]) -> Tuple[Optional[List[Exc

@staticmethod
def _delete_by_slug(client: MetaClient, slug: str) -> int:
"""
(internal) Deletes a dataset by slug

Parameters
----------
client: MetaClient
The client to use to make the request

slug: str
The slug of the dataset to delete

Returns
-------
int
The dataset deleted
"""
assert_is(isinstance(client, MetaClient), "client must be a MetaClient")
assert_is(isinstance(slug, str), "slug must be a string")

Expand All @@ -61,8 +113,45 @@ def _delete_by_slug(client: MetaClient, slug: str) -> int:

@staticmethod
def _delete_by_id(client: MetaClient, dataset_id: int) -> int:
"""
(internal) Deletes a dataset by id

Parameters
----------
client: MetaClient
The client to use to make the request

dataset_id: int
The id of the dataset to delete

Returns
-------
int
The dataset deleted
"""
assert_is(isinstance(client, MetaClient), "client must be a MetaClient")
assert_is(isinstance(dataset_id, int), "dataset_id must be an integer")

dataset_deleted = remove_dataset(client, dataset_id)
return dataset_deleted

@staticmethod
def _validate_slug(slug: str) -> None:
"""
Validates a slug

Parameters
----------
slug: str
The slug to validate

Raises
------
AssertionError
"""
slug_copy = str(slug).lower().strip()
assert_is(isinstance(slug_copy, str), "slug must be a string")
assert_is(len(slug_copy) > 0, "slug must not be empty")

VALID_SLUG_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
assert_is(all(c in VALID_SLUG_CHARS for c in slug_copy), "slug must only contain valid characters")
60 changes: 58 additions & 2 deletions darwin/future/tests/meta/objects/test_datasetmeta.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import string
from unittest.mock import Mock, patch

from pytest import fixture, raises
from pytest import fixture, mark, raises
from responses import RequestsMock

from darwin.future.core.client import DarwinConfig
Expand All @@ -27,8 +28,48 @@ def _delete_by_id_mock(): # type: ignore
# `get_dataset_by_id` tests
# TODO get_dataset_by_id tests


# `create_dataset` tests
# TODO create_dataset tests
def test_create_dataset_returns_exceptions_thrown(base_config: DarwinConfig) -> None:
valid_client = MetaClient(base_config)
valid_slug = "test_dataset"

base_url = base_config.base_url + "api/datasets"

with RequestsMock() as rsps:
rsps.add(rsps.POST, base_url, status=500)
dataset_meta = DatasetMeta(valid_client)

exceptions, dataset_created = dataset_meta.create_dataset(valid_slug)

assert exceptions is not None
assert "500 Server Error" in str(exceptions[0])
assert dataset_created is None


def test_create_dataset_returns_dataset_created_if_dataset_created(base_config: DarwinConfig) -> None:
valid_client = MetaClient(base_config)
valid_slug = "test_dataset"

base_url = base_config.base_url + "api/datasets"

with RequestsMock() as rsps:
rsps.add(
rsps.POST,
base_url,
json={"id": 1, "name": "Test Dataset", "slug": "test_dataset"},
status=201,
)
dataset_meta = DatasetMeta(valid_client)

exceptions, dataset_created = dataset_meta.create_dataset(valid_slug)

assert exceptions is None
assert dataset_created is not None
assert dataset_created.id == 1
assert dataset_created.name == "test dataset"
assert dataset_created.slug == "test_dataset"


# `update_dataset` tests
# TODO update_dataset tests
Expand Down Expand Up @@ -147,3 +188,18 @@ def test_delete_by_id_returns_dataset_deleted_if_dataset_found(base_config: Darw
dataset_deleted = DatasetMeta._delete_by_id(valid_client, valid_id)

assert dataset_deleted == 1


@mark.parametrize(
"invalid_slug",
["", " ", "test dataset", *[f"dataset_{c}" for c in string.punctuation if c not in ["-", "_", "."]]],
)
def test_validate_slugh_raises_exception_if_passed_invalid_inputs(invalid_slug: str) -> None:
with raises(AssertionError):
DatasetMeta._validate_slug(invalid_slug)


def test_validate_slug_returns_none_if_passed_valid_slug() -> None:
valid_slug = "test-dataset"

assert DatasetMeta._validate_slug(valid_slug) is None