Skip to content

Commit

Permalink
Merge branch 'dev' into fix/dataset_assets_contributor_uploader
Browse files Browse the repository at this point in the history
  • Loading branch information
tcp authored Oct 5, 2023
2 parents 8a72919 + a431832 commit a16a247
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 6 deletions.
2 changes: 1 addition & 1 deletion packages/syft/src/syft/client/domain_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def add_default_uploader(
name=user.name,
email=user.email,
)
obj.contributors.append(uploader)
obj.contributors.add(uploader)
obj.uploader = uploader
return obj

Expand Down
45 changes: 40 additions & 5 deletions packages/syft/src/syft/service/dataset/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Dict
from typing import List
from typing import Optional
from typing import Set
from typing import Tuple
from typing import Union

Expand Down Expand Up @@ -89,6 +90,16 @@ def _repr_html_(self) -> Any:
</div>
"""

def __eq__(self, value: object) -> bool:
if not isinstance(value, Contributor):
return False

# We assoctiate two contributors as equal if they have the same email
return self.email == value.email

def __hash__(self) -> int:
return hash(self.email)


@serializable()
class MarkdownDescription(SyftObject):
Expand Down Expand Up @@ -125,7 +136,7 @@ class Asset(SyftObject):
node_uid: UID
name: str
description: Optional[MarkdownDescription] = None
contributors: List[Contributor] = []
contributors: Set[Contributor] = set()
data_subjects: List[DataSubject] = []
mock_is_real: bool = False
shape: Optional[Tuple]
Expand Down Expand Up @@ -214,6 +225,21 @@ def _repr_markdown_(self) -> str:
_repr_str += f"\t{contributor.name}: {contributor.email}\n"
return as_markdown_python_code(_repr_str)

def __eq__(self, other: object) -> bool:
if not isinstance(other, Asset):
return False
return (
self.action_id == other.action_id
and self.name == other.name
and self.contributors == other.contributors
and self.shape == other.shape
and self.description == other.description
and self.data_subjects == other.data_subjects
and self.mock_is_real == other.mock_is_real
and self.uploader == other.uploader
and self.created_at == other.created_at
)

@property
def pointer(self) -> Any:
# relative
Expand Down Expand Up @@ -295,7 +321,7 @@ class CreateAsset(SyftObject):
id: Optional[UID] = None
name: str
description: Optional[MarkdownDescription] = None
contributors: List[Contributor] = []
contributors: Set[Contributor] = set()
data_subjects: List[DataSubjectCreate] = []
node_uid: Optional[UID]
action_id: Optional[UID]
Expand Down Expand Up @@ -348,7 +374,12 @@ def add_contributor(
contributor = Contributor(
name=name, role=_role_str, email=email, phone=phone, note=note
)
self.contributors.append(contributor)
if contributor in self.contributors:
return SyftError(
message=f"Contributor with email: '{email}' already exists in '{self.name}' Asset."
)
self.contributors.add(contributor)

return SyftSuccess(
message=f"Contributor '{name}' added to '{self.name}' Asset."
)
Expand Down Expand Up @@ -429,7 +460,7 @@ class Dataset(SyftObject):
name: str
node_uid: Optional[UID]
asset_list: List[Asset] = []
contributors: List[Contributor] = []
contributors: Set[Contributor] = set()
citation: Optional[str]
url: Optional[str]
description: Optional[MarkdownDescription] = None
Expand Down Expand Up @@ -635,7 +666,11 @@ def add_contributor(
contributor = Contributor(
name=name, role=_role_str, email=email, phone=phone, note=note
)
self.contributors.append(contributor)
if contributor in self.contributors:
return SyftError(
message=f"Contributor with email: '{email}' already exists in '{self.name}' Dataset."
)
self.contributors.add(contributor)
return SyftSuccess(
message=f"Contributor '{name}' added to '{self.name}' Dataset."
)
Expand Down
3 changes: 3 additions & 0 deletions packages/syft/src/syft/types/syft_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,8 @@ def list_dict_repr_html(self) -> str:
extra_fields = []
if isinstance(self, dict):
values = list(self.values())
elif isinstance(self, set):
values = list(self)
else:
values = self

Expand Down Expand Up @@ -625,6 +627,7 @@ def list_dict_repr_html(self) -> str:
# give lists and dicts a _repr_html_ if they contain SyftObject's
aggressive_set_attr(type([]), "_repr_html_", list_dict_repr_html)
aggressive_set_attr(type({}), "_repr_html_", list_dict_repr_html)
aggressive_set_attr(type(set()), "_repr_html_", list_dict_repr_html)


class StorableObjectType:
Expand Down
35 changes: 35 additions & 0 deletions packages/syft/tests/syft/service/dataset/dataset_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
import pytest

# syft absolute
import syft as sy
from syft.node.worker import Worker
from syft.service.action.action_object import ActionObject
from syft.service.dataset.dataset import CreateAsset as Asset
from syft.service.dataset.dataset import CreateDataset as Dataset
from syft.service.dataset.dataset import _ASSET_WITH_NONE_MOCK_ERROR_MESSAGE
from syft.service.response import SyftError
from syft.service.response import SyftSuccess
from syft.types.twin_object import TwinMode


Expand Down Expand Up @@ -216,3 +219,35 @@ def test_domain_client_cannot_upload_dataset_with_non_mock(worker: Worker) -> No
root_domain_client.upload_dataset(dataset)

assert _ASSET_WITH_NONE_MOCK_ERROR_MESSAGE in str(excinfo.value)


def test_adding_contributors_with_duplicate_email():
# Datasets

dataset = Dataset(name="Sample dataset")
res1 = dataset.add_contributor(
role=sy.roles.UPLOADER, name="Alice", email="[email protected]"
)
res2 = dataset.add_contributor(
role=sy.roles.UPLOADER, name="Alice Smith", email="[email protected]"
)

assert isinstance(res1, SyftSuccess)
assert isinstance(res2, SyftError)
assert len(dataset.contributors) == 1

# Assets
asset = Asset(**make_asset_without_mock(), mock=ActionObject.empty())

res3 = asset.add_contributor(
role=sy.roles.UPLOADER, name="Bob", email="[email protected]"
)

res4 = asset.add_contributor(
role=sy.roles.UPLOADER, name="Bob Abraham", email="[email protected]"
)
dataset.add_asset(asset)

assert isinstance(res3, SyftSuccess)
assert isinstance(res4, SyftError)
assert len(asset.contributors) == 1

0 comments on commit a16a247

Please sign in to comment.