From 67d9503fcdb9ef3e5a9773ca85fa5c6b045f6285 Mon Sep 17 00:00:00 2001 From: dk Date: Tue, 2 Jul 2024 10:09:31 +0700 Subject: [PATCH 001/117] [syft/action_obj] - also delete the corresponding blob entry for an action object - refactor `BlobStorageService.delete` - add placeholder for test cases --- .../src/syft/service/action/action_service.py | 21 ++++++++- .../src/syft/service/blob_storage/service.py | 46 +++++++++++-------- .../syft/service/action/action_object_test.py | 14 ++++++ 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index da273e2c12b..076d42529c3 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -855,10 +855,27 @@ def exists( def delete( self, context: AuthedServiceContext, uid: UID ) -> SyftSuccess | SyftError: - res = self.store.delete(context.credentials, uid) + # delete object's blob storage entry + get_res = self.store.get(uid=uid, credentials=context.credentials) + if get_res.is_err(): + return SyftError(message=get_res.err()) + action_obj: ActionObject = get_res.ok() + if action_obj.syft_blob_storage_entry_id: + blob_store_service = context.node.get_service("BlobStorageService") + blob_del_res = blob_store_service.delete( + context=context, uid=action_obj.syft_blob_storage_entry_id + ) + if isinstance(blob_del_res, SyftError): + return SyftError(message=blob_del_res.message) + return_msg: list = [blob_del_res.message] + # delete from the action store + res = self.store.delete(credentials=context.credentials, uid=uid) if res.is_err(): return SyftError(message=res.err()) - return SyftSuccess(message="Great Success!") + space_14: str = 14 * " " # used to make the SyftSuccess message look nice + return_msg.append(f"{space_14}Action object with uid '{uid}' deleted.") + + return SyftSuccess(message="\n".join(return_msg)) def resolve_action_args( diff --git a/packages/syft/src/syft/service/blob_storage/service.py b/packages/syft/src/syft/service/blob_storage/service.py index 12a9cc9f8c2..6e044fb3be5 100644 --- a/packages/syft/src/syft/service/blob_storage/service.py +++ b/packages/syft/src/syft/service/blob_storage/service.py @@ -309,30 +309,36 @@ def mark_write_complete( def delete( self, context: AuthedServiceContext, uid: UID ) -> SyftSuccess | SyftError: - result = self.stash.get_by_uid(context.credentials, uid=uid) - if result.is_ok(): - obj = result.ok() + get_res = self.stash.get_by_uid(context.credentials, uid=uid) + if get_res.is_err(): + return SyftError(message=get_res.err()) - if obj is None: - return SyftError( - message=f"No blob storage entry exists for uid: {uid}, or you have no permissions to read it" - ) - - try: - with context.node.blob_storage_client.connect() as conn: - file_unlinked_result = conn.delete(obj.location) - except Exception as e: - return SyftError(message=f"Failed to delete file: {e}") + obj = get_res.ok() + if obj is None: + return SyftError( + message=f"No blob storage entry exists for uid: {uid}, " + f"or you have no permissions to read it" + ) - if isinstance(file_unlinked_result, SyftError): - return file_unlinked_result - blob_storage_entry_deleted = self.stash.delete( - context.credentials, UIDPartitionKey.with_obj(uid), has_permission=True + try: + with context.node.blob_storage_client.connect() as conn: + file_unlinked_result = conn.delete(obj.location) + if isinstance(file_unlinked_result, SyftError): + return file_unlinked_result + except Exception as e: + return SyftError( + message=f"Failed to delete blob file with id '{uid}'. Error: {e}" ) - if blob_storage_entry_deleted.is_ok(): - return file_unlinked_result - return SyftError(message=result.err()) + blob_entry_delete_res = self.stash.delete( + context.credentials, UIDPartitionKey.with_obj(uid), has_permission=True + ) + if blob_entry_delete_res.is_err(): + return SyftError(message=blob_entry_delete_res.err()) + + return SyftSuccess( + message=f"Blob storage entry with id '{uid}' deleted successfully." + ) TYPE_TO_SERVICE[BlobStorageEntry] = BlobStorageEntry diff --git a/packages/syft/tests/syft/service/action/action_object_test.py b/packages/syft/tests/syft/service/action/action_object_test.py index dd7351f78e4..a2ca8449d1b 100644 --- a/packages/syft/tests/syft/service/action/action_object_test.py +++ b/packages/syft/tests/syft/service/action/action_object_test.py @@ -1023,3 +1023,17 @@ def test_actionobject_syft_getattr_pandas(worker): obj.columns = ["a", "b", "c"] assert (obj.columns == ["a", "b", "c"]).all() + + +def test_actionobject_delete(): + """ + Test deleting a small action object that does not have its blob file + """ + pass + + +def test_actionobject_blob_entry_delete(): + """ + Test deleting a big action object that has its blob file + """ + pass From cc4665ddd99102fc509d487a38bfb576e8889bd3 Mon Sep 17 00:00:00 2001 From: dk Date: Tue, 2 Jul 2024 11:04:45 +0700 Subject: [PATCH 002/117] [syft/unit-tests] add tests for deleting action objects --- .../src/syft/service/action/action_service.py | 6 +-- .../syft/service/action/action_object_test.py | 39 ++++++++++++++----- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index 076d42529c3..eb359791e2c 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -856,6 +856,7 @@ def delete( self, context: AuthedServiceContext, uid: UID ) -> SyftSuccess | SyftError: # delete object's blob storage entry + return_msg = [] get_res = self.store.get(uid=uid, credentials=context.credentials) if get_res.is_err(): return SyftError(message=get_res.err()) @@ -867,13 +868,12 @@ def delete( ) if isinstance(blob_del_res, SyftError): return SyftError(message=blob_del_res.message) - return_msg: list = [blob_del_res.message] + return_msg.append(blob_del_res.message) # delete from the action store res = self.store.delete(credentials=context.credentials, uid=uid) if res.is_err(): return SyftError(message=res.err()) - space_14: str = 14 * " " # used to make the SyftSuccess message look nice - return_msg.append(f"{space_14}Action object with uid '{uid}' deleted.") + return_msg.append(f"Action object with uid '{uid}' deleted.") return SyftSuccess(message="\n".join(return_msg)) diff --git a/packages/syft/tests/syft/service/action/action_object_test.py b/packages/syft/tests/syft/service/action/action_object_test.py index a2ca8449d1b..0af5ebe4c19 100644 --- a/packages/syft/tests/syft/service/action/action_object_test.py +++ b/packages/syft/tests/syft/service/action/action_object_test.py @@ -23,6 +23,9 @@ from syft.service.action.action_object import propagate_node_uid from syft.service.action.action_object import send_action_side_effect from syft.service.action.action_types import action_type_for_type +from syft.service.response import SyftError +from syft.service.response import SyftSuccess +from syft.store.blob_storage import SyftObjectRetrieval from syft.types.uid import LineageID from syft.types.uid import UID @@ -1025,15 +1028,33 @@ def test_actionobject_syft_getattr_pandas(worker): assert (obj.columns == ["a", "b", "c"]).all() -def test_actionobject_delete(): +def test_actionobject_delete(worker): """ - Test deleting a small action object that does not have its blob file + Test deleting action objects and their corresponding blob storage entries """ - pass - + root_domain_client = worker.root_client -def test_actionobject_blob_entry_delete(): - """ - Test deleting a big action object that has its blob file - """ - pass + # small object with no blob store entry + data_small = np.random.randint(0, 100, size=3) + action_obj = ActionObject.from_obj(data_small) + action_obj.send(root_domain_client) + assert action_obj.syft_blob_storage_entry_id is None + del_res = root_domain_client.api.services.action.delete(uid=action_obj.id) + assert isinstance(del_res, SyftSuccess) + + # big object with blob store entry + num_elements = 25 * 1024 * 1024 + data_big = np.random.randint(0, 100, size=num_elements) # 4 bytes per int32 + action_obj_2 = ActionObject.from_obj(data_big) + action_obj_2.send(root_domain_client) + assert isinstance(action_obj_2.syft_blob_storage_entry_id, UID) + read_res = root_domain_client.api.services.blob_storage.read( + action_obj_2.syft_blob_storage_entry_id + ) + assert isinstance(read_res, SyftObjectRetrieval) + del_res = root_domain_client.api.services.action.delete(uid=action_obj_2.id) + assert isinstance(del_res, SyftSuccess) + read_res = root_domain_client.api.services.blob_storage.read( + action_obj_2.syft_blob_storage_entry_id + ) + assert isinstance(read_res, SyftError) From 4859671574d72e393abe3b41da08a0553927ddf6 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 2 Jul 2024 09:38:24 +0200 Subject: [PATCH 003/117] add cannonicalname and version --- packages/syft/src/syft/serde/array.py | 37 +++++- packages/syft/src/syft/serde/recursive.py | 39 +++++-- .../src/syft/serde/recursive_primitives.py | 109 ++++++++++++++---- packages/syft/src/syft/serde/signature.py | 22 +++- packages/syft/src/syft/serde/third_party.py | 69 +++++++++-- .../syft/src/syft/service/policy/policy.py | 2 +- packages/syft/src/syft/types/syft_object.py | 4 +- 7 files changed, 235 insertions(+), 47 deletions(-) diff --git a/packages/syft/src/syft/serde/array.py b/packages/syft/src/syft/serde/array.py index 56158225857..fa1ed27e74b 100644 --- a/packages/syft/src/syft/serde/array.py +++ b/packages/syft/src/syft/serde/array.py @@ -3,6 +3,7 @@ from numpy import frombuffer # relative +from ..types.syft_object import SYFT_OBJECT_VERSION_1 from .arrow import numpy_deserialize from .arrow import numpy_serialize from .recursive import recursive_serde_register @@ -34,11 +35,17 @@ } recursive_serde_register( - np.ndarray, serialize=numpy_serialize, deserialize=numpy_deserialize + np.ndarray, + serialize=numpy_serialize, + deserialize=numpy_deserialize, + canonical_name="numpy_ndarray", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np._globals._NoValueType, + canonical_name="numpy_no_value", + version=SYFT_OBJECT_VERSION_1, ) # serialize=numpy_serialize, deserialize=numpy_deserialize @@ -47,84 +54,112 @@ np.bool_, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.bool_)[0], + canonical_name="numpy_bool", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.int8, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.int8)[0], + canonical_name="numpy_int8", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.int16, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.int16)[0], + canonical_name="numpy_int16", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.int32, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.int32)[0], + canonical_name="numpy_int32", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.int64, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.int64)[0], + canonical_name="numpy_int64", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.uint8, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.uint8)[0], + canonical_name="numpy_uint8", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.uint16, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.uint16)[0], + canonical_name="numpy_uint16", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.uint32, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.uint32)[0], + canonical_name="numpy_uint32", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.uint64, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.uint64)[0], + canonical_name="numpy_uint64", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.single, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.single)[0], + canonical_name="numpy_single", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.double, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.double)[0], + canonical_name="numpy_double", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.float16, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.float16)[0], + canonical_name="numpy_float16", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.float32, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.float32)[0], + canonical_name="numpy_float32", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( np.float64, serialize=lambda x: x.tobytes(), deserialize=lambda buffer: frombuffer(buffer, dtype=np.float64)[0], + canonical_name="numpy_float64", + version=SYFT_OBJECT_VERSION_1, ) # TODO: There is an incorrect mapping in looping,which makes it not work. diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index 0afb967ba3e..6581a808a77 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -78,6 +78,33 @@ def check_fqn_alias(cls: object | type) -> tuple | None: return None +def validate_cannonical_name_version( + cls: type, cannonical_name: str | None, version: int | None +) -> tuple[str, int]: + cls_canonical_name = getattr(cls, "__canonical_name__", None) + cls_version = getattr(cls, "__version__", None) + if cls_canonical_name and cannonical_name: + raise ValueError( + "Cannot specify both __canonical_name__ attribute and cannonical_name argument." + ) + if cls_version and version: + raise ValueError( + "Cannot specify both __version__ attribute and version argument." + ) + if cls_canonical_name is None and cannonical_name is None: + raise ValueError( + "Must specify either __canonical_name__ attribute or cannonical_name argument." + ) + if cls_version is None and version is None: + raise ValueError( + "Must specify either __version__ attribute or version argument." + ) + + cannonical_name = cannonical_name or cls_canonical_name + version = version or cls_version + return cannonical_name, version # type: ignore + + def recursive_serde_register( cls: object | type, serialize: Callable | None = None, @@ -86,6 +113,8 @@ def recursive_serde_register( exclude_attrs: list | None = None, inherit_attrs: bool | None = True, inheritable_attrs: bool | None = True, + canonical_name: str | None = None, + version: int | None = None, ) -> None: pydantic_fields = None base_attrs = None @@ -94,6 +123,9 @@ def recursive_serde_register( alias_fqn = check_fqn_alias(cls) cls = type(cls) if not isinstance(cls, type) else cls fqn = f"{cls.__module__}.{cls.__name__}" + canonical_name, version = validate_cannonical_name_version( + cls, canonical_name, version + ) nonrecursive = bool(serialize and deserialize) _serialize = serialize if nonrecursive else rs_object2proto @@ -158,13 +190,6 @@ def recursive_serde_register( ) TYPE_BANK[fqn] = serde_attributes - if hasattr(cls, "__canonical_name__"): - canonical_name = cls.__canonical_name__ - version = cls.__version__ - else: - # TODO: refactor - canonical_name = fqn - version = 1 SyftObjectRegistry.register_cls(canonical_name, version, serde_attributes) diff --git a/packages/syft/src/syft/serde/recursive_primitives.py b/packages/syft/src/syft/serde/recursive_primitives.py index cb90932247a..c0b52825859 100644 --- a/packages/syft/src/syft/serde/recursive_primitives.py +++ b/packages/syft/src/syft/serde/recursive_primitives.py @@ -27,6 +27,7 @@ import weakref # relative +from ..types.syft_object import SYFT_OBJECT_VERSION_1 from .capnp import get_capnp_schema from .recursive import chunk_bytes from .recursive import combine_bytes @@ -209,111 +210,163 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: int, serialize=lambda x: x.to_bytes((x.bit_length() + 7) // 8 + 1, "big", signed=True), deserialize=lambda x_bytes: int.from_bytes(x_bytes, "big", signed=True), + canonical_name="int", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( float, serialize=lambda x: x.hex().encode(), deserialize=lambda x: float.fromhex(x.decode()), + canonical_name="float", + version=SYFT_OBJECT_VERSION_1, ) -recursive_serde_register(bytes, serialize=lambda x: x, deserialize=lambda x: x) +recursive_serde_register( + bytes, + serialize=lambda x: x, + deserialize=lambda x: x, + canonical_name="bytes", + version=SYFT_OBJECT_VERSION_1, +) recursive_serde_register( - str, serialize=lambda x: x.encode(), deserialize=lambda x: x.decode() + str, + serialize=lambda x: x.encode(), + deserialize=lambda x: x.decode(), + canonical_name="str", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( list, serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, list), + canonical_name="list", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( tuple, serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, tuple), + canonical_name="tuple", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( - dict, serialize=serialize_kv, deserialize=functools.partial(deserialize_kv, dict) + dict, + serialize=serialize_kv, + deserialize=functools.partial(deserialize_kv, dict), + canonical_name="dict", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( defaultdict, serialize=serialize_defaultdict, deserialize=deserialize_defaultdict, + canonical_name="defaultdict", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( OrderedDict, serialize=serialize_kv, deserialize=functools.partial(deserialize_kv, OrderedDict), + canonical_name="OrderedDict", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( - type(None), serialize=lambda _: b"1", deserialize=lambda _: None + type(None), + serialize=lambda _: b"1", + deserialize=lambda _: None, + canonical_name="NoneType", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( bool, serialize=lambda x: b"1" if x else b"0", deserialize=lambda x: False if x == b"0" else True, + canonical_name="bool", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( set, serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, set), + canonical_name="set", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( weakref.WeakSet, serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, weakref.WeakSet), + canonical_name="WeakSet", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( frozenset, serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, frozenset), + canonical_name="frozenset", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( complex, serialize=lambda x: serialize_iterable((x.real, x.imag)), deserialize=lambda x: complex(*deserialize_iterable(tuple, x)), + canonical_name="complex", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( range, serialize=lambda x: serialize_iterable((x.start, x.stop, x.step)), deserialize=lambda x: range(*deserialize_iterable(tuple, x)), + canonical_name="range", + version=SYFT_OBJECT_VERSION_1, ) - recursive_serde_register( slice, serialize=lambda x: serialize_iterable((x.start, x.stop, x.step)), deserialize=lambda x: slice(*deserialize_iterable(tuple, x)), + canonical_name="slice", + version=SYFT_OBJECT_VERSION_1, ) recursive_serde_register( - slice, - serialize=lambda x: serialize_iterable((x.start, x.stop, x.step)), - deserialize=lambda x: slice(*deserialize_iterable(tuple, x)), + type, + serialize=serialize_type, + deserialize=deserialize_type, + canonical_name="type", + version=SYFT_OBJECT_VERSION_1, ) -recursive_serde_register(type, serialize=serialize_type, deserialize=deserialize_type) recursive_serde_register( MappingProxyType, serialize=serialize_kv, deserialize=functools.partial(deserialize_kv, MappingProxyType), + canonical_name="MappingProxyType", + version=SYFT_OBJECT_VERSION_1, ) +recursive_serde_register( + PurePath, + serialize=serialize_path, + deserialize=functools.partial(deserialize_path, PurePath), + canonical_name="PurePath", + version=SYFT_OBJECT_VERSION_1, +) for __path_type in ( - PurePath, pathlib.PurePosixPath, pathlib.PureWindowsPath, pathlib.Path, @@ -324,6 +377,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: __path_type, serialize=serialize_path, deserialize=functools.partial(deserialize_path, __path_type), + canonical_name=f"pathlib_{__path_type.__name__}", ) @@ -373,7 +427,12 @@ def deserialize_generic_alias(type_blob: bytes) -> type: # 🟡 TODO 5: add tests and all typing options for signatures -def recursive_serde_register_type(t: type, serialize_attrs: list | None = None) -> None: +def recursive_serde_register_type( + t: type, + serialize_attrs: list | None = None, + canonical_name: str | None = None, + version: int | None = None, +) -> None: if (isinstance(t, type) and issubclass(t, _GenericAlias)) or issubclass( type(t), _GenericAlias ): @@ -382,6 +441,8 @@ def recursive_serde_register_type(t: type, serialize_attrs: list | None = None) serialize=serialize_generic_alias, deserialize=deserialize_generic_alias, serialize_attrs=serialize_attrs, + canonical_name=canonical_name, + version=version, ) else: recursive_serde_register( @@ -389,6 +450,8 @@ def recursive_serde_register_type(t: type, serialize_attrs: list | None = None) serialize=serialize_type, deserialize=deserialize_type, serialize_attrs=serialize_attrs, + canonical_name=canonical_name, + version=version, ) @@ -411,12 +474,14 @@ def deserialize_union_type(type_blob: bytes) -> type: UnionType, serialize=serialize_union_type, deserialize=deserialize_union_type, + canonical_name="UnionType", + version=SYFT_OBJECT_VERSION_1, ) -recursive_serde_register_type(_SpecialForm) -recursive_serde_register_type(_GenericAlias) -recursive_serde_register_type(Union) -recursive_serde_register_type(TypeVar) +recursive_serde_register_type(_SpecialForm, canonical_name="_SpecialForm", version=1) +recursive_serde_register_type(_GenericAlias, canonical_name="_GenericAlias", version=1) +recursive_serde_register_type(Union, canonical_name="Union", version=1) +recursive_serde_register_type(TypeVar, canonical_name="TypeVar", version=1) recursive_serde_register_type( _UnionGenericAlias, @@ -429,11 +494,15 @@ def deserialize_union_type(type_blob: bytes) -> type: "__module__", "__origin__", ], + canonical_name="_UnionGenericAlias", + version=1, +) +recursive_serde_register_type( + _SpecialGenericAlias, canonical_name="_SpecialGenericAlias", version=1 ) -recursive_serde_register_type(_SpecialGenericAlias) -recursive_serde_register_type(GenericAlias) +recursive_serde_register_type(GenericAlias, canonical_name="GenericAlias", version=1) -recursive_serde_register_type(Any) -recursive_serde_register_type(EnumMeta) +recursive_serde_register_type(Any, canonical_name="Any", version=1) +recursive_serde_register_type(EnumMeta, canonical_name="EnumMeta", version=1) -recursive_serde_register_type(ABCMeta) +recursive_serde_register_type(ABCMeta, canonical_name="ABCMeta", version=1) diff --git a/packages/syft/src/syft/serde/signature.py b/packages/syft/src/syft/serde/signature.py index 865a4f142e3..23b0a556fca 100644 --- a/packages/syft/src/syft/serde/signature.py +++ b/packages/syft/src/syft/serde/signature.py @@ -12,11 +12,18 @@ from .recursive import recursive_serde_register from .serialize import _serialize -recursive_serde_register(_ParameterKind) +recursive_serde_register( + _ParameterKind, + canonical_name="inspect_ParameterKind", + version=1, +) recursive_serde_register( - Parameter, serialize_attrs=["_annotation", "_name", "_kind", "_default"] + Parameter, + serialize_attrs=["_annotation", "_name", "_kind", "_default"], + canonical_name="inspect_Parameter", + version=1, ) @@ -42,9 +49,6 @@ # return Parameter(**obj_dict) -# recursive_serde_register(Parameter, serialize_parameter, deserialize_parameter) - - def serialize_signature(obj: Signature) -> bytes: parameters = list(dict(obj.parameters).values()) return_annotation = obj.return_annotation @@ -57,7 +61,13 @@ def deserialize_signature(blob: bytes) -> Signature: return Signature(**obj_dict) -recursive_serde_register(Signature, serialize_signature, deserialize_signature) +recursive_serde_register( + Signature, + serialize_signature, + deserialize_signature, + canonical_name="inspect_Signature", + version=1, +) def signature_remove_self(signature: Signature) -> Signature: diff --git a/packages/syft/src/syft/serde/third_party.py b/packages/syft/src/syft/serde/third_party.py index 4e94219951e..5eeee33ceba 100644 --- a/packages/syft/src/syft/serde/third_party.py +++ b/packages/syft/src/syft/serde/third_party.py @@ -43,25 +43,37 @@ SigningKey, serialize=lambda x: bytes(x), deserialize=lambda x: SigningKey(x), + canonical_name="nacl_signing_key", + version=1, ) recursive_serde_register( VerifyKey, serialize=lambda x: bytes(x), deserialize=lambda x: VerifyKey(x), + canonical_name="nacl_verify_key", + version=1, ) # result Ok and Err -recursive_serde_register(Ok, serialize_attrs=["_value"]) -recursive_serde_register(Err, serialize_attrs=["_value"]) -recursive_serde_register(Result) +recursive_serde_register( + Ok, serialize_attrs=["_value"], canonical_name="result_Ok", version=1 +) +recursive_serde_register( + Err, serialize_attrs=["_value"], canonical_name="result_Err", version=1 +) +recursive_serde_register( + Result, serialize_attrs=["_value"], canonical_name="result_Result", version=1 +) # exceptions -recursive_serde_register(cls=TypeError) +recursive_serde_register(cls=TypeError, canonical_name="TypeError", version=1) # mongo collection -recursive_serde_register_type(Collection) +recursive_serde_register_type( + Collection, canonical_name="pymongo_collection", version=1 +) def serialize_dataframe(df: DataFrame) -> bytes: @@ -91,6 +103,8 @@ def deserialize_dataframe(buf: bytes) -> DataFrame: DataFrame, serialize=serialize_dataframe, deserialize=deserialize_dataframe, + canonical_name="pandas_dataframe", + version=1, ) @@ -103,30 +117,38 @@ def deserialize_series(blob: bytes) -> Series: Series, serialize=lambda x: serialize(DataFrame(x).to_dict(), to_bytes=True), deserialize=deserialize_series, + canonical_name="pandas_series", + version=1, ) recursive_serde_register( datetime, serialize=lambda x: serialize(x.isoformat(), to_bytes=True), deserialize=lambda x: parser.isoparse(deserialize(x, from_bytes=True)), + canonical_name="datetime_datetime", + version=1, ) recursive_serde_register( time, serialize=lambda x: serialize(x.isoformat(), to_bytes=True), deserialize=lambda x: parser.parse(deserialize(x, from_bytes=True)).time(), + canonical_name="datetime_time", + version=1, ) recursive_serde_register( date, serialize=lambda x: serialize(x.isoformat(), to_bytes=True), deserialize=lambda x: parser.parse(deserialize(x, from_bytes=True)).date(), + canonical_name="datetime_date", ) recursive_serde_register( Timestamp, serialize=lambda x: serialize(x.value, to_bytes=True), deserialize=lambda x: Timestamp(deserialize(x, from_bytes=True)), + canonical_name="pandas_timestamp", ) @@ -138,11 +160,13 @@ def _serialize_dicttuple(x: DictTuple) -> bytes: _DictTupleMetaClass, serialize=serialize_type, deserialize=deserialize_type, + canonical_name="dicttuple_meta", ) recursive_serde_register( DictTuple, serialize=_serialize_dicttuple, deserialize=functools.partial(deserialize_kv, DictTuple), + canonical_name="dicttuple", ) @@ -150,11 +174,16 @@ def _serialize_dicttuple(x: DictTuple) -> bytes: EmptyType, serialize=serialize_type, deserialize=deserialize_type, + canonical_name="empty_type", ) -recursive_serde_register_type(ModelMetaclass) -recursive_serde_register_type(PartialModelMetaclass) +recursive_serde_register_type( + ModelMetaclass, canonical_name="pydantic_model_metaclass", version=1 +) +recursive_serde_register_type( + PartialModelMetaclass, canonical_name="partial_model_metaclass", version=1 +) def serialize_bytes_io(io: BytesIO) -> bytes: @@ -166,13 +195,15 @@ def serialize_bytes_io(io: BytesIO) -> bytes: BytesIO, serialize=serialize_bytes_io, deserialize=lambda x: BytesIO(deserialize(x, from_bytes=True)), + canonical_name="bytes_io", + version=1, ) try: # third party from IPython.display import Image - recursive_serde_register(Image) + recursive_serde_register(Image, canonical_name="IPython_display_Image", version=1) except Exception: # nosec pass @@ -196,6 +227,8 @@ def deserialize_torch_tensor_meta(buf: bytes) -> _TensorMeta: _TensorMeta, serialize=serialize_torch_tensor_meta, deserialize=deserialize_torch_tensor_meta, + canonical_name="torch_tensor_meta", + version=1, ) def torch_serialize(tensor: torch.Tensor) -> bytes: @@ -209,18 +242,26 @@ def torch_deserialize(buffer: bytes) -> torch.tensor: torch.Tensor, serialize=torch_serialize, deserialize=lambda data: torch_deserialize(data), + canonical_name="torch_tensor", + version=1, ) -except Exception: # nosec +except ImportError: # nosec pass # unsure why we have to register the object not the type but this works -recursive_serde_register(np.core._ufunc_config._unspecified()) +recursive_serde_register( + np.core._ufunc_config._unspecified(), + canonical_name="numpy_ufunc_unspecified", + version=1, +) recursive_serde_register( pydantic.EmailStr, serialize=lambda x: x.encode(), deserialize=lambda x: pydantic.EmailStr(x.decode()), + canonical_name="pydantic_emailstr", + version=1, ) @@ -246,13 +287,19 @@ def convert_from_dataframe(blob: bytes) -> DataFrame: return dataframe recursive_serde_register( - RowIterator, serialize=convert_to_dataframe, deserialize=convert_from_dataframe + RowIterator, + serialize=convert_to_dataframe, + deserialize=convert_from_dataframe, + canonical_name="bigquery_rowiterator", + version=1, ) recursive_serde_register( QueryJob, serialize=lambda obj: convert_to_dataframe(obj.result()), deserialize=convert_from_dataframe, + canonical_name="bigquery_queryjob", + version=1, ) except ImportError: pass diff --git a/packages/syft/src/syft/service/policy/policy.py b/packages/syft/src/syft/service/policy/policy.py index c5fda8e0f3e..35f8c117cab 100644 --- a/packages/syft/src/syft/service/policy/policy.py +++ b/packages/syft/src/syft/service/policy/policy.py @@ -476,7 +476,7 @@ def __call__(cls, *args: Any, **kwargs: Any) -> None: return obj -recursive_serde_register_type(CustomPolicy) +recursive_serde_register_type(CustomPolicy, canonical_name="CustomPolicy", version=1) @serializable() diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 438b789dba6..614a794faf0 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -696,7 +696,9 @@ def __iter__(self) -> TupleGenerator: yield from ((k, v) for k, v in super().__iter__() if v is not Empty) -recursive_serde_register_type(PartialSyftObject) +recursive_serde_register_type( + PartialSyftObject, canonical_name="PartialSyftObject", version=1 +) def attach_attribute_to_syft_object(result: Any, attr_dict: dict[str, Any]) -> None: From b796964a732fd04ef751d4a4b45dbe29176162c1 Mon Sep 17 00:00:00 2001 From: dk Date: Tue, 2 Jul 2024 16:26:09 +0700 Subject: [PATCH 004/117] [syft/dataset_service] fix `unhashable type: 'list'` when deleting a dataset - add a test for deleting dataset --- .../syft/src/syft/service/dataset/dataset.py | 3 +-- .../syft/service/dataset/dataset_service.py | 2 +- .../syft/src/syft/store/kv_document_store.py | 10 ++++++--- .../service/dataset/dataset_service_test.py | 22 +++++++++++++++++++ 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index 2bd7dc33b90..3b6c14bcb62 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -499,8 +499,7 @@ def _repr_html_(self) -> Any: """ def action_ids(self) -> list[UID]: - data = [asset.action_id for asset in self.asset_list if asset.action_id] - return data + return [asset.action_id for asset in self.asset_list if asset.action_id] @property def assets(self) -> DictTuple[str, Asset]: diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index 451746fa15a..1c40ce1f060 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -205,7 +205,7 @@ def get_assets_by_action_id( def delete_dataset( self, context: AuthedServiceContext, uid: UID ) -> SyftSuccess | SyftError: - result = self.stash.delete_by_uid(context.credentials, uid) + result = self.stash.delete_by_uid(credentials=context.credentials, uid=uid) if result.is_ok(): return result.ok() else: diff --git a/packages/syft/src/syft/store/kv_document_store.py b/packages/syft/src/syft/store/kv_document_store.py index b594be92775..5bc85c81fd6 100644 --- a/packages/syft/src/syft/store/kv_document_store.py +++ b/packages/syft/src/syft/store/kv_document_store.py @@ -522,9 +522,13 @@ def _delete_unique_keys_for(self, obj: SyftObject) -> Result[SyftSuccess, str]: def _delete_search_keys_for(self, obj: SyftObject) -> Result[SyftSuccess, str]: for _search_ck in self.searchable_cks: - qk = _search_ck.with_obj(obj) - search_keys = self.searchable_keys[qk.key] - search_keys.pop(qk.value, None) + qk: QueryKey = _search_ck.with_obj(obj) + search_keys: defaultdict = self.searchable_keys[qk.key] + if isinstance(qk.value, list): + for qk_value in qk.value: + search_keys.pop(qk_value, None) + else: + search_keys.pop(qk.value, None) self.searchable_keys[qk.key] = search_keys return Ok(SyftSuccess(message="Deleted")) diff --git a/packages/syft/tests/syft/service/dataset/dataset_service_test.py b/packages/syft/tests/syft/service/dataset/dataset_service_test.py index 1aa85c07865..7b7597b1ef1 100644 --- a/packages/syft/tests/syft/service/dataset/dataset_service_test.py +++ b/packages/syft/tests/syft/service/dataset/dataset_service_test.py @@ -301,3 +301,25 @@ def test_upload_dataset_with_assets_of_different_data_types( assert type(root_domain_client.datasets[0].assets[0].mock) == type( different_data_types ) + + +def test_delete_datasets(worker: Worker) -> None: + root_domain_client = worker.root_client + mock = np.array([0, 1, 2, 3, 4]) + private = np.array([5, 6, 7, 8, 9]) + assets = [ + sy.Asset( + name="numpy-data", + mock=mock, + data=private, + shape=private.shape, + ) + ] + dataset = sy.Dataset( + name="my-dataset", description="This is a cool dataset", asset_list=assets + ) + upload_res = root_domain_client.upload_dataset(dataset) + assert isinstance(upload_res, SyftSuccess) + ds = root_domain_client.api.services.dataset.get_all()[0] + del_res = root_domain_client.api.services.dataset.delete_by_uid(uid=ds.id) + assert isinstance(del_res, SyftSuccess) From 8b9eb8473560e77f1a9c3a7f6daa402222f5b75a Mon Sep 17 00:00:00 2001 From: dk Date: Wed, 3 Jul 2024 10:43:59 +0700 Subject: [PATCH 005/117] [syft/dataset_service] delete assets of a dataset when deleting the dataset --- .../src/syft/service/action/action_service.py | 60 +++++++++++++++---- .../syft/service/dataset/dataset_service.py | 21 ++++++- .../service/dataset/dataset_service_test.py | 30 ++++++++-- 3 files changed, 93 insertions(+), 18 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index eb359791e2c..05069cce08b 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -855,27 +855,67 @@ def exists( def delete( self, context: AuthedServiceContext, uid: UID ) -> SyftSuccess | SyftError: - # delete object's blob storage entry - return_msg = [] get_res = self.store.get(uid=uid, credentials=context.credentials) if get_res.is_err(): return SyftError(message=get_res.err()) - action_obj: ActionObject = get_res.ok() - if action_obj.syft_blob_storage_entry_id: - blob_store_service = context.node.get_service("BlobStorageService") + obj: ActionObject | TwinObject = get_res.ok() + return_msg = [] + + # delete object's blob storage entry + blob_del_res = self._delete_blob_entry(context=context, obj=obj) + if isinstance(blob_del_res, SyftError): + return SyftError(message=blob_del_res.message) + return_msg.append(blob_del_res.message) + + # delete the object from the action store + store_del_res = self._delete_from_action_store(context=context, obj=obj) + if isinstance(store_del_res, SyftError): + return SyftError(message=store_del_res.message) + return_msg.append(store_del_res.message) + + return SyftSuccess(message="\n".join(return_msg)) + + def _delete_blob_entry( + self, + context: AuthedServiceContext, + obj: TwinObject | ActionObject, + ) -> SyftSuccess | SyftError: + return_msg = [] + blob_store_service = context.node.get_service("BlobStorageService") + if isinstance(obj, ActionObject) and obj.syft_blob_storage_entry_id: blob_del_res = blob_store_service.delete( - context=context, uid=action_obj.syft_blob_storage_entry_id + context=context, uid=obj.syft_blob_storage_entry_id ) if isinstance(blob_del_res, SyftError): return SyftError(message=blob_del_res.message) return_msg.append(blob_del_res.message) - # delete from the action store + if isinstance(obj, TwinObject): + if obj.private.syft_blob_storage_entry_id: + blob_del_res = blob_store_service.delete( + context=context, uid=obj.private.syft_blob_storage_entry_id + ) + if isinstance(blob_del_res, SyftError): + return SyftError(message=blob_del_res.message) + return_msg.append(blob_del_res.message) + if obj.mock.syft_blob_storage_entry_id: + blob_del_res = blob_store_service.delete( + context=context, uid=obj.mock.syft_blob_storage_entry_id + ) + if isinstance(blob_del_res, SyftError): + return SyftError(message=blob_del_res.message) + return_msg.append(blob_del_res.message) + return SyftSuccess(message="\n".join(return_msg)) + + def _delete_from_action_store( + self, + context: AuthedServiceContext, + obj: TwinObject | ActionObject, + ) -> SyftSuccess | SyftError: + uid = obj.id res = self.store.delete(credentials=context.credentials, uid=uid) if res.is_err(): return SyftError(message=res.err()) - return_msg.append(f"Action object with uid '{uid}' deleted.") - - return SyftSuccess(message="\n".join(return_msg)) + return SyftSuccess(message=f"Action object with uid '{uid}' deleted.") def resolve_action_args( diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index 1c40ce1f060..bbd50353bfe 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -205,11 +205,26 @@ def get_assets_by_action_id( def delete_dataset( self, context: AuthedServiceContext, uid: UID ) -> SyftSuccess | SyftError: + # check if the dataset exists + dataset = self.get_by_id(context=context, uid=uid) + if isinstance(dataset, SyftError): + return dataset + # delete the dataset's assets + return_msg = [] + for asset in dataset.asset_list: + action_service = context.node.get_service("ActionService") + del_res: SyftSuccess | SyftError = action_service.delete( + context=context, uid=asset.action_id + ) + if isinstance(del_res, SyftError): + return del_res + return_msg.append(f"Asset with id '{asset.id}' deleted.") + # delete the dataset object from the store result = self.stash.delete_by_uid(credentials=context.credentials, uid=uid) - if result.is_ok(): - return result.ok() - else: + if result.is_err(): return SyftError(message=result.err()) + return_msg.append(f"Dataset with id '{uid}' deleted.") + return SyftSuccess(message="\n".join(return_msg)) TYPE_TO_SERVICE[Dataset] = DatasetService diff --git a/packages/syft/tests/syft/service/dataset/dataset_service_test.py b/packages/syft/tests/syft/service/dataset/dataset_service_test.py index 7b7597b1ef1..1787aff4ab4 100644 --- a/packages/syft/tests/syft/service/dataset/dataset_service_test.py +++ b/packages/syft/tests/syft/service/dataset/dataset_service_test.py @@ -14,13 +14,13 @@ import syft as sy from syft.node.worker import Worker from syft.service.action.action_object import ActionObject +from syft.service.action.action_object import TwinMode 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 SyftException from syft.service.response import SyftSuccess -from syft.types.twin_object import TwinMode def random_hash() -> str: @@ -304,7 +304,7 @@ def test_upload_dataset_with_assets_of_different_data_types( def test_delete_datasets(worker: Worker) -> None: - root_domain_client = worker.root_client + root_client = worker.root_client mock = np.array([0, 1, 2, 3, 4]) private = np.array([5, 6, 7, 8, 9]) assets = [ @@ -318,8 +318,28 @@ def test_delete_datasets(worker: Worker) -> None: dataset = sy.Dataset( name="my-dataset", description="This is a cool dataset", asset_list=assets ) - upload_res = root_domain_client.upload_dataset(dataset) + upload_res = root_client.upload_dataset(dataset) assert isinstance(upload_res, SyftSuccess) - ds = root_domain_client.api.services.dataset.get_all()[0] - del_res = root_domain_client.api.services.dataset.delete_by_uid(uid=ds.id) + + dataset = root_client.api.services.dataset.get_all()[0] + asset = dataset.asset_list[0] + asset_mock = root_client.api.services.action.get( + uid=asset.action_id, twin_mode=sy.service.action.action_object.TwinMode.MOCK + ) + asset_private = root_client.api.services.action.get( + uid=asset.action_id, twin_mode=sy.service.action.action_object.TwinMode.PRIVATE + ) + assert isinstance(asset_mock, ActionObject) + assert isinstance(asset_private, ActionObject) + + # delete the dataset + del_res = root_client.api.services.dataset.delete_by_uid(uid=dataset.id) assert isinstance(del_res, SyftSuccess) + asset_mock = root_client.api.services.action.get( + uid=asset.action_id, twin_mode=sy.service.action.action_object.TwinMode.MOCK + ) + asset_private = root_client.api.services.action.get( + uid=asset.action_id, twin_mode=sy.service.action.action_object.TwinMode.PRIVATE + ) + assert isinstance(asset_mock, SyftError) + assert isinstance(asset_private, SyftError) From f12b5192582b804f31db42ab03ad160f4b0ee71a Mon Sep 17 00:00:00 2001 From: khoaguin Date: Wed, 3 Jul 2024 15:14:56 +0700 Subject: [PATCH 006/117] [syft/unit-tests] fix `test_delete_datasets` --- .../syft/src/syft/service/action/action_service.py | 4 ---- .../syft/service/dataset/dataset_service_test.py | 14 ++++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index 05069cce08b..fbc958506cb 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -276,10 +276,6 @@ def _get( resolve_nested: bool = True, ) -> Result[ActionObject, str]: """Get an object from the action store""" - # stdlib - - # relative - result = self.store.get( uid=uid, credentials=context.credentials, has_permission=has_permission ) diff --git a/packages/syft/tests/syft/service/dataset/dataset_service_test.py b/packages/syft/tests/syft/service/dataset/dataset_service_test.py index 1787aff4ab4..0ba659fe58b 100644 --- a/packages/syft/tests/syft/service/dataset/dataset_service_test.py +++ b/packages/syft/tests/syft/service/dataset/dataset_service_test.py @@ -324,10 +324,10 @@ def test_delete_datasets(worker: Worker) -> None: dataset = root_client.api.services.dataset.get_all()[0] asset = dataset.asset_list[0] asset_mock = root_client.api.services.action.get( - uid=asset.action_id, twin_mode=sy.service.action.action_object.TwinMode.MOCK + uid=asset.action_id, twin_mode=TwinMode.MOCK ) asset_private = root_client.api.services.action.get( - uid=asset.action_id, twin_mode=sy.service.action.action_object.TwinMode.PRIVATE + uid=asset.action_id, twin_mode=TwinMode.PRIVATE ) assert isinstance(asset_mock, ActionObject) assert isinstance(asset_private, ActionObject) @@ -336,10 +336,12 @@ def test_delete_datasets(worker: Worker) -> None: del_res = root_client.api.services.dataset.delete_by_uid(uid=dataset.id) assert isinstance(del_res, SyftSuccess) asset_mock = root_client.api.services.action.get( - uid=asset.action_id, twin_mode=sy.service.action.action_object.TwinMode.MOCK + uid=asset.action_id, twin_mode=TwinMode.MOCK ) asset_private = root_client.api.services.action.get( - uid=asset.action_id, twin_mode=sy.service.action.action_object.TwinMode.PRIVATE + uid=asset.action_id, twin_mode=TwinMode.PRIVATE ) - assert isinstance(asset_mock, SyftError) - assert isinstance(asset_private, SyftError) + assert isinstance(asset_mock, str) + assert f"Could not find item with uid {asset.action_id}" in asset_mock + assert isinstance(asset_private, str) + assert f"Could not find item with uid {asset.action_id}" in asset_private From 6ebe48c5560fac65c7e19357948ee23aefa10475 Mon Sep 17 00:00:00 2001 From: dk Date: Thu, 4 Jul 2024 09:55:56 +0700 Subject: [PATCH 007/117] [syft/dataset] adding properties to get private data and mock's blob entries for `Asset` --- .../syft/src/syft/service/dataset/dataset.py | 57 +++++++++++++++++++ .../syft/service/dataset/dataset_service.py | 4 ++ 2 files changed, 61 insertions(+) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index f7f492d9a06..80dcaed0fcf 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -20,6 +20,7 @@ # relative from ...serde.serializable import serializable +from ...store.blob_storage import BlobRetrieval from ...store.document_store import PartitionKey from ...types.datetime import DateTime from ...types.dicttuple import DictTuple @@ -299,6 +300,62 @@ def data(self) -> Any: display(warning) return None + @property + def data_blob(self) -> BlobRetrieval | SyftError: + """ + Return the blob entry for the data of the asset + """ + # relative + from ...client.api import APIRegistry + + api = APIRegistry.api_for( + node_uid=self.node_uid, + user_verify_key=self.syft_client_verify_key, + ) + if api is None or api.services is None: + return None + data_action_obj: str | ActionObject = api.services.action.get(self.action_id) + if isinstance(data_action_obj, str): + return SyftError( + message=f"Could not access private data. {str(data_action_obj)}" + ) + if not self.has_permission(data_action_obj): + return SyftError( + message="You do not have permission to access private data." + ) + blob_retrieval_res: BlobRetrieval | SyftError = api.services.blob_storage.read( + uid=data_action_obj.syft_blob_storage_entry_id + ) + if isinstance(blob_retrieval_res, SyftError): + return blob_retrieval_res + return blob_retrieval_res + + @property + def mock_blob(self) -> Any: + """ + Return the blob entry for the mock of the asset + """ + # relative + from ...client.api import APIRegistry + + api = APIRegistry.api_for( + node_uid=self.node_uid, + user_verify_key=self.syft_client_verify_key, + ) + if api is None or api.services is None: + return None + mock_action_obj: SyftError | ActionObject = api.services.action.get_mock( + self.action_id + ) + if isinstance(mock_action_obj, SyftError): + return mock_action_obj + blob_retrieval_res = api.services.blob_storage.read( + uid=mock_action_obj.syft_blob_storage_entry_id + ) + if isinstance(blob_retrieval_res, SyftError): + return blob_retrieval_res + return blob_retrieval_res + def _is_action_data_empty(obj: Any) -> bool: # just a wrapper of action_object.is_action_data_empty diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index bbd50353bfe..31246fc7445 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -1,6 +1,7 @@ # stdlib from collections.abc import Collection from collections.abc import Sequence +import logging # relative from ...serde.serializable import serializable @@ -28,6 +29,8 @@ from .dataset import DatasetPageView from .dataset_stash import DatasetStash +logger = logging.getLogger(__name__) + def _paginate_collection( collection: Collection, @@ -218,6 +221,7 @@ def delete_dataset( ) if isinstance(del_res, SyftError): return del_res + logger.info(del_res.message) return_msg.append(f"Asset with id '{asset.id}' deleted.") # delete the dataset object from the store result = self.stash.delete_by_uid(credentials=context.credentials, uid=uid) From 11e1d22541e187ac5a73e796cfb2819cc1cbb332 Mon Sep 17 00:00:00 2001 From: dk Date: Thu, 4 Jul 2024 10:55:46 +0700 Subject: [PATCH 008/117] [tests/unit] - add property methods to retrieve blob entries for Asset's mock and data - add test cases for deleting small (no blob store) and big datasets (with blob store) - modify blob_storage_test accordingly to new changes --- .../syft/src/syft/service/dataset/dataset.py | 4 ++ packages/syft/tests/conftest.py | 35 ++++++++++ .../syft/blob_storage/blob_storage_test.py | 60 ++++++----------- .../service/dataset/dataset_service_test.py | 65 +++++++++---------- 4 files changed, 90 insertions(+), 74 deletions(-) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index 80dcaed0fcf..48229c7e7f3 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -261,6 +261,8 @@ def mock(self) -> SyftError | Any: if api is None: return SyftError(message=f"You must login to {self.node_uid}") result = api.services.action.get_mock(self.action_id) + if isinstance(result, SyftError): + return result try: if isinstance(result, SyftObject): return result.syft_action_data @@ -291,6 +293,8 @@ def data(self) -> Any: if api is None or api.services is None: return None res = api.services.action.get(self.action_id) + if isinstance(res, str): + return SyftError(message=f"Could not access private data. {str(res)}") if self.has_permission(res): return res.syft_action_data else: diff --git a/packages/syft/tests/conftest.py b/packages/syft/tests/conftest.py index 2d781f817d7..5fb0cc0cb2d 100644 --- a/packages/syft/tests/conftest.py +++ b/packages/syft/tests/conftest.py @@ -10,10 +10,12 @@ # third party from faker import Faker +import numpy as np import pytest # syft absolute import syft as sy +from syft import Dataset from syft.abstract_node import NodeSideType from syft.client.domain_client import DomainClient from syft.node.worker import Worker @@ -246,6 +248,39 @@ def patched_user(monkeypatch): ) +@pytest.fixture +def small_dataset() -> Dataset: + dataset = Dataset( + name="small_dataset", + asset_list=[ + sy.Asset( + name="small_dataset", + data=np.array([1, 2, 3]), + mock=np.array([1, 1, 1]), + ) + ], + ) + yield dataset + + +@pytest.fixture +def big_dataset() -> Dataset: + num_elements = 20 * 1024 * 1024 + data_big = np.random.randint(0, 100, size=num_elements) + mock_big = np.random.randint(0, 100, size=num_elements) + dataset = Dataset( + name="big_dataset", + asset_list=[ + sy.Asset( + name="big_dataset", + data=data_big, + mock=mock_big, + ) + ], + ) + yield dataset + + __all__ = [ "mongo_store_partition", "mongo_document_store", diff --git a/packages/syft/tests/syft/blob_storage/blob_storage_test.py b/packages/syft/tests/syft/blob_storage/blob_storage_test.py index 1889004a47e..09f5ba45e86 100644 --- a/packages/syft/tests/syft/blob_storage/blob_storage_test.py +++ b/packages/syft/tests/syft/blob_storage/blob_storage_test.py @@ -9,6 +9,8 @@ # syft absolute import syft as sy from syft import ActionObject +from syft import Dataset +from syft import Worker from syft.client.domain_client import DomainClient from syft.service.blob_storage.util import can_upload_to_blob_storage from syft.service.blob_storage.util import min_size_for_blob_storage_upload @@ -117,7 +119,7 @@ def test_action_obj_send_save_to_blob_storage(worker): # big object that should be saved to blob storage assert min_size_for_blob_storage_upload(root_client.api.metadata) == 16 - num_elements = 50 * 1024 * 1024 + num_elements = 20 * 1024 * 1024 data_big = np.random.randint(0, 100, size=num_elements) # 4 bytes per int32 action_obj_2 = ActionObject.from_obj(data_big) assert can_upload_to_blob_storage(action_obj_2, root_client.api.metadata) @@ -135,44 +137,20 @@ def test_action_obj_send_save_to_blob_storage(worker): assert all(syft_retrieved_data.read() == data_big) -def test_upload_dataset_save_to_blob_storage(worker): +def test_upload_dataset_save_to_blob_storage( + worker: Worker, big_dataset: Dataset, small_dataset: Dataset +) -> None: root_client: DomainClient = worker.root_client - root_authed_ctx = AuthedServiceContext( - node=worker, credentials=root_client.verify_key - ) - dataset = sy.Dataset( - name="small_dataset", - asset_list=[ - sy.Asset( - name="small_dataset", - data=np.array([1, 2, 3]), - mock=np.array([1, 1, 1]), - ) - ], - ) - root_client.upload_dataset(dataset) - blob_storage = worker.get_service("BlobStorageService") - assert len(blob_storage.get_all_blob_storage_entries(context=root_authed_ctx)) == 0 - - num_elements = 50 * 1024 * 1024 - data_big = np.random.randint(0, 100, size=num_elements) - dataset_big = sy.Dataset( - name="big_dataset", - asset_list=[ - sy.Asset( - name="big_dataset", - data=data_big, - mock=np.array([1, 1, 1]), - ) - ], - ) - root_client.upload_dataset(dataset_big) - # the private data should be saved to the blob storage - blob_entries: list = blob_storage.get_all_blob_storage_entries( - context=root_authed_ctx - ) - assert len(blob_entries) == 1 - data_big_retrieved: SyftObjectRetrieval = blob_storage.read( - context=root_authed_ctx, uid=blob_entries[0].id - ) - assert all(data_big_retrieved.read() == data_big) + # the small dataset should not be saved to the blob storage + root_client.upload_dataset(small_dataset) + assert len(root_client.api.services.blob_storage.get_all()) == 0 + + # the big dataset should be saved to the blob storage + root_client.upload_dataset(big_dataset) + assert len(root_client.api.services.blob_storage.get_all()) == 2 + dataset = root_client.api.services.dataset.search(name=big_dataset.name)[0] + asset = dataset.asset_list[0] + assert isinstance(asset.mock_blob, SyftObjectRetrieval) + assert isinstance(asset.data_blob, SyftObjectRetrieval) + assert all(asset.mock_blob.read() == asset.mock) + assert all(asset.data_blob.read() == asset.data) diff --git a/packages/syft/tests/syft/service/dataset/dataset_service_test.py b/packages/syft/tests/syft/service/dataset/dataset_service_test.py index 0ba659fe58b..cf92ef5078f 100644 --- a/packages/syft/tests/syft/service/dataset/dataset_service_test.py +++ b/packages/syft/tests/syft/service/dataset/dataset_service_test.py @@ -15,12 +15,14 @@ from syft.node.worker import Worker from syft.service.action.action_object import ActionObject from syft.service.action.action_object import TwinMode +from syft.service.blob_storage.util import can_upload_to_blob_storage 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 SyftException from syft.service.response import SyftSuccess +from syft.store.blob_storage import SyftObjectRetrieval def random_hash() -> str: @@ -303,45 +305,42 @@ def test_upload_dataset_with_assets_of_different_data_types( ) -def test_delete_datasets(worker: Worker) -> None: +def test_delete_small_datasets(worker: Worker, small_dataset: Dataset) -> None: root_client = worker.root_client - mock = np.array([0, 1, 2, 3, 4]) - private = np.array([5, 6, 7, 8, 9]) - assets = [ - sy.Asset( - name="numpy-data", - mock=mock, - data=private, - shape=private.shape, - ) - ] - dataset = sy.Dataset( - name="my-dataset", description="This is a cool dataset", asset_list=assets - ) - upload_res = root_client.upload_dataset(dataset) + assert not can_upload_to_blob_storage(small_dataset, root_client.api.metadata) + upload_res = root_client.upload_dataset(small_dataset) assert isinstance(upload_res, SyftSuccess) dataset = root_client.api.services.dataset.get_all()[0] asset = dataset.asset_list[0] - asset_mock = root_client.api.services.action.get( - uid=asset.action_id, twin_mode=TwinMode.MOCK - ) - asset_private = root_client.api.services.action.get( - uid=asset.action_id, twin_mode=TwinMode.PRIVATE - ) - assert isinstance(asset_mock, ActionObject) - assert isinstance(asset_private, ActionObject) + assert isinstance(asset.data, np.ndarray) + assert isinstance(asset.mock, np.ndarray) # delete the dataset del_res = root_client.api.services.dataset.delete_by_uid(uid=dataset.id) assert isinstance(del_res, SyftSuccess) - asset_mock = root_client.api.services.action.get( - uid=asset.action_id, twin_mode=TwinMode.MOCK - ) - asset_private = root_client.api.services.action.get( - uid=asset.action_id, twin_mode=TwinMode.PRIVATE - ) - assert isinstance(asset_mock, str) - assert f"Could not find item with uid {asset.action_id}" in asset_mock - assert isinstance(asset_private, str) - assert f"Could not find item with uid {asset.action_id}" in asset_private + assert isinstance(asset.data, SyftError) + assert isinstance(asset.mock, SyftError) + + +def test_delete_big_datasets(worker: Worker, big_dataset: Dataset) -> None: + root_client = worker.root_client + assert can_upload_to_blob_storage(big_dataset, root_client.api.metadata) + upload_res = root_client.upload_dataset(big_dataset) + assert isinstance(upload_res, SyftSuccess) + + dataset = root_client.api.services.dataset.get_all()[0] + asset = dataset.asset_list[0] + assert isinstance(asset.data, np.ndarray) + assert isinstance(asset.mock, np.ndarray) + # test that the data is saved in the blob storage + assert isinstance(asset.mock_blob, SyftObjectRetrieval) + assert isinstance(asset.data_blob, SyftObjectRetrieval) + + # delete the dataset + del_res = root_client.api.services.dataset.delete_by_uid(uid=dataset.id) + assert isinstance(del_res, SyftSuccess) + assert isinstance(asset.data, SyftError) + assert isinstance(asset.mock, SyftError) + assert isinstance(asset.data_blob, SyftError) + assert isinstance(asset.mock_blob, SyftError) From 5fbeb387fa7d28e60383ae99fc7835778de775dd Mon Sep 17 00:00:00 2001 From: dk Date: Thu, 4 Jul 2024 11:13:09 +0700 Subject: [PATCH 009/117] [syft/chore] fix linting --- .../syft/src/syft/service/dataset/dataset.py | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index 48229c7e7f3..c4aa49f9d88 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -19,6 +19,7 @@ from typing_extensions import Self # relative +from ...client.api import APIRegistry from ...serde.serializable import serializable from ...store.blob_storage import BlobRetrieval from ...store.document_store import PartitionKey @@ -239,9 +240,6 @@ def __eq__(self, other: object) -> bool: @property def pointer(self) -> Any: - # relative - from ...client.api import APIRegistry - api = APIRegistry.api_for( node_uid=self.node_uid, user_verify_key=self.syft_client_verify_key, @@ -251,9 +249,6 @@ def pointer(self) -> Any: @property def mock(self) -> SyftError | Any: - # relative - from ...client.api import APIRegistry - api = APIRegistry.api_for( node_uid=self.node_uid, user_verify_key=self.syft_client_verify_key, @@ -284,7 +279,6 @@ def has_permission(self, data_result: Any) -> bool: @property def data(self) -> Any: # relative - from ...client.api import APIRegistry api = APIRegistry.api_for( node_uid=self.node_uid, @@ -309,15 +303,15 @@ def data_blob(self) -> BlobRetrieval | SyftError: """ Return the blob entry for the data of the asset """ - # relative - from ...client.api import APIRegistry - api = APIRegistry.api_for( node_uid=self.node_uid, user_verify_key=self.syft_client_verify_key, ) if api is None or api.services is None: - return None + return SyftError( + message=f"Could not get api for {self.node_uid}. You must login first." + ) + data_action_obj: str | ActionObject = api.services.action.get(self.action_id) if isinstance(data_action_obj, str): return SyftError( @@ -327,6 +321,7 @@ def data_blob(self) -> BlobRetrieval | SyftError: return SyftError( message="You do not have permission to access private data." ) + blob_retrieval_res: BlobRetrieval | SyftError = api.services.blob_storage.read( uid=data_action_obj.syft_blob_storage_entry_id ) @@ -335,29 +330,31 @@ def data_blob(self) -> BlobRetrieval | SyftError: return blob_retrieval_res @property - def mock_blob(self) -> Any: + def mock_blob(self) -> BlobRetrieval | SyftError | None: """ Return the blob entry for the mock of the asset """ - # relative - from ...client.api import APIRegistry - api = APIRegistry.api_for( node_uid=self.node_uid, user_verify_key=self.syft_client_verify_key, ) if api is None or api.services is None: - return None + return SyftError( + message=f"Could not get api for {self.node_uid}. You must login first." + ) + mock_action_obj: SyftError | ActionObject = api.services.action.get_mock( self.action_id ) if isinstance(mock_action_obj, SyftError): return mock_action_obj + blob_retrieval_res = api.services.blob_storage.read( uid=mock_action_obj.syft_blob_storage_entry_id ) if isinstance(blob_retrieval_res, SyftError): return blob_retrieval_res + return blob_retrieval_res From fccc2e446de246d19cbcd5107918f68de0dfe30e Mon Sep 17 00:00:00 2001 From: khoaguin Date: Thu, 4 Jul 2024 13:39:48 +0700 Subject: [PATCH 010/117] [syft/dataset] return None if can't get mock / data --- packages/syft/src/syft/service/dataset/dataset.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index c4aa49f9d88..2396fbbbe7d 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -256,8 +256,6 @@ def mock(self) -> SyftError | Any: if api is None: return SyftError(message=f"You must login to {self.node_uid}") result = api.services.action.get_mock(self.action_id) - if isinstance(result, SyftError): - return result try: if isinstance(result, SyftObject): return result.syft_action_data @@ -287,8 +285,6 @@ def data(self) -> Any: if api is None or api.services is None: return None res = api.services.action.get(self.action_id) - if isinstance(res, str): - return SyftError(message=f"Could not access private data. {str(res)}") if self.has_permission(res): return res.syft_action_data else: From d08fafd7cc5eaef00e323555ab38d27937f7b442 Mon Sep 17 00:00:00 2001 From: khoaguin Date: Thu, 4 Jul 2024 13:52:35 +0700 Subject: [PATCH 011/117] [syft/dataset] add back error handling for `Asset.data` and `Asset.mock` - change tutorial notebook accordingly --- .../model-training/01-data-scientist-submit-code.ipynb | 3 ++- packages/syft/src/syft/service/dataset/dataset.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb b/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb index 7b65d033cbc..f29f499d145 100644 --- a/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb +++ b/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb @@ -103,7 +103,8 @@ "metadata": {}, "outputs": [], "source": [ - "assert training_images.data is None" + "assert isinstance(training_images.data, sy.SyftError)\n", + "training_labels.data" ] }, { diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index 2396fbbbe7d..c4aa49f9d88 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -256,6 +256,8 @@ def mock(self) -> SyftError | Any: if api is None: return SyftError(message=f"You must login to {self.node_uid}") result = api.services.action.get_mock(self.action_id) + if isinstance(result, SyftError): + return result try: if isinstance(result, SyftObject): return result.syft_action_data @@ -285,6 +287,8 @@ def data(self) -> Any: if api is None or api.services is None: return None res = api.services.action.get(self.action_id) + if isinstance(res, str): + return SyftError(message=f"Could not access private data. {str(res)}") if self.has_permission(res): return res.syft_action_data else: From f915e748b252119932fa8053ff26c3e584b79dbd Mon Sep 17 00:00:00 2001 From: khoaguin Date: Thu, 4 Jul 2024 14:30:14 +0700 Subject: [PATCH 012/117] [tests/integration] change gateway_test to reflect new changes in Asset --- tests/integration/network/gateway_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/network/gateway_test.py b/tests/integration/network/gateway_test.py index 48cddf8ce4c..11e369907f6 100644 --- a/tests/integration/network/gateway_test.py +++ b/tests/integration/network/gateway_test.py @@ -221,7 +221,7 @@ def test_dataset_search(set_env_var, gateway_port: int, domain_1_port: int) -> N assert isinstance(dataset, Dataset) assert len(dataset.assets) == 1 assert isinstance(dataset.assets[0].mock, np.ndarray) - assert dataset.assets[0].data is None + assert isinstance(dataset.assets[0].data, SyftError) # search a wrong dataset should return an empty list wrong_search = sy.search(_random_hash()) From 328dc29c275334aa48571b304ba49ae44bf6b9b4 Mon Sep 17 00:00:00 2001 From: teo Date: Thu, 4 Jul 2024 18:45:10 +0300 Subject: [PATCH 013/117] added created and updated date --- .../src/syft/service/action/action_object.py | 2 + .../syft/src/syft/store/document_store.py | 39 +++++++----------- packages/syft/src/syft/types/basedatetime.py | 41 +++++++++++++++++++ packages/syft/src/syft/types/syft_object.py | 6 ++- 4 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 packages/syft/src/syft/types/basedatetime.py diff --git a/packages/syft/src/syft/service/action/action_object.py b/packages/syft/src/syft/service/action/action_object.py index b9ffd16ebf6..a6a89a731f0 100644 --- a/packages/syft/src/syft/service/action/action_object.py +++ b/packages/syft/src/syft/service/action/action_object.py @@ -255,6 +255,8 @@ class ActionObjectPointer: "_get_api", # syft "__validate_private_attrs__", # syft "id", # syft + "created_date", #syft + "updated_date", #syft "to_mongo", # syft 🟡 TODO 23: Add composeable / inheritable object passthrough attrs "__attr_searchable__", # syft "__canonical_name__", # syft diff --git a/packages/syft/src/syft/store/document_store.py b/packages/syft/src/syft/store/document_store.py index e71110667c3..a679faa4f61 100644 --- a/packages/syft/src/syft/store/document_store.py +++ b/packages/syft/src/syft/store/document_store.py @@ -13,6 +13,7 @@ from result import Err from result import Ok from result import Result +from syft.types.basedatetime import BaseDateTime from typeguard import check_type # relative @@ -639,6 +640,13 @@ def set( add_storage_permission: bool = True, ignore_duplicates: bool = False, ) -> Result[BaseStash.object_type, str]: + + res = self.check_type(obj, self.object_type) + # we dont use and_then logic here as it is hard because of the order of the arguments + if res.is_err(): + return res + if obj.created_date is None: + obj.created_date = BaseDateTime.now() res = self.partition.set( credentials=credentials, obj=obj, @@ -745,27 +753,25 @@ def update( obj: BaseStash.object_type, has_permission: bool = False, ) -> Result[BaseStash.object_type, str]: + obj.updated_date = BaseDateTime.now() qk = self.partition.store_query_key(obj) res = self.partition.update( credentials=credentials, qk=qk, obj=obj, has_permission=has_permission ) return res - -@instrument -class BaseUIDStoreStash(BaseStash): def delete_by_uid( self, credentials: SyftVerifyKey, uid: UID ) -> Result[SyftSuccess, str]: qk = UIDPartitionKey.with_obj(uid) - result = super().delete(credentials=credentials, qk=qk) + result = self.delete(credentials=credentials, qk=qk) if result.is_ok(): return Ok(SyftSuccess(message=f"ID: {uid} deleted")) return result def get_by_uid( self, credentials: SyftVerifyKey, uid: UID - ) -> Result[BaseUIDStoreStash.object_type | None, str]: + ) -> Result[BaseStash.object_type | None, str]: res = self.partition.get(credentials=credentials, uid=uid) # NOTE Return Ok(None) when no results are found for backwards compatibility @@ -773,26 +779,9 @@ def get_by_uid( return Ok(None) return res - def set( - self, - credentials: SyftVerifyKey, - obj: BaseUIDStoreStash.object_type, - add_permissions: list[ActionObjectPermission] | None = None, - add_storage_permission: bool = True, - ignore_duplicates: bool = False, - ) -> Result[BaseUIDStoreStash.object_type, str]: - res = self.check_type(obj, self.object_type) - # we dont use and_then logic here as it is hard because of the order of the arguments - if res.is_err(): - return res - return super().set( - credentials=credentials, - obj=res.ok(), - ignore_duplicates=ignore_duplicates, - add_permissions=add_permissions, - add_storage_permission=add_storage_permission, - ) - +@instrument +class BaseUIDStoreStash(BaseStash): + pass @serializable() class StoreConfig(SyftBaseObject): diff --git a/packages/syft/src/syft/types/basedatetime.py b/packages/syft/src/syft/types/basedatetime.py new file mode 100644 index 00000000000..a667d4433e1 --- /dev/null +++ b/packages/syft/src/syft/types/basedatetime.py @@ -0,0 +1,41 @@ +from datetime import datetime, timezone +from functools import total_ordering +from typing import Any + +# third party +from typing_extensions import Self +import pydantic + +# relative +from ..serde.serializable import serializable +from datetime import datetime + + +@serializable() +@total_ordering +class BaseDateTime(pydantic.BaseModel): + # id: UID | None = None # type: ignore + utc_timestamp: float + + @classmethod + def now(cls) -> Self: + return cls(utc_timestamp=datetime.utcnow().timestamp()) + + def __str__(self) -> str: + utc_datetime = datetime.utcfromtimestamp(self.utc_timestamp) + return utc_datetime.strftime("%Y-%m-%d %H:%M:%S") + + def __hash__(self) -> int: + return hash(self.utc_timestamp) + + def __sub__(self, other: Self) -> Self: + res = self.utc_timestamp - other.utc_timestamp + return BaseDateTime(utc_timestamp=res) + + def __eq__(self, other: Any) -> bool: + if other is None: + return False + return self.utc_timestamp == other.utc_timestamp + + def __lt__(self, other: Self) -> bool: + return self.utc_timestamp < other.utc_timestamp \ No newline at end of file diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 10c975bc5f0..a2849f12406 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -33,6 +33,7 @@ from pydantic import model_validator from pydantic.fields import PydanticUndefined from result import OkErr +from syft.types.basedatetime import BaseDateTime from typeguard import check_type from typing_extensions import Self @@ -395,7 +396,7 @@ def get_migration_for_version( class SyftObject(SyftBaseObject, SyftObjectRegistry, SyftMigrationRegistry): __canonical_name__ = "SyftObject" - __version__ = SYFT_OBJECT_VERSION_2 + __version__ = SYFT_OBJECT_VERSION_3 model_config = ConfigDict( arbitrary_types_allowed=True, @@ -404,6 +405,9 @@ class SyftObject(SyftBaseObject, SyftObjectRegistry, SyftMigrationRegistry): # all objects have a UID id: UID + + created_date: BaseDateTime | None = BaseDateTime.now() + updated_date: BaseDateTime | None = BaseDateTime.now() # # move this to transforms @model_validator(mode="before") From f11f0c22c54b18088fa520daa444d89ec51175ad Mon Sep 17 00:00:00 2001 From: teo Date: Thu, 4 Jul 2024 18:52:19 +0300 Subject: [PATCH 014/117] fix lint --- packages/syft/src/syft/service/action/action_object.py | 4 ++-- packages/syft/src/syft/store/document_store.py | 5 +++-- packages/syft/src/syft/types/basedatetime.py | 8 ++++---- packages/syft/src/syft/types/syft_object.py | 4 ++-- .../tests/syft/service/dataset/dataset_service_test.py | 10 +++------- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_object.py b/packages/syft/src/syft/service/action/action_object.py index a6a89a731f0..7d022c41c8f 100644 --- a/packages/syft/src/syft/service/action/action_object.py +++ b/packages/syft/src/syft/service/action/action_object.py @@ -255,8 +255,8 @@ class ActionObjectPointer: "_get_api", # syft "__validate_private_attrs__", # syft "id", # syft - "created_date", #syft - "updated_date", #syft + "created_date", # syft + "updated_date", # syft "to_mongo", # syft 🟡 TODO 23: Add composeable / inheritable object passthrough attrs "__attr_searchable__", # syft "__canonical_name__", # syft diff --git a/packages/syft/src/syft/store/document_store.py b/packages/syft/src/syft/store/document_store.py index a679faa4f61..a6ae1f9229c 100644 --- a/packages/syft/src/syft/store/document_store.py +++ b/packages/syft/src/syft/store/document_store.py @@ -13,7 +13,6 @@ from result import Err from result import Ok from result import Result -from syft.types.basedatetime import BaseDateTime from typeguard import check_type # relative @@ -25,6 +24,7 @@ from ..service.context import AuthedServiceContext from ..service.response import SyftSuccess from ..types.base import SyftBaseModel +from ..types.basedatetime import BaseDateTime from ..types.syft_object import SYFT_OBJECT_VERSION_2 from ..types.syft_object import SyftBaseObject from ..types.syft_object import SyftObject @@ -640,7 +640,6 @@ def set( add_storage_permission: bool = True, ignore_duplicates: bool = False, ) -> Result[BaseStash.object_type, str]: - res = self.check_type(obj, self.object_type) # we dont use and_then logic here as it is hard because of the order of the arguments if res.is_err(): @@ -779,10 +778,12 @@ def get_by_uid( return Ok(None) return res + @instrument class BaseUIDStoreStash(BaseStash): pass + @serializable() class StoreConfig(SyftBaseObject): """Base Store configuration diff --git a/packages/syft/src/syft/types/basedatetime.py b/packages/syft/src/syft/types/basedatetime.py index a667d4433e1..41f58291632 100644 --- a/packages/syft/src/syft/types/basedatetime.py +++ b/packages/syft/src/syft/types/basedatetime.py @@ -1,14 +1,14 @@ -from datetime import datetime, timezone +# stdlib +from datetime import datetime from functools import total_ordering from typing import Any # third party -from typing_extensions import Self import pydantic +from typing_extensions import Self # relative from ..serde.serializable import serializable -from datetime import datetime @serializable() @@ -38,4 +38,4 @@ def __eq__(self, other: Any) -> bool: return self.utc_timestamp == other.utc_timestamp def __lt__(self, other: Self) -> bool: - return self.utc_timestamp < other.utc_timestamp \ No newline at end of file + return self.utc_timestamp < other.utc_timestamp diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index a2849f12406..37f2689592d 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -33,7 +33,6 @@ from pydantic import model_validator from pydantic.fields import PydanticUndefined from result import OkErr -from syft.types.basedatetime import BaseDateTime from typeguard import check_type from typing_extensions import Self @@ -48,6 +47,7 @@ from ..util.util import aggressive_set_attr from ..util.util import full_name_with_qualname from ..util.util import get_qualname_for +from .basedatetime import BaseDateTime from .syft_metaclass import Empty from .syft_metaclass import PartialModelMetaclass from .uid import UID @@ -405,7 +405,7 @@ class SyftObject(SyftBaseObject, SyftObjectRegistry, SyftMigrationRegistry): # all objects have a UID id: UID - + created_date: BaseDateTime | None = BaseDateTime.now() updated_date: BaseDateTime | None = BaseDateTime.now() diff --git a/packages/syft/tests/syft/service/dataset/dataset_service_test.py b/packages/syft/tests/syft/service/dataset/dataset_service_test.py index 1aa85c07865..f978b0d2729 100644 --- a/packages/syft/tests/syft/service/dataset/dataset_service_test.py +++ b/packages/syft/tests/syft/service/dataset/dataset_service_test.py @@ -276,13 +276,9 @@ def different_data_types( def test_upload_dataset_with_assets_of_different_data_types( worker: Worker, - different_data_types: int - | str - | dict - | set - | np.ndarray - | pd.DataFrame - | torch.Tensor, + different_data_types: ( + int | str | dict | set | np.ndarray | pd.DataFrame | torch.Tensor + ), ) -> None: asset = sy.Asset( name=random_hash(), From 5d6263994e7ab53585e42529f50730ee95ed9142 Mon Sep 17 00:00:00 2001 From: dk Date: Fri, 5 Jul 2024 10:01:05 +0700 Subject: [PATCH 015/117] [tests/unit] delete dataset after depositing results in `test_diff_state_with_dataset` --- .../service/sync/sync_resolve_single_test.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py b/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py index 83fba7fd168..1b39ae3e267 100644 --- a/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py +++ b/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py @@ -10,6 +10,7 @@ from syft.client.sync_decision import SyncDecision from syft.client.syncing import compare_clients from syft.client.syncing import resolve +from syft.node.worker import Worker from syft.service.job.job_stash import Job from syft.service.request.request import RequestStatus from syft.service.response import SyftError @@ -135,7 +136,7 @@ def compute() -> int: assert res == compute(syft_no_node=True) -def test_diff_state_with_dataset(low_worker, high_worker): +def test_diff_state_with_dataset(low_worker: Worker, high_worker: Worker): low_client: DomainClient = low_worker.root_client client_low_ds = get_ds_client(low_client) high_client: DomainClient = high_worker.root_client @@ -162,8 +163,14 @@ def compute_mean(data) -> int: # run_and_deposit_result(high_client) data_high = high_client.datasets[0].assets[0] - result = high_client.code.compute_mean(data=data_high, blocking=True) - high_client.requests[0].deposit_result(result) + mean_result = high_client.code.compute_mean(data=data_high, blocking=True) + high_client.requests[0].deposit_result(mean_result) + + # the high side client delete the dataset after depositing the result + dataset_del_res = high_client.api.services.dataset.delete_by_uid( + high_client.datasets[0].id + ) + assert isinstance(dataset_del_res, SyftSuccess) diff_state_before, diff_state_after = compare_and_resolve( from_client=high_client, to_client=low_client @@ -182,11 +189,7 @@ def compute_mean(data) -> int: res_non_blocking = client_low_ds.code.compute_mean(blocking=False).wait() # expected_result = compute_mean(syft_no_node=True, data=) - assert ( - res_blocking - == res_non_blocking - == high_client.datasets[0].assets[0].data.mean() - ) + assert res_blocking == res_non_blocking == mean_result def test_sync_with_error(low_worker, high_worker): From 449d0fb7e21d0c2c226f50ee7863a3e8783ccfaf Mon Sep 17 00:00:00 2001 From: dk Date: Fri, 5 Jul 2024 10:09:34 +0700 Subject: [PATCH 016/117] [tests/unit] delete low side dataset in `test_diff_state_with_dataset` since it's not needed --- .../syft/tests/syft/service/sync/sync_resolve_single_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py b/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py index 1b39ae3e267..8d603afb427 100644 --- a/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py +++ b/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py @@ -142,7 +142,6 @@ def test_diff_state_with_dataset(low_worker: Worker, high_worker: Worker): high_client: DomainClient = high_worker.root_client _ = create_dataset(high_client) - _ = create_dataset(low_client) @sy.syft_function_single_use() def compute_mean(data) -> int: From ef881b61164af1f2f29c4d1f45f8ac98f15bcd75 Mon Sep 17 00:00:00 2001 From: dk Date: Fri, 5 Jul 2024 14:03:44 +0700 Subject: [PATCH 017/117] [tests/unit] improve assert message for clarity --- .../syft/tests/syft/service/sync/sync_resolve_single_test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py b/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py index 8d603afb427..7e07f467277 100644 --- a/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py +++ b/packages/syft/tests/syft/service/sync/sync_resolve_single_test.py @@ -150,7 +150,9 @@ def compute_mean(data) -> int: _ = client_low_ds.code.request_code_execution(compute_mean) result = client_low_ds.code.compute_mean(blocking=False) - assert isinstance(result, SyftError), "DS cannot start a job on low side" + assert isinstance( + result, SyftError + ), "DS cannot start a job on low side since the data was not passed as an argument" diff_state_before, diff_state_after = compare_and_resolve( from_client=low_client, to_client=high_client From a0526292ac40863998de7d7ef732a1cb9d46820f Mon Sep 17 00:00:00 2001 From: teo Date: Fri, 5 Jul 2024 11:58:52 +0300 Subject: [PATCH 018/117] added middle level between version and syft object --- .../syft/src/syft/store/document_store.py | 2 +- packages/syft/src/syft/types/basedatetime.py | 41 ---------------- packages/syft/src/syft/types/syft_object.py | 48 +++++++++++++++++-- 3 files changed, 45 insertions(+), 46 deletions(-) delete mode 100644 packages/syft/src/syft/types/basedatetime.py diff --git a/packages/syft/src/syft/store/document_store.py b/packages/syft/src/syft/store/document_store.py index a6ae1f9229c..7458148e5fc 100644 --- a/packages/syft/src/syft/store/document_store.py +++ b/packages/syft/src/syft/store/document_store.py @@ -24,7 +24,7 @@ from ..service.context import AuthedServiceContext from ..service.response import SyftSuccess from ..types.base import SyftBaseModel -from ..types.basedatetime import BaseDateTime +from ..types.syft_object import BaseDateTime from ..types.syft_object import SYFT_OBJECT_VERSION_2 from ..types.syft_object import SyftBaseObject from ..types.syft_object import SyftObject diff --git a/packages/syft/src/syft/types/basedatetime.py b/packages/syft/src/syft/types/basedatetime.py deleted file mode 100644 index 41f58291632..00000000000 --- a/packages/syft/src/syft/types/basedatetime.py +++ /dev/null @@ -1,41 +0,0 @@ -# stdlib -from datetime import datetime -from functools import total_ordering -from typing import Any - -# third party -import pydantic -from typing_extensions import Self - -# relative -from ..serde.serializable import serializable - - -@serializable() -@total_ordering -class BaseDateTime(pydantic.BaseModel): - # id: UID | None = None # type: ignore - utc_timestamp: float - - @classmethod - def now(cls) -> Self: - return cls(utc_timestamp=datetime.utcnow().timestamp()) - - def __str__(self) -> str: - utc_datetime = datetime.utcfromtimestamp(self.utc_timestamp) - return utc_datetime.strftime("%Y-%m-%d %H:%M:%S") - - def __hash__(self) -> int: - return hash(self.utc_timestamp) - - def __sub__(self, other: Self) -> Self: - res = self.utc_timestamp - other.utc_timestamp - return BaseDateTime(utc_timestamp=res) - - def __eq__(self, other: Any) -> bool: - if other is None: - return False - return self.utc_timestamp == other.utc_timestamp - - def __lt__(self, other: Self) -> bool: - return self.utc_timestamp < other.utc_timestamp diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 37f2689592d..1dd4250c71c 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -7,7 +7,9 @@ from collections.abc import Mapping from collections.abc import Sequence from collections.abc import Set +from datetime import datetime from functools import cache +from functools import total_ordering from hashlib import sha256 import inspect from inspect import Signature @@ -39,6 +41,7 @@ # relative from ..node.credentials import SyftVerifyKey from ..serde.recursive_primitives import recursive_serde_register_type +from ..serde.serializable import serializable from ..serde.serialize import _serialize as serialize from ..service.response import SyftError from ..util.autoreload import autoreload_enabled @@ -47,7 +50,6 @@ from ..util.util import aggressive_set_attr from ..util.util import full_name_with_qualname from ..util.util import get_qualname_for -from .basedatetime import BaseDateTime from .syft_metaclass import Empty from .syft_metaclass import PartialModelMetaclass from .uid import UID @@ -394,7 +396,44 @@ def get_migration_for_version( ] -class SyftObject(SyftBaseObject, SyftObjectRegistry, SyftMigrationRegistry): +class SyftObjectVersioned(SyftBaseObject, SyftObjectRegistry, SyftMigrationRegistry): + __canonical_name__ = "SyftObjectVersioned" + __version__ = SYFT_OBJECT_VERSION_1 + + +@serializable() +@total_ordering +class BaseDateTime(SyftObjectVersioned): + __canonical_name__ = "BaseDateTime" + __version__ = SYFT_OBJECT_VERSION_1 + # id: UID | None = None # type: ignore + utc_timestamp: float + + @classmethod + def now(cls) -> Self: + return cls(utc_timestamp=datetime.utcnow().timestamp()) + + def __str__(self) -> str: + utc_datetime = datetime.utcfromtimestamp(self.utc_timestamp) + return utc_datetime.strftime("%Y-%m-%d %H:%M:%S") + + def __hash__(self) -> int: + return hash(self.utc_timestamp) + + def __sub__(self, other: Self) -> Self: + res = self.utc_timestamp - other.utc_timestamp + return BaseDateTime(utc_timestamp=res) + + def __eq__(self, other: Any) -> bool: + if other is None: + return False + return self.utc_timestamp == other.utc_timestamp + + def __lt__(self, other: Self) -> bool: + return self.utc_timestamp < other.utc_timestamp + + +class SyftObject(SyftObjectVersioned): __canonical_name__ = "SyftObject" __version__ = SYFT_OBJECT_VERSION_3 @@ -406,8 +445,9 @@ class SyftObject(SyftBaseObject, SyftObjectRegistry, SyftMigrationRegistry): # all objects have a UID id: UID - created_date: BaseDateTime | None = BaseDateTime.now() - updated_date: BaseDateTime | None = BaseDateTime.now() + created_date: BaseDateTime | None = None + updated_date: BaseDateTime | None = None + deleted_date: BaseDateTime | None = None # # move this to transforms @model_validator(mode="before") From 2f617e52d63350cf6fa8ac688df45a5f5b676abf Mon Sep 17 00:00:00 2001 From: teo Date: Fri, 5 Jul 2024 15:02:38 +0300 Subject: [PATCH 019/117] fix bug with action objects --- packages/syft/src/syft/service/action/action_object.py | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/syft/src/syft/service/action/action_object.py b/packages/syft/src/syft/service/action/action_object.py index 7d022c41c8f..c4c9f535a99 100644 --- a/packages/syft/src/syft/service/action/action_object.py +++ b/packages/syft/src/syft/service/action/action_object.py @@ -257,6 +257,7 @@ class ActionObjectPointer: "id", # syft "created_date", # syft "updated_date", # syft + "deleted_date", # syft "to_mongo", # syft 🟡 TODO 23: Add composeable / inheritable object passthrough attrs "__attr_searchable__", # syft "__canonical_name__", # syft From a4284d9d81d264ebb01f37307a04beae6b6fee12 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Mon, 8 Jul 2024 15:08:45 +0530 Subject: [PATCH 020/117] cleanup message for the blob storage entry delete - rename _delete_blob_entry to _delete_blob_storage_entry --- .../src/syft/service/action/action_service.py | 27 ++++++++++++------- .../syft/service/dataset/dataset_service.py | 10 ++++--- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index 7a16b5651d9..7b6d7f966f0 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -2,6 +2,7 @@ import importlib import logging from typing import Any +from typing import cast # third party import numpy as np @@ -859,13 +860,13 @@ def delete( obj: ActionObject | TwinObject = get_res.ok() return_msg = [] - # delete object's blob storage entry - blob_del_res = self._delete_blob_entry(context=context, obj=obj) + # delete any associated blob storage entry object to the action object + blob_del_res = self._delete_blob_storage_entry(context=context, obj=obj) if isinstance(blob_del_res, SyftError): return SyftError(message=blob_del_res.message) return_msg.append(blob_del_res.message) - # delete the object from the action store + # delete the action object from the action store store_del_res = self._delete_from_action_store(context=context, obj=obj) if isinstance(store_del_res, SyftError): return SyftError(message=store_del_res.message) @@ -873,20 +874,23 @@ def delete( return SyftSuccess(message="\n".join(return_msg)) - def _delete_blob_entry( + def _delete_blob_storage_entry( self, context: AuthedServiceContext, obj: TwinObject | ActionObject, ) -> SyftSuccess | SyftError: - return_msg = [] - blob_store_service = context.node.get_service("BlobStorageService") + deleted_blob_ids = [] + blob_store_service = cast( + BlobStorageService, context.node.get_service(BlobStorageService) + ) + if isinstance(obj, ActionObject) and obj.syft_blob_storage_entry_id: blob_del_res = blob_store_service.delete( context=context, uid=obj.syft_blob_storage_entry_id ) if isinstance(blob_del_res, SyftError): return SyftError(message=blob_del_res.message) - return_msg.append(blob_del_res.message) + deleted_blob_ids.append(obj.syft_blob_storage_entry_id) if isinstance(obj, TwinObject): if obj.private.syft_blob_storage_entry_id: blob_del_res = blob_store_service.delete( @@ -894,15 +898,18 @@ def _delete_blob_entry( ) if isinstance(blob_del_res, SyftError): return SyftError(message=blob_del_res.message) - return_msg.append(blob_del_res.message) + deleted_blob_ids.append(obj.private.syft_blob_storage_entry_id) if obj.mock.syft_blob_storage_entry_id: blob_del_res = blob_store_service.delete( context=context, uid=obj.mock.syft_blob_storage_entry_id ) if isinstance(blob_del_res, SyftError): return SyftError(message=blob_del_res.message) - return_msg.append(blob_del_res.message) - return SyftSuccess(message="\n".join(return_msg)) + deleted_blob_ids.append(obj.mock.syft_blob_storage_entry_id) + + message = f"Deleted blob storage entries: {', '.join(str(blob_id) for blob_id in deleted_blob_ids)}" + + return SyftSuccess(message=message) def _delete_from_action_store( self, diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index 31246fc7445..ddd40c8f416 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -2,6 +2,7 @@ from collections.abc import Collection from collections.abc import Sequence import logging +from typing import cast # relative from ...serde.serializable import serializable @@ -11,6 +12,7 @@ from ...util.telemetry import instrument from ..action.action_permissions import ActionObjectPermission from ..action.action_permissions import ActionPermission +from ..action.action_service import ActionService from ..context import AuthedServiceContext from ..response import SyftError from ..response import SyftSuccess @@ -215,19 +217,21 @@ def delete_dataset( # delete the dataset's assets return_msg = [] for asset in dataset.asset_list: - action_service = context.node.get_service("ActionService") + action_service = cast( + ActionService, context.node.get_service(ActionService) + ) del_res: SyftSuccess | SyftError = action_service.delete( context=context, uid=asset.action_id ) if isinstance(del_res, SyftError): return del_res logger.info(del_res.message) - return_msg.append(f"Asset with id '{asset.id}' deleted.") + return_msg.append(f"Asset with id '{asset.id}' successfully deleted.") # delete the dataset object from the store result = self.stash.delete_by_uid(credentials=context.credentials, uid=uid) if result.is_err(): return SyftError(message=result.err()) - return_msg.append(f"Dataset with id '{uid}' deleted.") + return_msg.append(f"Dataset with id '{uid}' successfully deleted.") return SyftSuccess(message="\n".join(return_msg)) From 204d2624fdb526a2715933d3c90badc9d2ab9b84 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Mon, 8 Jul 2024 22:15:42 +0530 Subject: [PATCH 021/117] add a marked as deleted flag to datasets - rename delete by uid API to delete --- .../src/syft/protocol/protocol_version.json | 4 +- .../syft/src/syft/service/dataset/dataset.py | 78 ++++--------------- .../syft/service/dataset/dataset_service.py | 4 +- 3 files changed, 17 insertions(+), 69 deletions(-) diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index 21e62327e28..93c2413889f 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -490,14 +490,14 @@ "Dataset": { "3": { "version": 3, - "hash": "12a24de2ec144fe54eb873767131abed362827e08cd47a5c4d128acee2f2db91", + "hash": "6fff7fd8eb47976d34fa954473757266ad6658bfef9781efbd1855c938aec131", "action": "add" } }, "CreateDataset": { "3": { "version": 3, - "hash": "c96a925ab43440b9c39ab5eb28d7fc4a4c8bf7934474b7c432dc7b12067c7766", + "hash": "1477cdc381b217612bb3b59b4a37ee1b8e2b27526852163d87d1a65338195136", "action": "add" } } diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index cba0e7df7d6..45e9ac3104e 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -22,7 +22,6 @@ # relative from ...client.api import APIRegistry from ...serde.serializable import serializable -from ...store.blob_storage import BlobRetrieval from ...store.document_store import PartitionKey from ...types.datetime import DateTime from ...types.dicttuple import DictTuple @@ -303,65 +302,6 @@ def data(self) -> Any: display(warning) return None - @property - def data_blob(self) -> BlobRetrieval | SyftError: - """ - Return the blob entry for the data of the asset - """ - api = APIRegistry.api_for( - node_uid=self.node_uid, - user_verify_key=self.syft_client_verify_key, - ) - if api is None or api.services is None: - return SyftError( - message=f"Could not get api for {self.node_uid}. You must login first." - ) - - data_action_obj: str | ActionObject = api.services.action.get(self.action_id) - if isinstance(data_action_obj, str): - return SyftError( - message=f"Could not access private data. {str(data_action_obj)}" - ) - if not self.has_permission(data_action_obj): - return SyftError( - message="You do not have permission to access private data." - ) - - blob_retrieval_res: BlobRetrieval | SyftError = api.services.blob_storage.read( - uid=data_action_obj.syft_blob_storage_entry_id - ) - if isinstance(blob_retrieval_res, SyftError): - return blob_retrieval_res - return blob_retrieval_res - - @property - def mock_blob(self) -> BlobRetrieval | SyftError | None: - """ - Return the blob entry for the mock of the asset - """ - api = APIRegistry.api_for( - node_uid=self.node_uid, - user_verify_key=self.syft_client_verify_key, - ) - if api is None or api.services is None: - return SyftError( - message=f"Could not get api for {self.node_uid}. You must login first." - ) - - mock_action_obj: SyftError | ActionObject = api.services.action.get_mock( - self.action_id - ) - if isinstance(mock_action_obj, SyftError): - return mock_action_obj - - blob_retrieval_res = api.services.blob_storage.read( - uid=mock_action_obj.syft_blob_storage_entry_id - ) - if isinstance(blob_retrieval_res, SyftError): - return blob_retrieval_res - - return blob_retrieval_res - def _is_action_data_empty(obj: Any) -> bool: # just a wrapper of action_object.is_action_data_empty @@ -566,6 +506,7 @@ class Dataset(SyftObject): created_at: DateTime = DateTime.now() uploader: Contributor summary: str | None = None + marked_as_deleted: bool = False __attr_searchable__ = [ "name", @@ -747,9 +688,6 @@ class CreateDataset(Dataset): model_config = ConfigDict(validate_assignment=True, extra="forbid") - def _check_asset_must_contain_mock(self) -> None: - _check_asset_must_contain_mock(self.asset_list) - @field_validator("asset_list") @classmethod def __assets_must_contain_mock( @@ -758,6 +696,13 @@ def __assets_must_contain_mock( _check_asset_must_contain_mock(asset_list) return asset_list + @field_validator("marked_as_deleted") + @classmethod + def __marked_as_deleted_must_be_false(cls, v: bool) -> bool: + if v is True: + raise ValueError("marked_as_deleted must be False") + return v + def set_description(self, description: str) -> None: self.description = MarkdownDescription(text=description) @@ -984,6 +929,7 @@ def createdataset_to_dataset() -> list[Callable]: validate_url, convert_asset, add_current_date, + make_set_default("marked_as_deleted", False), # explicitly set it to False ] @@ -993,6 +939,7 @@ def migrate_dataset_v2_to_v3() -> list[Callable]: make_set_default("summary", None), drop("__repr_attrs__"), make_set_default("__repr_attrs__", ["name", "summary", "url", "created_at"]), + make_set_default("marked_as_deleted", False), ] @@ -1000,7 +947,7 @@ def migrate_dataset_v2_to_v3() -> list[Callable]: def migrate_dataset_v3_to_v2() -> list[Callable]: return [ drop("summary"), - drop("__repr_attrs__"), + drop(["__repr_attrs__", "marked_as_deleted"]), make_set_default("__repr_attrs__", ["name", "url", "created_at"]), ] @@ -1011,6 +958,7 @@ def migrate_create_dataset_v2_to_v3() -> list[Callable]: make_set_default("summary", None), drop("__repr_attrs__"), make_set_default("__repr_attrs__", ["name", "summary", "url"]), + make_set_default("marked_as_deleted", False), ] @@ -1018,7 +966,7 @@ def migrate_create_dataset_v2_to_v3() -> list[Callable]: def migrate_create_dataset_v3_to_v2() -> list[Callable]: return [ drop("summary"), - drop("__repr_attrs__"), + drop(["__repr_attrs__", "marked_as_deleted"]), make_set_default("__repr_attrs__", ["name", "url"]), ] diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index ddd40c8f416..bd2dbf39244 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -202,8 +202,8 @@ def get_assets_by_action_id( ] @service_method( - path="dataset.delete_by_uid", - name="delete_by_uid", + path="dataset.delete", + name="delete", roles=DATA_OWNER_ROLE_LEVEL, warning=HighSideCRUDWarning(confirmation=True), ) From 6290613b95c7246107c63d80bd71c7de3cbf5df9 Mon Sep 17 00:00:00 2001 From: Madhava Jay Date: Tue, 9 Jul 2024 13:33:30 +1000 Subject: [PATCH 022/117] Renamed domain, Domain and DOMAIN to datasite, Datasite and DATASITE - Removed old protocol version versions due to conflict --- .github/workflows/pr-tests-stack.yml | 12 +- README.md | 22 +- ...omain-00.gif => 00-deploy-datasite-00.gif} | Bin ...omain-01.jpg => 00-deploy-datasite-01.jpg} | Bin .../api_reference/syft.client.registry.rst | 2 +- ...node.domain.rst => syft.node.datasite.rst} | 6 +- docs/source/api_reference/syft.node.rst | 2 +- docs/source/deployment/glossary.rst | 34 +- docs/source/getting_started/index.rst | 6 +- docs/source/guides/index.rst | 14 +- .../admin/Custom API + Custom Worker.ipynb | 523 -------- notebooks/api/0.8/00-load-data.ipynb | 48 +- notebooks/api/0.8/01-submit-code.ipynb | 28 +- .../api/0.8/02-review-code-and-approve.ipynb | 18 +- .../03-data-scientist-download-result.ipynb | 18 +- notebooks/api/0.8/04-pytorch-example.ipynb | 28 +- notebooks/api/0.8/05-custom-policy.ipynb | 20 +- .../api/0.8/06-multiple-code-requests.ipynb | 10 +- ...> 07-datasite-register-control-flow.ipynb} | 12 +- notebooks/api/0.8/08-code-version.ipynb | 12 +- notebooks/api/0.8/09-blob-storage.ipynb | 16 +- notebooks/api/0.8/10-container-images.ipynb | 98 +- .../api/0.8/11-container-images-k8s.ipynb | 94 +- .../api/0.8/12-custom-api-endpoint.ipynb | 82 +- ....ipynb => 01-primary-datasite-setup.ipynb} | 0 .../enclave/02-manual-enclave-setup.ipynb | 70 +- ...pynb => 03-secondary-datasite-setup.ipynb} | 0 .../enclave/04-data-scientist-join.ipynb | 96 +- ...review.ipynb => 05-datasites-review.ipynb} | 0 .../enclave/07-audit-project-logs.ipynb | 66 +- ...in.ipynb => 03-configuring-datasite.ipynb} | 0 ...nb => 04-setup-datasite-with-tunnel.ipynb} | 0 .../reverse-tunnel/06-proxy-clients.ipynb | 66 +- .../01-uploading-private-data.ipynb | 4 +- .../data-owner/02-account-management.ipynb | 2 +- .../data-owner/03-messages-and-requests.ipynb | 2 +- .../data-owner/05-syft-services-api.ipynb | 2 +- .../data-scientist/02-finding-datasets.ipynb | 2 +- .../03-working-with-private-datasets.ipynb | 2 +- .../data-scientist/04-syft-functions.ipynb | 8 +- .../05-messaging-and-requests.ipynb | 2 +- .../deployments/01-deploy-python.ipynb | 16 +- .../deployments/02-deploy-container.ipynb | 16 +- .../deployments/03-deploy-k8s-k3d.ipynb | 10 +- .../deployments/07-deploy-devspace.ipynb | 6 +- .../tutorials/hello-syft/01-hello-syft.ipynb | 12 +- .../model-auditing/colab/01-user-log.ipynb | 20 +- .../00-data-owner-upload-data.ipynb | 4 +- .../01-data-scientist-submit-code.ipynb | 6 +- .../02-data-owner-review-approve-code.ipynb | 2 +- .../03-data-scientist-download-results.ipynb | 2 +- .../01-reading-from-a-csv.ipynb | 24 +- ...lecting-data-finding-common-complain.ipynb | 26 +- ...orough-has-the-most-noise-complaints.ipynb | 24 +- ...-weekday-bike-most-groupby-aggregate.ipynb | 20 +- ...ing-dataframes-scraping-weather-data.ipynb | 24 +- ...rations-which-month-was-the-snowiest.ipynb | 20 +- .../07-cleaning-up-messy-data.ipynb | 18 +- .../08-how-to-deal-with-timestamps.ipynb | 20 +- packages/grid/backend/backend.dockerfile | 2 +- packages/grid/backend/grid/core/config.py | 6 +- packages/grid/backend/grid/core/node.py | 6 +- packages/grid/backend/grid/start.sh | 2 +- packages/grid/default.env | 8 +- packages/grid/devspace.yaml | 16 +- packages/grid/frontend/README.md | 2 +- .../src/_routes/(app)/account/+page.svelte | 10 +- .../src/_routes/(app)/config/+page.svelte | 18 +- .../src/_routes/(app)/users/+page.svelte | 2 +- .../(app)/users/[slug]/+page.server.ts | 2 +- .../_routes/(app)/users/[slug]/+page.svelte | 2 +- .../src/_routes/(auth)/login/+page.svelte | 14 +- .../src/_routes/(auth)/signup/+page.svelte | 4 +- .../src/lib/components/AccountSettings.svelte | 4 +- .../Datasets/DatasetListItem.svelte | 2 +- .../Datasets/DatasetNoneFound.svelte | 2 +- ....svelte => DatasiteOnlineIndicator.svelte} | 4 +- .../Navigation/SideNavDOHandbook.svelte | 2 +- .../lib/components/Navigation/TopNav.svelte | 4 +- .../src/lib/components/OnboardingModal.svelte | 36 +- .../components/Users/UserCreateModal.svelte | 10 +- .../lib/components/Users/UserListItem.svelte | 2 +- ...el.svelte => DatasiteMetadataPanel.svelte} | 14 +- packages/grid/frontend/src/lib/utils.ts | 2 +- .../frontend/src/routes/[...all]/+page.svelte | 4 +- .../src/types/{domain => datasite}/dataset.ts | 0 .../types/{domain => datasite}/metadata.ts | 2 +- .../src/types/datasite/onlineIndicator.ts | 1 + .../src/types/{domain => datasite}/syft.ts | 0 .../src/types/{domain => datasite}/users.ts | 0 .../src/types/domain/onlineIndicator.ts | 1 - .../frontend/tests/e2e/metadata-panel.spec.ts | 4 +- ...omain.tunnel.yaml => datasite.tunnel.yaml} | 2 +- .../backend/backend-statefulset.yaml | 2 +- packages/grid/helm/syft/values.yaml | 4 +- packages/grid/quickstart/template.json | 30 +- packages/grid/scripts/helm_upgrade.sh | 6 +- packages/syft/PYPI.md | 22 +- packages/syft/src/syft/__init__.py | 12 +- packages/syft/src/syft/abstract_node.py | 2 +- packages/syft/src/syft/client/api.py | 2 +- packages/syft/src/syft/client/client.py | 12 +- .../{domain_client.py => datasite_client.py} | 4 +- .../syft/src/syft/client/gateway_client.py | 18 +- packages/syft/src/syft/client/registry.py | 86 +- packages/syft/src/syft/client/search.py | 12 +- packages/syft/src/syft/client/syncing.py | 10 +- .../src/syft/node/{domain.py => datasite.py} | 2 +- packages/syft/src/syft/node/node.py | 6 +- packages/syft/src/syft/node/routes.py | 4 +- packages/syft/src/syft/node/server.py | 8 +- packages/syft/src/syft/orchestra.py | 6 +- .../src/syft/protocol/protocol_version.json | 1162 +++++++++++++---- .../src/syft/service/action/action_object.py | 2 +- .../syft/src/syft/service/action/numpy.py | 4 +- .../syft/src/syft/service/code/code_parse.py | 2 +- .../syft/src/syft/service/code/user_code.py | 30 +- .../syft/service/code/user_code_service.py | 4 +- packages/syft/src/syft/service/code/utils.py | 2 +- .../syft/service/metadata/node_metadata.py | 8 +- .../syft/service/network/network_service.py | 2 +- .../service/notification/email_templates.py | 4 +- .../syft/service/notifier/notifier_service.py | 6 +- .../syft/src/syft/service/policy/policy.py | 6 +- .../syft/src/syft/service/request/request.py | 4 +- .../src/syft/service/settings/settings.py | 6 +- .../syft/service/settings/settings_service.py | 2 +- .../syft/src/syft/service/sync/diff_state.py | 4 +- .../syft/src/syft/service/user/user_roles.py | 2 +- .../src/syft/service/user/user_service.py | 2 +- .../src/syft/service/worker/image_registry.py | 8 +- packages/syft/src/syft/util/schema.py | 4 +- packages/syft/tests/conftest.py | 10 +- packages/syft/tests/syft/action_test.py | 28 +- packages/syft/tests/syft/api_test.py | 10 +- .../syft/blob_storage/blob_storage_test.py | 6 +- packages/syft/tests/syft/dataset/fixtures.py | 6 +- packages/syft/tests/syft/eager_test.py | 70 +- packages/syft/tests/syft/grid_url_test.py | 4 +- packages/syft/tests/syft/request/fixtures.py | 6 +- .../tests/syft/request/request_stash_test.py | 22 +- .../syft/service/action/action_object_test.py | 16 +- .../service/action/action_service_test.py | 4 +- .../service/dataset/dataset_service_test.py | 24 +- .../service/sync/sync_resolve_single_test.py | 24 +- .../tests/syft/service_permission_test.py | 20 +- packages/syft/tests/syft/settings/fixtures.py | 4 +- .../syft/settings/settings_service_test.py | 18 +- .../tests/syft/users/local_execution_test.py | 10 +- .../syft/tests/syft/users/user_code_test.py | 96 +- .../syft/tests/syft/users/user_stash_test.py | 73 +- packages/syft/tests/syft/users/user_test.py | 60 +- .../worker_pool/worker_pool_service_test.py | 4 +- scripts/get_k8s_secret_ci.sh | 2 +- scripts/patch_hosts.py | 34 +- tests/integration/conftest.py | 4 +- .../container_workload/blob_storage_test.py | 10 +- .../container_workload/pool_image_test.py | 80 +- .../frontend/frontend_start_test.py | 6 +- tests/integration/local/gateway_local_test.py | 122 +- tests/integration/local/job_test.py | 6 +- tests/integration/local/syft_function_test.py | 6 +- tests/integration/local/twin_api_sync_test.py | 14 +- tests/integration/network/client_test.py | 6 +- tests/integration/network/gateway_test.py | 565 ++++---- tests/integration/orchestra/orchestra_test.py | 4 +- tox.ini | 80 +- 167 files changed, 2517 insertions(+), 2336 deletions(-) rename docs/source/_static/personas-image/data-owner/{00-deploy-domain-00.gif => 00-deploy-datasite-00.gif} (100%) rename docs/source/_static/personas-image/data-owner/{00-deploy-domain-01.jpg => 00-deploy-datasite-01.jpg} (100%) rename docs/source/api_reference/{syft.node.domain.rst => syft.node.datasite.rst} (64%) delete mode 100644 notebooks/admin/Custom API + Custom Worker.ipynb rename notebooks/api/0.8/{07-domain-register-control-flow.ipynb => 07-datasite-register-control-flow.ipynb} (95%) rename notebooks/scenarios/enclave/{01-primary-domain-setup.ipynb => 01-primary-datasite-setup.ipynb} (100%) rename notebooks/scenarios/enclave/{03-secondary-domain-setup.ipynb => 03-secondary-datasite-setup.ipynb} (100%) rename notebooks/scenarios/enclave/{05-domains-review.ipynb => 05-datasites-review.ipynb} (100%) rename notebooks/scenarios/getting-started/{03-configuring-domain.ipynb => 03-configuring-datasite.ipynb} (100%) rename notebooks/scenarios/reverse-tunnel/{04-setup-domain-with-tunnel.ipynb => 04-setup-datasite-with-tunnel.ipynb} (100%) rename packages/grid/frontend/src/lib/components/{DomainOnlineIndicator.svelte => DatasiteOnlineIndicator.svelte} (68%) rename packages/grid/frontend/src/lib/components/authentication/{DomainMetadataPanel.svelte => DatasiteMetadataPanel.svelte} (76%) rename packages/grid/frontend/src/types/{domain => datasite}/dataset.ts (100%) rename packages/grid/frontend/src/types/{domain => datasite}/metadata.ts (88%) create mode 100644 packages/grid/frontend/src/types/datasite/onlineIndicator.ts rename packages/grid/frontend/src/types/{domain => datasite}/syft.ts (100%) rename packages/grid/frontend/src/types/{domain => datasite}/users.ts (100%) delete mode 100644 packages/grid/frontend/src/types/domain/onlineIndicator.ts rename packages/grid/helm/examples/dev/{domain.tunnel.yaml => datasite.tunnel.yaml} (67%) rename packages/syft/src/syft/client/{domain_client.py => datasite_client.py} (99%) rename packages/syft/src/syft/node/{domain.py => datasite.py} (85%) diff --git a/.github/workflows/pr-tests-stack.yml b/.github/workflows/pr-tests-stack.yml index eae0b555c3e..f593ca1c0e7 100644 --- a/.github/workflows/pr-tests-stack.yml +++ b/.github/workflows/pr-tests-stack.yml @@ -252,9 +252,9 @@ jobs: run: | mkdir -p ./k8s-logs kubectl describe all -A --context k3d-test-gateway-1 --namespace syft > ./k8s-logs/test-gateway-1-desc-${{ steps.date.outputs.date }}.txt - kubectl describe all -A --context k3d-test-domain-1 --namespace syft > ./k8s-logs/test-domain-1-desc-${{ steps.date.outputs.date }}.txt + kubectl describe all -A --context k3d-test-datasite-1 --namespace syft > ./k8s-logs/test-datasite-1-desc-${{ steps.date.outputs.date }}.txt kubectl logs -l app.kubernetes.io/name!=random --prefix=true --context k3d-test-gateway-1 --namespace syft > ./k8s-logs/test-gateway-1-logs-${{ steps.date.outputs.date }}.txt - kubectl logs -l app.kubernetes.io/name!=random --prefix=true --context k3d-test-domain-1 --namespace syft > ./k8s-logs/test-domain-1-logs-${{ steps.date.outputs.date }}.txt + kubectl logs -l app.kubernetes.io/name!=random --prefix=true --context k3d-test-datasite-1 --namespace syft > ./k8s-logs/test-datasite-1-logs-${{ steps.date.outputs.date }}.txt ls -la ./k8s-logs - name: Upload logs to GitHub @@ -270,7 +270,7 @@ jobs: run: | export PATH=`pwd`:$PATH k3d cluster delete test-gateway-1 || true - k3d cluster delete test-domain-1 || true + k3d cluster delete test-datasite-1 || true k3d registry delete k3d-registry.localhost || true pr-tests-notebook-k8s: @@ -395,9 +395,9 @@ jobs: run: | mkdir -p ./k8s-logs kubectl describe all -A --context k3d-test-gateway-1 --namespace syft > ./k8s-logs/test-gateway-1-desc-${{ steps.date.outputs.date }}.txt - kubectl describe all -A --context k3d-test-domain-1 --namespace syft > ./k8s-logs/test-domain-1-desc-${{ steps.date.outputs.date }}.txt + kubectl describe all -A --context k3d-test-datasite-1 --namespace syft > ./k8s-logs/test-datasite-1-desc-${{ steps.date.outputs.date }}.txt kubectl logs -l app.kubernetes.io/name!=random --prefix=true --context k3d-test-gateway-1 --namespace syft > ./k8s-logs/test-gateway-1-logs-${{ steps.date.outputs.date }}.txt - kubectl logs -l app.kubernetes.io/name!=random --prefix=true --context k3d-test-domain-1 --namespace syft > ./k8s-logs/test-domain-1-logs-${{ steps.date.outputs.date }}.txt + kubectl logs -l app.kubernetes.io/name!=random --prefix=true --context k3d-test-datasite-1 --namespace syft > ./k8s-logs/test-datasite-1-logs-${{ steps.date.outputs.date }}.txt ls -la ./k8s-logs - name: Upload logs to GitHub @@ -413,5 +413,5 @@ jobs: run: | export PATH=`pwd`:$PATH k3d cluster delete test-gateway-1 || true - k3d cluster delete test-domain-1 || true + k3d cluster delete test-datasite-1 || true k3d registry delete k3d-registry.localhost || true diff --git a/README.md b/README.md index 8c602a27f0f..6c650e86a2c 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ $ pip install -U syft[data_science] import syft as sy sy.requires(">=0.8.6,<0.8.7") node = sy.orchestra.launch( - name="my-domain", + name="my-datasite", port=8080, create_producer=True, n_consumers=1, @@ -36,7 +36,7 @@ node = sy.orchestra.launch( ```bash # or from the command line -$ syft launch --name=my-domain --port=8080 --reset=True +$ syft launch --name=my-datasite --port=8080 --reset=True Starting syft-node server on 0.0.0.0:8080 ``` @@ -46,7 +46,7 @@ Starting syft-node server on 0.0.0.0:8080 ```python import syft as sy sy.requires(">=0.8.6,<0.8.7") -domain_client = sy.login( +datasite_client = sy.login( port=8080, email="info@openmined.org", password="changethis" @@ -64,7 +64,7 @@ domain_client = sy.login( - 04-pytorch-example.ipynb - 05-custom-policy.ipynb - 06-multiple-code-requests.ipynb -- 07-domain-register-control-flow.ipynb +- 07-datasite-register-control-flow.ipynb - 08-code-version.ipynb - 09-blob-storage.ipynb - 10-container-images.ipynb @@ -104,7 +104,7 @@ SYFT_VERSION="" #### 4. Provisioning Helm Charts ```sh -helm install my-domain openmined/syft --version $SYFT_VERSION --namespace syft --create-namespace --set ingress.className="traefik" +helm install my-datasite openmined/syft --version $SYFT_VERSION --namespace syft --create-namespace --set ingress.className="traefik" ``` ### Ingress Controllers @@ -179,9 +179,9 @@ PySyft (Beta): `pip install -U syft --pre` ### Why should I use Syft? -`Syft` allows a `Data Scientist` to ask `questions` about a `dataset` and, within `privacy limits` set by the `data owner`, get `answers` to those `questions`, all without obtaining a `copy` of the data itself. We call this process `Remote Data Science`. It means in a wide variety of `domains` across society, the current `risks` of sharing information (`copying` data) with someone such as, privacy invasion, IP theft and blackmail will no longer prevent the vast `benefits` such as innovation, insights and scientific discovery which secure access will provide. +`Syft` allows a `Data Scientist` to ask `questions` about a `dataset` and, within `privacy limits` set by the `data owner`, get `answers` to those `questions`, all without obtaining a `copy` of the data itself. We call this process `Remote Data Science`. It means in a wide variety of `datasites` across society, the current `risks` of sharing information (`copying` data) with someone such as, privacy invasion, IP theft and blackmail will no longer prevent the vast `benefits` such as innovation, insights and scientific discovery which secure access will provide. -No more cold calls to get `access` to a dataset. No more weeks of `wait times` to get a `result` on your `query`. It also means `1000x more data` in every domain. PySyft opens the doors to a streamlined Data Scientist `workflow`, all with the individual's `privacy` at its heart. +No more cold calls to get `access` to a dataset. No more weeks of `wait times` to get a `result` on your `query`. It also means `1000x more data` in every datasite. PySyft opens the doors to a streamlined Data Scientist `workflow`, all with the individual's `privacy` at its heart. -Provides services to a group of `Data Owners` and `Data Scientists`, such as dataset `search` and bulk `project approval` (legal / technical) to participate in a project. A gateway server acts as a bridge between it's members (`Domains`) and their subscribers (`Data Scientists`) and can provide access to a collection of `domains` at once. +Provides services to a group of `Data Owners` and `Data Scientists`, such as dataset `search` and bulk `project approval` (legal / technical) to participate in a project. A gateway server acts as a bridge between it's members (`Datasites`) and their subscribers (`Data Scientists`) and can provide access to a collection of `datasites` at once. diff --git a/docs/source/_static/personas-image/data-owner/00-deploy-domain-00.gif b/docs/source/_static/personas-image/data-owner/00-deploy-datasite-00.gif similarity index 100% rename from docs/source/_static/personas-image/data-owner/00-deploy-domain-00.gif rename to docs/source/_static/personas-image/data-owner/00-deploy-datasite-00.gif diff --git a/docs/source/_static/personas-image/data-owner/00-deploy-domain-01.jpg b/docs/source/_static/personas-image/data-owner/00-deploy-datasite-01.jpg similarity index 100% rename from docs/source/_static/personas-image/data-owner/00-deploy-domain-01.jpg rename to docs/source/_static/personas-image/data-owner/00-deploy-datasite-01.jpg diff --git a/docs/source/api_reference/syft.client.registry.rst b/docs/source/api_reference/syft.client.registry.rst index 57f0136d312..9b2987bfb78 100644 --- a/docs/source/api_reference/syft.client.registry.rst +++ b/docs/source/api_reference/syft.client.registry.rst @@ -17,7 +17,7 @@ syft.client.registry .. autosummary:: - DomainRegistry + DatasiteRegistry NetworkRegistry diff --git a/docs/source/api_reference/syft.node.domain.rst b/docs/source/api_reference/syft.node.datasite.rst similarity index 64% rename from docs/source/api_reference/syft.node.domain.rst rename to docs/source/api_reference/syft.node.datasite.rst index eb4ff6334a5..bb6b582d067 100644 --- a/docs/source/api_reference/syft.node.domain.rst +++ b/docs/source/api_reference/syft.node.datasite.rst @@ -1,7 +1,7 @@ -syft.node.domain +syft.node.datasite ================ -.. automodule:: syft.node.domain +.. automodule:: syft.node.datasite @@ -17,7 +17,7 @@ syft.node.domain .. autosummary:: - Domain + Datasite diff --git a/docs/source/api_reference/syft.node.rst b/docs/source/api_reference/syft.node.rst index a94e20d906d..d2850a28469 100644 --- a/docs/source/api_reference/syft.node.rst +++ b/docs/source/api_reference/syft.node.rst @@ -28,7 +28,7 @@ :recursive: syft.node.credentials - syft.node.domain + syft.node.datasite syft.node.gateway syft.node.node syft.node.routes diff --git a/docs/source/deployment/glossary.rst b/docs/source/deployment/glossary.rst index a257c3ca4f8..68df75e3c9f 100644 --- a/docs/source/deployment/glossary.rst +++ b/docs/source/deployment/glossary.rst @@ -12,20 +12,20 @@ General terms Data Consortium ~~~~~~~~~~~~~~~~~~~~~ -A legal agreement under which multiple data owners delegate legal authority (IRB authority) to a central party, such that a data scientist need only enter into legal contract with that central party in order to perform analysis across all relevant participating domains in the ``data consortium``. +A legal agreement under which multiple data owners delegate legal authority (IRB authority) to a central party, such that a data scientist need only enter into legal contract with that central party in order to perform analysis across all relevant participating datasites in the ``data consortium``. Differential Privacy ~~~~~~~~~~~~~~~~~~~~~ While the textbook definition can be found here_, within the context of remote data science, ``differential privacy`` is a set of algorithms which empower a data owner to limit the probability that a data scientist will be able to use their statistical results to reverse engineer the data owner's def. of too much information about the underlying data that generated those results. In a nutshell, its aim is to prevent a Data Scientist from identifying any individual from the dataset through reverse-engineering. -Domain Node +Datasite Node ~~~~~~~~~~~~~~~~~~~~~ A ``computer system`` (or collection of computer systems) which manages the remote study of a data owner's data by a data scientist. It is responsible for allowing the `Data Owner` to manage the data, as well as incoming ``requests`` from data scientists and for gatekeeping the data scientist's access to data, compute, and experimental results stored within the data owner's compute infrastructure. Network Node ~~~~~~~~~~~~~~~~~~~~~ -A server which exists outside of any data owner's institution, providing services to the network of data owners and data scientists such as dataset search and bulk project approval (simultaneous legal/technical approval to participate in a project across groups of domains and data scientists at a time). A Network acts as a bridge between between its members and subscribers. The members are ``Domains`` while subscribers are the ``end users`` (e.g. Data Scientist) who explore and perform analysis on the datasets hosted by the members. -A network is used to provide access to a collection of domains at once i.e. if a user agrees to a ``Network Agreement``, then they automatically agree to the conditions to the Domains enlisted in that Network. +A server which exists outside of any data owner's institution, providing services to the network of data owners and data scientists such as dataset search and bulk project approval (simultaneous legal/technical approval to participate in a project across groups of datasites and data scientists at a time). A Network acts as a bridge between between its members and subscribers. The members are ``Datasites`` while subscribers are the ``end users`` (e.g. Data Scientist) who explore and perform analysis on the datasets hosted by the members. +A network is used to provide access to a collection of datasites at once i.e. if a user agrees to a ``Network Agreement``, then they automatically agree to the conditions to the Datasites enlisted in that Network. Privacy Budget ~~~~~~~~~~~~~~~~~~~~~ @@ -54,25 +54,25 @@ Data Owner ~~~~~~~~~~~~~~~~~~~~~ Within the field of remote data science, a data owner is someone who has a (digital) dataset which they would like to make available for study by an outside party whom they may or may not fully trust to have good intentions. -Domain Owner +Datasite Owner ~~~~~~~~~~~~~~~~~~~~~ -A user of ``PyGrid`` who has deployed a domain node. +A user of ``PyGrid`` who has deployed a datasite node. Network Owner ~~~~~~~~~~~~~~~~~~~~~ -Within the field of remote data science, a network owner provides technical and legal services helping to connect data scientists with data owners (domains) by helping them find each other (dataset search) and by helping them enter into bulk legal agreements through the hosting of a network-level data consortium to which such data owners and data scientist may apply. +Within the field of remote data science, a network owner provides technical and legal services helping to connect data scientists with data owners (datasites) by helping them find each other (dataset search) and by helping them enter into bulk legal agreements through the hosting of a network-level data consortium to which such data owners and data scientist may apply. Data Scientist ~~~~~~~~~~~~~~~~~~~~~ -Within the context of remote data science, a data scientist is a persona which desires to answer a specific question using data owned by someone else. This user is required to sign a ``Data Access Agreement`` if you have required one in the ``Domain Settings Configurations``. +Within the context of remote data science, a data scientist is a persona which desires to answer a specific question using data owned by someone else. This user is required to sign a ``Data Access Agreement`` if you have required one in the ``Datasite Settings Configurations``. -Domain Compliance Officer +Datasite Compliance Officer ~~~~~~~~~~~~~~~~~~~~~~~~~~~ All the personas in an institution that are in charge of making sure that the utilization of data at an institution occurs within legal boundaries and under their supervision and with their liability/responsibility. Network Compliance Officer ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -All the personas in an institution that are in charge of making sure that the access and utilization of data between their network's domains and members (data scientists) fall within the bounds outlined in the network's legal agreements. +All the personas in an institution that are in charge of making sure that the access and utilization of data between their network's datasites and members (data scientists) fall within the bounds outlined in the network's legal agreements. User roles ============ @@ -82,7 +82,7 @@ Default roles Data Scientist """""""""""""" -This role is for users who will be performing computations on your datasets. They may be users you know directly or those who found your domain through search and discovery. By default this user can see a ``list of your datasets`` and can request to get results. This user will also be required to sign a ``Data Access Agreement`` if you have required one in the ``Domain Settings Configurations``. +This role is for users who will be performing computations on your datasets. They may be users you know directly or those who found your datasite through search and discovery. By default this user can see a ``list of your datasets`` and can request to get results. This user will also be required to sign a ``Data Access Agreement`` if you have required one in the ``Datasite Settings Configurations``. Default permissions: @@ -90,7 +90,7 @@ Default permissions: Compliance Officer """""""""""""""""""" -This role is for users who will help you manage requests made on your node. They should be users you trust. They are not able to change ``Domain Settings`` or edit roles but they are by default able to accept or deny ``user requests`` on behalf of the ``domain node``. +This role is for users who will help you manage requests made on your node. They should be users you trust. They are not able to change ``Datasite Settings`` or edit roles but they are by default able to accept or deny ``user requests`` on behalf of the ``datasite node``. Default permissions: @@ -100,7 +100,7 @@ Default permissions: Admin """""" -This role is for users who will help you manage your node. This should be users you trust. The main difference between this ``user`` and a ``Compliance Officer`` is that this user by default not only can manage requests but can also edit ``Domain Settings.`` This is the highest level permission outside of an Owner. +This role is for users who will help you manage your node. This should be users you trust. The main difference between this ``user`` and a ``Compliance Officer`` is that this user by default not only can manage requests but can also edit ``Datasite Settings.`` This is the highest level permission outside of an Owner. Default permissions: @@ -108,7 +108,7 @@ Default permissions: Owner """""""" -There is only one Owner account assigned to any one domain node. The owner account is the highest level permission and is a requirement for deploying a domain node. If you should ever want to transfer ownership of your domain node to someone, please contact us at support@openmined.org. +There is only one Owner account assigned to any one datasite node. The owner account is the highest level permission and is a requirement for deploying a datasite node. If you should ever want to transfer ownership of your datasite node to someone, please contact us at support@openmined.org. Default permissions: @@ -116,16 +116,16 @@ Default permissions: * Cannot disable permissions by default -Domain membership roles +Datasite membership roles ~~~~~~~~~~~~~~~~~~~~~~~~~~ Guest """""""""""""" -The lowest level of ``network membership``, a guest domain is listed within a network node's registry and its datasets are searchable/discoverable by all users of the network, but the network has no legal relationship to the domain nor any authority to grant data scientists access to its data. As such, upon discovering a domain on the network, such a data scientist must apply directly to the domain for access by creating an account on such a domain and signing a legal agreement (a "data-sharing agreement") directly with its corresponding data owner. +The lowest level of ``network membership``, a guest datasite is listed within a network node's registry and its datasets are searchable/discoverable by all users of the network, but the network has no legal relationship to the datasite nor any authority to grant data scientists access to its data. As such, upon discovering a datasite on the network, such a data scientist must apply directly to the datasite for access by creating an account on such a datasite and signing a legal agreement (a "data-sharing agreement") directly with its corresponding data owner. Member """""""""""""" -The highest level of ``network membership``, a full domain member is greater than a guest member because, beyond its listing within a network node's registry, the domain has entered into a legal relationship with the network owner such that the network owner can unilaterally give its full data scientists access to data hosted by the domain. Note that this does not mean that the network can control access to all potential users of the ``registered domain``, because the domain's membership in the network is non-exclusive (domains can register in multiple networks and also accept direct data-scientist users on the side). A network node only has authority to give its own full data scientists access to any full domain within its registry. +The highest level of ``network membership``, a full datasite member is greater than a guest member because, beyond its listing within a network node's registry, the datasite has entered into a legal relationship with the network owner such that the network owner can unilaterally give its full data scientists access to data hosted by the datasite. Note that this does not mean that the network can control access to all potential users of the ``registered datasite``, because the datasite's membership in the network is non-exclusive (datasites can register in multiple networks and also accept direct data-scientist users on the side). A network node only has authority to give its own full data scientists access to any full datasite within its registry. .. |image0| image:: ../_static/deployment/image2.png :width: 95% diff --git a/docs/source/getting_started/index.rst b/docs/source/getting_started/index.rst index 4633130e472..c6c7cee9873 100644 --- a/docs/source/getting_started/index.rst +++ b/docs/source/getting_started/index.rst @@ -7,9 +7,9 @@ Getting Started .. toctree:: :maxdepth: 3 -Welcome to the domain deployment installation tutorials! +Welcome to the datasite deployment installation tutorials! This section of our documentation is designed to be the -simplest way to get you started deploying your data to a domain node +simplest way to get you started deploying your data to a datasite node on an OSX, Linux, or Windows machine and interacting with it as a data scientist using PySyft. @@ -20,7 +20,7 @@ as a data scientist using PySyft. `advanced deployment documentation `__. The purpose of these tutorials is to help you install everything -you need to run a Domain node from your personal machine (such +you need to run a Datasite node from your personal machine (such as if you're running through OpenMined `courses `__ or diff --git a/docs/source/guides/index.rst b/docs/source/guides/index.rst index ff7da37d0b1..7f60ef9e966 100644 --- a/docs/source/guides/index.rst +++ b/docs/source/guides/index.rst @@ -34,12 +34,12 @@ an ``outside party`` they may or may not ``fully trust`` has good intentions. You Will Learn ⬇️ """""""""""""""""""" -| :doc:`Part 1: Deploying your own Domain Server ` -| :doc:`Part 2: Uploading Private Data to a Domain Server ` -| :doc:`Part 3: Creating User Accounts on your Domain Server ` +| :doc:`Part 1: Deploying your own Datasite Server ` +| :doc:`Part 2: Uploading Private Data to a Datasite Server ` +| :doc:`Part 3: Creating User Accounts on your Datasite Server ` | :doc:`Part 4: Joining a Network ` | :doc:`Part 5: Creating a Network <04-create-network>` -| :doc:`Part 6: Configuring Privacy Budget on your Domain Server <05-configure-pb>` +| :doc:`Part 6: Configuring Privacy Budget on your Datasite Server <05-configure-pb>` B. Getting Started with Data Scientist 👩🏽‍🔬 @@ -50,9 +50,9 @@ specific ``question`` using one or more data owners' ``datasets``. You Will Learn ⬇️ """""""""""""""""""" -| :doc:`Part 7: Connect to a Domain` -| :doc:`Part 8: Searching for Datasets on the Domain` -| :doc:`Part 9: Exploring a Dataset in the Domain` +| :doc:`Part 7: Connect to a Datasite` +| :doc:`Part 8: Searching for Datasets on the Datasite` +| :doc:`Part 9: Exploring a Dataset in the Datasite` | :doc:`Part 10: Training a Model` | :doc:`Part 11: Retrieving Secure Results <>` diff --git a/notebooks/admin/Custom API + Custom Worker.ipynb b/notebooks/admin/Custom API + Custom Worker.ipynb deleted file mode 100644 index d50c1f1b4f2..00000000000 --- a/notebooks/admin/Custom API + Custom Worker.ipynb +++ /dev/null @@ -1,523 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "0", - "metadata": {}, - "source": [ - "## Custom API + Custom Worker" - ] - }, - { - "cell_type": "markdown", - "id": "1", - "metadata": {}, - "source": [ - "#### Import dependencies" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2", - "metadata": {}, - "outputs": [], - "source": [ - "# syft absolute\n", - "import syft as sy\n", - "from syft.service.settings.settings import NodeSettingsUpdate\n", - "from syft.service.worker.worker_image import SyftWorkerImage" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, - "outputs": [], - "source": [ - "## remote mode\n", - "# os.environ[\"ORCHESTRA_DEPLOYMENT_TYPE\"] = \"remote\"\n", - "# os.environ[\"DEV_MODE\"] = \"True\"\n", - "domain_client = sy.login(\n", - " email=\"info@openmined.org\",\n", - " url=\"http://127.0.0.1\",\n", - " password=\"\",\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4", - "metadata": {}, - "outputs": [], - "source": [ - "# # python mode\n", - "# # !uv pip install google-cloud-bigquery db_dtypes\n", - "# node = sy.orchestra.launch(name=\"test-domain-1\", port=\"auto\", dev_mode=True, reset=True)\n", - "# domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5", - "metadata": {}, - "outputs": [], - "source": [ - "domain_client.worker_pools" - ] - }, - { - "cell_type": "markdown", - "id": "6", - "metadata": {}, - "source": [ - "## Register a custom Image" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", - "metadata": {}, - "outputs": [], - "source": [ - "registry = \"us-central1-docker.pkg.dev/reddit-testing-415005/syft-registry-us\"\n", - "backend_version = None\n", - "assert backend_version is not None\n", - "\n", - "custom_dockerfile_str = f\"\"\"\n", - "FROM {registry}/openmined/grid-backend:{backend_version}\n", - "\n", - "RUN uv pip install google-cloud-bigquery[all]==3.20.1 db-dtypes==1.2.0\n", - "\n", - "\"\"\".strip()\n", - "print(custom_dockerfile_str)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8", - "metadata": {}, - "outputs": [], - "source": [ - "docker_config = sy.DockerWorkerConfig(dockerfile=custom_dockerfile_str)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9", - "metadata": {}, - "outputs": [], - "source": [ - "submit_result = domain_client.api.services.worker_image.submit(\n", - " worker_config=docker_config\n", - ")\n", - "submit_result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "10", - "metadata": {}, - "outputs": [], - "source": [ - "dockerfile_list = domain_client.images.get_all()\n", - "dockerfile_list" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "11", - "metadata": {}, - "outputs": [], - "source": [ - "workerimage = next(\n", - " (\n", - " image\n", - " for image in dockerfile_list\n", - " if not image.is_prebuilt and image.config.dockerfile == custom_dockerfile_str\n", - " ),\n", - " None,\n", - ")\n", - "\n", - "assert isinstance(workerimage, SyftWorkerImage), str(workerimage)\n", - "workerimage" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "12", - "metadata": {}, - "outputs": [], - "source": [ - "external_registry = registry\n", - "worker_docker_tag = \"openmined/bigquery:0.0.1\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "13", - "metadata": {}, - "outputs": [], - "source": [ - "registry_add_result = domain_client.api.services.image_registry.add(external_registry)\n", - "registry_add_result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "14", - "metadata": {}, - "outputs": [], - "source": [ - "registries = domain_client.api.services.image_registry.get_all()\n", - "registry_uid = next((r.id for r in registries if r.url == external_registry), None)\n", - "registry_uid" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "15", - "metadata": {}, - "outputs": [], - "source": [ - "# build with registry_uid\n", - "docker_build_result = domain_client.api.services.worker_image.build(\n", - " image_uid=workerimage.id,\n", - " tag=worker_docker_tag,\n", - " registry_uid=registry_uid,\n", - ")\n", - "print(docker_build_result)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "16", - "metadata": {}, - "outputs": [], - "source": [ - "image_list = domain_client.images.get_all()\n", - "# we can also index with string using the repo_with_tag format\n", - "workerimage = next((image for image in image_list if image.id == workerimage.id), None)\n", - "assert workerimage.is_built is True\n", - "workerimage" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "17", - "metadata": {}, - "outputs": [], - "source": [ - "push_result = domain_client.api.services.worker_image.push(workerimage.id)\n", - "push_result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "18", - "metadata": {}, - "outputs": [], - "source": [ - "worker_pool_name = \"bigquery-pool\"\n", - "domain_client.api.services.worker_pool.launch(\n", - " pool_name=worker_pool_name,\n", - " image_uid=workerimage.id,\n", - " num_workers=1,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "19", - "metadata": {}, - "outputs": [], - "source": [ - "domain_client.worker_pools[1]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "20", - "metadata": {}, - "outputs": [], - "source": [ - "new_default_worker_pool = NodeSettingsUpdate(default_worker_pool=worker_pool_name)\n", - "domain_client.settings.update(settings=new_default_worker_pool)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "21", - "metadata": {}, - "outputs": [], - "source": [ - "SERVICE_ACCOUNT = {}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "22", - "metadata": {}, - "outputs": [], - "source": [ - "# debug manually\n", - "# from google.oauth2 import service_account\n", - "# from google.cloud import bigquery\n", - "# credentials = service_account.Credentials.from_service_account_info(SERVICE_ACCOUNT)\n", - "# scoped_credentials = credentials.with_scopes(['https://www.googleapis.com/auth/bigquery'])\n", - "# scoped_credentials = credentials.with_scopes(['https://www.googleapis.com/auth/cloud-platform'])\n", - "\n", - "# client = bigquery.Client(\n", - "# credentials=scoped_credentials,\n", - "# location=\"us-west1\",\n", - "# )\n", - "# sql=\"SELECT * FROM reddit-testing-415005.test_1gb.accounts limit 10\"\n", - "# rows = client.query_and_wait(\n", - "# sql\n", - "# )\n", - "# g = sy.ActionObject.from_obj(rows)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "23", - "metadata": {}, - "outputs": [], - "source": [ - "@sy.api_endpoint_method(\n", - " settings={\"credentials\": SERVICE_ACCOUNT, \"project_id\": \"reddit-testing-415005\"}\n", - ")\n", - "def public_function(context, sql: str) -> str:\n", - " # third party\n", - " from google.cloud import bigquery\n", - " from google.oauth2 import service_account\n", - "\n", - " credentials = service_account.Credentials.from_service_account_info(\n", - " context.settings[\"credentials\"]\n", - " )\n", - " scoped_credentials = credentials.with_scopes(\n", - " [\"https://www.googleapis.com/auth/bigquery\"]\n", - " )\n", - " scoped_credentials = credentials.with_scopes(\n", - " [\"https://www.googleapis.com/auth/cloud-platform\"]\n", - " )\n", - "\n", - " client = bigquery.Client(\n", - " credentials=scoped_credentials,\n", - " location=\"us-west1\",\n", - " )\n", - "\n", - " rows = client.query_and_wait(\n", - " sql,\n", - " project=context.settings[\"project_id\"],\n", - " )\n", - "\n", - " return rows\n", - "\n", - "\n", - "@sy.api_endpoint_method(\n", - " settings={\"credentials\": SERVICE_ACCOUNT, \"project_id\": \"reddit-testing-415005\"}\n", - ")\n", - "def private_function(context, sql: str) -> str:\n", - " # third party\n", - " from google.cloud import bigquery\n", - " from google.oauth2 import service_account\n", - "\n", - " credentials = service_account.Credentials.from_service_account_info(\n", - " context.settings[\"credentials\"]\n", - " )\n", - " scoped_credentials = credentials.with_scopes(\n", - " [\"https://www.googleapis.com/auth/bigquery\"]\n", - " )\n", - " scoped_credentials = credentials.with_scopes(\n", - " [\"https://www.googleapis.com/auth/cloud-platform\"]\n", - " )\n", - "\n", - " client = bigquery.Client(\n", - " credentials=scoped_credentials,\n", - " location=\"us-west1\",\n", - " )\n", - "\n", - " rows = client.query_and_wait(\n", - " sql,\n", - " project=context.settings[\"project_id\"],\n", - " )\n", - "\n", - " return rows" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "24", - "metadata": {}, - "outputs": [], - "source": [ - "new_endpoint = sy.TwinAPIEndpoint(\n", - " path=\"bigquery.query\",\n", - " mock_function=public_function,\n", - " private_function=private_function,\n", - " description=\"Lore ipsulum ...\",\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "25", - "metadata": {}, - "outputs": [], - "source": [ - "response = domain_client.api.services.api.delete(endpoint_path=\"bigquery.query\")\n", - "response" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "26", - "metadata": {}, - "outputs": [], - "source": [ - "response = domain_client.api.services.api.add(endpoint=new_endpoint)\n", - "response" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "27", - "metadata": {}, - "outputs": [], - "source": [ - "domain_client.refresh()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "28", - "metadata": {}, - "outputs": [], - "source": [ - "@sy.syft_function_single_use(\n", - " endpoint=domain_client.api.services.bigquery.query,\n", - " worker_pool_name=worker_pool_name,\n", - ")\n", - "def job_function(endpoint):\n", - " result = endpoint(\n", - " sql=\"SELECT * FROM reddit-testing-415005.test_1gb.accounts limit 10\"\n", - " )\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "29", - "metadata": {}, - "outputs": [], - "source": [ - "new_project = sy.Project(\n", - " name=\"My Cool UN Project\",\n", - " description=\"Hi, I want to calculate the trade volume in million's with my cool code.\",\n", - " members=[domain_client],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "30", - "metadata": {}, - "outputs": [], - "source": [ - "result = new_project.create_code_request(job_function, domain_client)\n", - "domain_client.requests[-1].approve()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "31", - "metadata": {}, - "outputs": [], - "source": [ - "domain_client.settings.get().default_worker_pool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "32", - "metadata": {}, - "outputs": [], - "source": [ - "job = domain_client.code.job_function(\n", - " endpoint=domain_client.api.services.bigquery.query, blocking=False\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "33", - "metadata": {}, - "outputs": [], - "source": [ - "job" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "34", - "metadata": {}, - "outputs": [], - "source": [ - "domain_client.jobs" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/notebooks/api/0.8/00-load-data.ipynb b/notebooks/api/0.8/00-load-data.ipynb index ad98a5ac361..1b13340871c 100644 --- a/notebooks/api/0.8/00-load-data.ipynb +++ b/notebooks/api/0.8/00-load-data.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Loading data into Syft Domain Server as a Data Owner\n", + "# Loading data into Syft Datasite Server as a Data Owner\n", "\n", "Welcome to Syft! This tutorial consists of 4 Jupyter notebooks that covers the basics of Syft which includes\n", "* [Uploading a private dataset as a Data Owner](./00-load-data.ipynb)\n", @@ -55,7 +55,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Launch a Syft Domain Server" + "### Launch a Syft Datasite Server" ] }, { @@ -66,8 +66,10 @@ }, "outputs": [], "source": [ - "# Launch a fresh domain server named \"test-domain-1\" in dev mode on the local machine\n", - "node = sy.orchestra.launch(name=\"test-domain-1\", port=\"auto\", dev_mode=True, reset=True)" + "# Launch a fresh datasite server named \"test-datasite-1\" in dev mode on the local machine\n", + "node = sy.orchestra.launch(\n", + " name=\"test-datasite-1\", port=\"auto\", dev_mode=True, reset=True\n", + ")" ] }, { @@ -79,7 +81,7 @@ "outputs": [], "source": [ "# log into the node with default root credentials\n", - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -91,7 +93,7 @@ "outputs": [], "source": [ "# List the available API\n", - "domain_client.api" + "datasite_client.api" ] }, { @@ -114,7 +116,7 @@ "outputs": [], "source": [ "# Check for existing Data Subjects\n", - "data_subjects = domain_client.data_subject_registry.get_all()" + "data_subjects = datasite_client.data_subject_registry.get_all()" ] }, { @@ -206,7 +208,7 @@ "outputs": [], "source": [ "# Adds the data subject and all its members to the registry\n", - "response = domain_client.data_subject_registry.add_data_subject(country)\n", + "response = datasite_client.data_subject_registry.add_data_subject(country)\n", "response" ] }, @@ -230,7 +232,7 @@ "outputs": [], "source": [ "# Lets look at the data subjects added to the data\n", - "data_subjects = domain_client.data_subject_registry.get_all()\n", + "data_subjects = datasite_client.data_subject_registry.get_all()\n", "data_subjects" ] }, @@ -375,7 +377,7 @@ "dataset.add_contributor(\n", " name=\"Andrew Trask\",\n", " email=\"andrew@openmined.org\",\n", - " note=\"Andrew runs this domain and prepared the dataset metadata.\",\n", + " note=\"Andrew runs this datasite and prepared the dataset metadata.\",\n", ")\n", "\n", "dataset.add_contributor(\n", @@ -439,7 +441,7 @@ "ctf.add_contributor(\n", " name=\"Andrew Trask\",\n", " email=\"andrew@openmined.org\",\n", - " note=\"Andrew runs this domain and prepared the asset.\",\n", + " note=\"Andrew runs this datasite and prepared the asset.\",\n", ")" ] }, @@ -539,7 +541,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Upload Syft Dataset to Domain Server" + "### Upload Syft Dataset to Datasite Server" ] }, { @@ -550,7 +552,7 @@ }, "outputs": [], "source": [ - "upload_res = domain_client.upload_dataset(dataset)\n", + "upload_res = datasite_client.upload_dataset(dataset)\n", "upload_res" ] }, @@ -569,8 +571,8 @@ "metadata": {}, "outputs": [], "source": [ - "# We can list all the datasets on the Domain Server by invoking the following\n", - "datasets = domain_client.datasets.get_all()\n", + "# We can list all the datasets on the Datasite Server by invoking the following\n", + "datasets = datasite_client.datasets.get_all()\n", "datasets" ] }, @@ -604,7 +606,7 @@ } }, "source": [ - "### Reading the Syft Dataset from Domain Server\n", + "### Reading the Syft Dataset from Datasite Server\n", "\n", "Following the logical hierarchy of `Dataset`, `Asset`, and its variant, we can read the data as follows" ] @@ -618,7 +620,7 @@ "outputs": [], "source": [ "# Reading the mock dataset\n", - "mock = domain_client.datasets[0].assets[0].mock" + "mock = datasite_client.datasets[0].assets[0].mock" ] }, { @@ -642,7 +644,7 @@ "source": [ "# Reading the real dataset\n", "# NOTE: Private data can be accessed by the Data Owners, but NOT the Data Scientists\n", - "real = domain_client.datasets[0].assets[0].data" + "real = datasite_client.datasets[0].assets[0].data" ] }, { @@ -660,12 +662,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Create a new Data Scientist account on the Domain Server\n", + "### Create a new Data Scientist account on the Datasite Server\n", "\n", "Signup is disabled by default.\n", - "An Admin/DO can enable it by `domain_client.settings.allow_guest_signup(enable=True)`\n", + "An Admin/DO can enable it by `datasite_client.settings.allow_guest_signup(enable=True)`\n", "\n", - "Refer to notebook [07-domain-register-control-flow](./07-domain-register-control-flow.ipynb) for more information." + "Refer to notebook [07-datasite-register-control-flow](./07-datasite-register-control-flow.ipynb) for more information." ] }, { @@ -674,7 +676,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.register(\n", + "datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -692,7 +694,7 @@ }, "outputs": [], "source": [ - "# Cleanup local domain server\n", + "# Cleanup local datasite server\n", "if node.node_type.value == \"python\":\n", " node.land()" ] diff --git a/notebooks/api/0.8/01-submit-code.ipynb b/notebooks/api/0.8/01-submit-code.ipynb index 3d360c88b18..7402e37a69b 100644 --- a/notebooks/api/0.8/01-submit-code.ipynb +++ b/notebooks/api/0.8/01-submit-code.ipynb @@ -50,7 +50,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Launch a Syft Domain Server" + "### Launch a Syft Datasite Server" ] }, { @@ -61,8 +61,8 @@ }, "outputs": [], "source": [ - "# Launch and connect to test-domain-1 server we setup in the previous notebook\n", - "node = sy.orchestra.launch(name=\"test-domain-1\", port=\"auto\", dev_mode=True)" + "# Launch and connect to test-datasite-1 server we setup in the previous notebook\n", + "node = sy.orchestra.launch(name=\"test-datasite-1\", port=\"auto\", dev_mode=True)" ] }, { @@ -80,7 +80,7 @@ }, "outputs": [], "source": [ - "guest_domain_client = node.client" + "guest_datasite_client = node.client" ] }, { @@ -92,7 +92,7 @@ "outputs": [], "source": [ "# Print this to see the few commands that are available for the guest client\n", - "guest_domain_client" + "guest_datasite_client" ] }, { @@ -102,14 +102,14 @@ "outputs": [], "source": [ "# This will return the public credentials of the guest client\n", - "guest_credentials = guest_domain_client.credentials" + "guest_credentials = guest_datasite_client.credentials" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Login into the Domain with Data Scientist credentials that we created in [00-load-data.ipynb](./00-load-data.ipynb) notebook" + "Login into the Datasite with Data Scientist credentials that we created in [00-load-data.ipynb](./00-load-data.ipynb) notebook" ] }, { @@ -120,7 +120,7 @@ }, "outputs": [], "source": [ - "jane_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")\n", + "jane_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")\n", "jane_client" ] }, @@ -139,7 +139,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Explore available Syft Datasets in the Domain Node" + "### Explore available Syft Datasets in the Datasite Node" ] }, { @@ -307,7 +307,7 @@ "\n", " aggregate = 0.0\n", " base_lap = dp.m.make_laplace(\n", - " dp.atom_domain(T=float),\n", + " dp.atom_datasite(T=float),\n", " dp.absolute_distance(T=float),\n", " scale=5.0,\n", " )\n", @@ -338,7 +338,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You can validate your code against the mock data, before submitting it to the Domain Server" + "You can validate your code against the mock data, before submitting it to the Datasite Server" ] }, { @@ -409,7 +409,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Submit your code to the Domain Server\n", + "### Submit your code to the Datasite Server\n", "\n", "We start by creating new Syft Project" ] @@ -481,7 +481,7 @@ }, "outputs": [], "source": [ - "# Once we start the project, it will submit the project along with the code request to the Domain Server\n", + "# Once we start the project, it will submit the project along with the code request to the Datasite Server\n", "project = new_project.send()\n", "project" ] @@ -569,7 +569,7 @@ }, "outputs": [], "source": [ - "# Cleanup local domain server\n", + "# Cleanup local datasite server\n", "\n", "if node.node_type.value == \"python\":\n", " node.land()" diff --git a/notebooks/api/0.8/02-review-code-and-approve.ipynb b/notebooks/api/0.8/02-review-code-and-approve.ipynb index cd84910030b..bae19250dbe 100644 --- a/notebooks/api/0.8/02-review-code-and-approve.ipynb +++ b/notebooks/api/0.8/02-review-code-and-approve.ipynb @@ -45,7 +45,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Login to Syft Domain Server" + "### Login to Syft Datasite Server" ] }, { @@ -56,8 +56,8 @@ }, "outputs": [], "source": [ - "# Launch and connect to test-domain-1 server we setup in the previous notebook\n", - "node = sy.orchestra.launch(name=\"test-domain-1\", port=\"auto\", dev_mode=True)" + "# Launch and connect to test-datasite-1 server we setup in the previous notebook\n", + "node = sy.orchestra.launch(name=\"test-datasite-1\", port=\"auto\", dev_mode=True)" ] }, { @@ -69,16 +69,16 @@ "outputs": [], "source": [ "# Log into the node with default root credentials\n", - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Selecting Project in the Syft Domain Server\n", + "### Selecting Project in the Syft Datasite Server\n", "\n", - "Let's see all the projects that are created by Data Scientists in this Domain Server" + "Let's see all the projects that are created by Data Scientists in this Datasite Server" ] }, { @@ -89,7 +89,7 @@ }, "outputs": [], "source": [ - "domain_client.projects" + "datasite_client.projects" ] }, { @@ -101,7 +101,7 @@ "outputs": [], "source": [ "# Select the project you want to work with\n", - "project = domain_client.projects[0]\n", + "project = datasite_client.projects[0]\n", "project" ] }, @@ -471,7 +471,7 @@ }, "outputs": [], "source": [ - "# Cleanup local domain server\n", + "# Cleanup local datasite server\n", "\n", "if node.node_type.value == \"python\":\n", " node.land()" diff --git a/notebooks/api/0.8/03-data-scientist-download-result.ipynb b/notebooks/api/0.8/03-data-scientist-download-result.ipynb index 81ce4f783fc..1e8ce2427f6 100644 --- a/notebooks/api/0.8/03-data-scientist-download-result.ipynb +++ b/notebooks/api/0.8/03-data-scientist-download-result.ipynb @@ -43,7 +43,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Login to Syft Domain Server" + "### Login to Syft Datasite Server" ] }, { @@ -54,7 +54,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"test-domain-1\", dev_mode=True)" + "node = sy.orchestra.launch(name=\"test-datasite-1\", dev_mode=True)" ] }, { @@ -65,7 +65,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "datasite_client = node.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -86,7 +86,7 @@ "outputs": [], "source": [ "# Get the canada_trade_flow asset from the Canada Trade dataset\n", - "asset = domain_client.datasets[0].assets[0]\n", + "asset = datasite_client.datasets[0].assets[0]\n", "asset" ] }, @@ -103,7 +103,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.code.sum_trade_value_mil" + "datasite_client.code.sum_trade_value_mil" ] }, { @@ -121,7 +121,7 @@ }, "outputs": [], "source": [ - "result_pointer = domain_client.code.sum_trade_value_mil(trade_data=asset)\n", + "result_pointer = datasite_client.code.sum_trade_value_mil(trade_data=asset)\n", "result_pointer" ] }, @@ -161,7 +161,7 @@ }, "outputs": [], "source": [ - "ops = domain_client.code[-1].output_policy\n", + "ops = datasite_client.code[-1].output_policy\n", "ops" ] }, @@ -171,7 +171,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.code" + "datasite_client.code" ] }, { @@ -201,7 +201,7 @@ }, "outputs": [], "source": [ - "# Cleanup local domain\n", + "# Cleanup local datasite\n", "\n", "if node.node_type.value == \"python\":\n", " node.land()" diff --git a/notebooks/api/0.8/04-pytorch-example.ipynb b/notebooks/api/0.8/04-pytorch-example.ipynb index 5cbc89ecaea..bd0e6d9f00a 100644 --- a/notebooks/api/0.8/04-pytorch-example.ipynb +++ b/notebooks/api/0.8/04-pytorch-example.ipynb @@ -43,7 +43,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"test-domain-1\", dev_mode=True, reset=True)" + "node = sy.orchestra.launch(name=\"test-datasite-1\", dev_mode=True, reset=True)" ] }, { @@ -55,7 +55,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -128,8 +128,8 @@ }, "outputs": [], "source": [ - "train_domain_obj = train.send(domain_client)\n", - "type(train_domain_obj)" + "train_datasite_obj = train.send(datasite_client)\n", + "type(train_datasite_obj)" ] }, { @@ -139,7 +139,7 @@ "metadata": {}, "outputs": [], "source": [ - "train_domain_obj" + "train_datasite_obj" ] }, { @@ -149,7 +149,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert torch.round(train_domain_obj.syft_action_data.sum()) == 1557" + "assert torch.round(train_datasite_obj.syft_action_data.sum()) == 1557" ] }, { @@ -233,7 +233,7 @@ }, "outputs": [], "source": [ - "weight_domain_obj = w.send(domain_client)" + "weight_datasite_obj = w.send(datasite_client)" ] }, { @@ -246,7 +246,9 @@ "outputs": [], "source": [ "@sy.syft_function(\n", - " input_policy=sy.ExactMatch(weights=weight_domain_obj.id, data=train_domain_obj.id),\n", + " input_policy=sy.ExactMatch(\n", + " weights=weight_datasite_obj.id, data=train_datasite_obj.id\n", + " ),\n", " output_policy=sy.SingleExecutionExactOutput(),\n", ")\n", "def train_mlp(weights, data):\n", @@ -292,7 +294,7 @@ }, "outputs": [], "source": [ - "pointer = train_mlp(weights=weight_domain_obj, data=train_domain_obj)\n", + "pointer = train_mlp(weights=weight_datasite_obj, data=train_datasite_obj)\n", "output = pointer.get()" ] }, @@ -315,7 +317,7 @@ }, "outputs": [], "source": [ - "request = domain_client.code.request_code_execution(train_mlp)\n", + "request = datasite_client.code.request_code_execution(train_mlp)\n", "request" ] }, @@ -340,8 +342,8 @@ }, "outputs": [], "source": [ - "domain_client._api = None\n", - "_ = domain_client.api" + "datasite_client._api = None\n", + "_ = datasite_client.api" ] }, { @@ -353,7 +355,7 @@ }, "outputs": [], "source": [ - "result_ptr = domain_client.code.train_mlp(weights=w.id, data=train.id)" + "result_ptr = datasite_client.code.train_mlp(weights=w.id, data=train.id)" ] }, { diff --git a/notebooks/api/0.8/05-custom-policy.ipynb b/notebooks/api/0.8/05-custom-policy.ipynb index ddd043c6f43..cebbe1fceeb 100644 --- a/notebooks/api/0.8/05-custom-policy.ipynb +++ b/notebooks/api/0.8/05-custom-policy.ipynb @@ -41,7 +41,9 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"test-domain-1\", port=\"auto\", dev_mode=True, reset=True)" + "node = sy.orchestra.launch(\n", + " name=\"test-datasite-1\", port=\"auto\", dev_mode=True, reset=True\n", + ")" ] }, { @@ -53,7 +55,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -63,7 +65,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.register(\n", + "datasite_client.register(\n", " email=\"newuser@openmined.org\", name=\"John Doe\", password=\"pw\", password_verify=\"pw\"\n", ")" ] @@ -231,7 +233,7 @@ "metadata": {}, "outputs": [], "source": [ - "x_pointer = x_pointer.send(domain_client)" + "x_pointer = x_pointer.send(datasite_client)" ] }, { @@ -286,7 +288,7 @@ " root_context = AuthedServiceContext(\n", " node=context.node, credentials=context.node.verify_key\n", " )\n", - " if context.node.node_type == NodeType.DOMAIN:\n", + " if context.node.node_type == NodeType.DATASITE:\n", " for var_name, arg_id in allowed_inputs.items():\n", " kwarg_value = action_service._get(\n", " context=root_context,\n", @@ -313,7 +315,7 @@ " from syft import NodeType\n", " from syft import UID\n", "\n", - " if context.node.node_type == NodeType.DOMAIN:\n", + " if context.node.node_type == NodeType.DATASITE:\n", " node_identity = NodeIdentity(\n", " node_name=context.node.name,\n", " node_id=context.node.id,\n", @@ -383,7 +385,7 @@ " from syft import UID\n", " from syft.client.api import NodeIdentity\n", "\n", - " if context.node.node_type == NodeType.DOMAIN:\n", + " if context.node.node_type == NodeType.DATASITE:\n", " node_identity = NodeIdentity(\n", " node_name=context.node.name,\n", " node_id=context.node.id,\n", @@ -469,7 +471,7 @@ "metadata": {}, "outputs": [], "source": [ - "for request in domain_client.requests:\n", + "for request in datasite_client.requests:\n", " if request.id == request_id:\n", " break" ] @@ -589,7 +591,7 @@ }, "outputs": [], "source": [ - "for code in domain_client.code.get_all():\n", + "for code in datasite_client.code.get_all():\n", " if code.service_func_name == \"func\":\n", " break\n", "print(code.output_policy.state)\n", diff --git a/notebooks/api/0.8/06-multiple-code-requests.ipynb b/notebooks/api/0.8/06-multiple-code-requests.ipynb index a52b5c6b38f..6958dd5d52b 100644 --- a/notebooks/api/0.8/06-multiple-code-requests.ipynb +++ b/notebooks/api/0.8/06-multiple-code-requests.ipynb @@ -41,7 +41,9 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"test-domain-1\", port=\"auto\", reset=True, dev_mode=True)" + "node = sy.orchestra.launch(\n", + " name=\"test-datasite-1\", port=\"auto\", reset=True, dev_mode=True\n", + ")" ] }, { @@ -204,7 +206,7 @@ " # compute sum\n", " res = data.sum()\n", " base_lap = dp.m.make_laplace(\n", - " dp.atom_domain(T=float),\n", + " dp.atom_datasite(T=float),\n", " dp.absolute_distance(T=float),\n", " scale=10.0,\n", " )\n", @@ -305,7 +307,7 @@ " # compute mean\n", " mean = data.mean()\n", " base_lap = dp.m.make_laplace(\n", - " dp.atom_domain(T=float),\n", + " dp.atom_datasite(T=float),\n", " dp.absolute_distance(T=float),\n", " scale=10.0,\n", " )\n", @@ -358,7 +360,7 @@ "metadata": {}, "outputs": [], "source": [ - "# The Domain Owner retrieves by name or uid for approval\n", + "# The Datasite Owner retrieves by name or uid for approval\n", "root_client_project = root_client.projects.get_by_uid(project.id)\n", "assert isinstance(root_client_project, sy.service.project.project.Project)" ] diff --git a/notebooks/api/0.8/07-domain-register-control-flow.ipynb b/notebooks/api/0.8/07-datasite-register-control-flow.ipynb similarity index 95% rename from notebooks/api/0.8/07-domain-register-control-flow.ipynb rename to notebooks/api/0.8/07-datasite-register-control-flow.ipynb index 5bd493a47c9..259ee5a9832 100644 --- a/notebooks/api/0.8/07-domain-register-control-flow.ipynb +++ b/notebooks/api/0.8/07-datasite-register-control-flow.ipynb @@ -5,9 +5,9 @@ "id": "0", "metadata": {}, "source": [ - "# Registering Users in Syft Domain Server\n", + "# Registering Users in Syft Datasite Server\n", "\n", - "By default users are not allowed to create a new account on the Syft Domain Server. This notebook is a tutorial for Data Owners to enable guest signups on their deployments." + "By default users are not allowed to create a new account on the Syft Datasite Server. This notebook is a tutorial for Data Owners to enable guest signups on their deployments." ] }, { @@ -48,7 +48,7 @@ "id": "4", "metadata": {}, "source": [ - "### Launch a Syft Domain Server" + "### Launch a Syft Datasite Server" ] }, { @@ -58,7 +58,9 @@ "metadata": {}, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"test-domain-1\", port=\"auto\", dev_mode=True, reset=True)" + "node = sy.orchestra.launch(\n", + " name=\"test-datasite-1\", port=\"auto\", dev_mode=True, reset=True\n", + ")" ] }, { @@ -329,7 +331,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Cleanup local domain server\n", + "# Cleanup local datasite server\n", "\n", "if node.node_type.value == \"python\":\n", " node.land()" diff --git a/notebooks/api/0.8/08-code-version.ipynb b/notebooks/api/0.8/08-code-version.ipynb index 4168770ca88..d900f749ef2 100644 --- a/notebooks/api/0.8/08-code-version.ipynb +++ b/notebooks/api/0.8/08-code-version.ipynb @@ -41,7 +41,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Launch a Syft Domain Server" + "### Launch a Syft Datasite Server" ] }, { @@ -50,7 +50,7 @@ "metadata": {}, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"test-domain-1\", port=\"auto\", dev_mode=True)" + "node = sy.orchestra.launch(name=\"test-datasite-1\", port=\"auto\", dev_mode=True)" ] }, { @@ -60,14 +60,14 @@ "outputs": [], "source": [ "# log into the node with default root credentials\n", - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Create a new Data Scientist account on the Domain Server\n" + "### Create a new Data Scientist account on the Datasite Server\n" ] }, { @@ -76,7 +76,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.register(\n", + "datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -268,7 +268,7 @@ "metadata": {}, "outputs": [], "source": [ - "# # Cleanup local domain server\n", + "# # Cleanup local datasite server\n", "if node.node_type.value == \"python\":\n", " node.land()" ] diff --git a/notebooks/api/0.8/09-blob-storage.ipynb b/notebooks/api/0.8/09-blob-storage.ipynb index 93491499896..8417c6dd81b 100644 --- a/notebooks/api/0.8/09-blob-storage.ipynb +++ b/notebooks/api/0.8/09-blob-storage.ipynb @@ -34,7 +34,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"test-domain-1\",\n", + " name=\"test-datasite-1\",\n", " dev_mode=True,\n", " reset=True,\n", " create_producer=True,\n", @@ -47,7 +47,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -89,7 +89,7 @@ "metadata": {}, "outputs": [], "source": [ - "data_ptr = domain_client.upload_files([a_file, b_file])" + "data_ptr = datasite_client.upload_files([a_file, b_file])" ] }, { @@ -127,7 +127,7 @@ "metadata": {}, "outputs": [], "source": [ - "lines_file_pptr = domain_client.upload_files(x_file)[0].syft_action_data" + "lines_file_pptr = datasite_client.upload_files(x_file)[0].syft_action_data" ] }, { @@ -169,7 +169,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.upload_dataset(ds)" + "datasite_client.upload_dataset(ds)" ] }, { @@ -219,7 +219,7 @@ "metadata": {}, "outputs": [], "source": [ - "single_data_ptr = domain_client.upload_files(a_file)\n", + "single_data_ptr = datasite_client.upload_files(a_file)\n", "single_data_ptr" ] }, @@ -237,14 +237,14 @@ "outputs": [], "source": [ "if False:\n", - " domain_client.upload_files(\"./path/to/folder\")" + " datasite_client.upload_files(\"./path/to/folder\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Cleanup local domain server" + "#### Cleanup local datasite server" ] }, { diff --git a/notebooks/api/0.8/10-container-images.ipynb b/notebooks/api/0.8/10-container-images.ipynb index 6ce97e012e1..f3412e4def9 100644 --- a/notebooks/api/0.8/10-container-images.ipynb +++ b/notebooks/api/0.8/10-container-images.ipynb @@ -101,8 +101,8 @@ "metadata": {}, "outputs": [], "source": [ - "domain = sy.orchestra.launch(\n", - " name=\"test-domain-1\",\n", + "datasite = sy.orchestra.launch(\n", + " name=\"test-datasite-1\",\n", " dev_mode=True,\n", " create_producer=True,\n", " reset=True,\n", @@ -117,7 +117,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client = domain.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = datasite.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -135,7 +135,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.worker_pools" + "datasite_client.worker_pools" ] }, { @@ -227,7 +227,7 @@ "metadata": {}, "outputs": [], "source": [ - "submit_result = domain_client.api.services.worker_image.submit(\n", + "submit_result = datasite_client.api.services.worker_image.submit(\n", " worker_config=docker_config\n", ")" ] @@ -259,7 +259,7 @@ "metadata": {}, "outputs": [], "source": [ - "dockerfile_list = domain_client.images.get_all()\n", + "dockerfile_list = datasite_client.images.get_all()\n", "dockerfile_list" ] }, @@ -270,7 +270,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert len(domain_client.images.get_all()) == 2" + "assert len(datasite_client.images.get_all()) == 2" ] }, { @@ -314,7 +314,7 @@ "metadata": {}, "outputs": [], "source": [ - "registry_add_result = domain_client.api.services.image_registry.add(\"localhost:5678\")\n", + "registry_add_result = datasite_client.api.services.image_registry.add(\"localhost:5678\")\n", "registry_add_result" ] }, @@ -335,7 +335,7 @@ "metadata": {}, "outputs": [], "source": [ - "images = domain_client.api.services.image_registry.get_all()\n", + "images = datasite_client.api.services.image_registry.get_all()\n", "assert len(images) == 1\n", "images" ] @@ -389,7 +389,7 @@ "source": [ "registry_uid = local_registry.id if running_as_container else local_registry.id\n", "\n", - "docker_build_result = domain_client.api.services.worker_image.build(\n", + "docker_build_result = datasite_client.api.services.worker_image.build(\n", " image_uid=workerimage.id,\n", " tag=docker_tag,\n", " registry_uid=registry_uid,\n", @@ -425,7 +425,7 @@ "metadata": {}, "outputs": [], "source": [ - "image_list = domain_client.images.get_all()\n", + "image_list = datasite_client.images.get_all()\n", "image_list" ] }, @@ -501,7 +501,7 @@ " local_registry_container.start()\n", " sleep(5)\n", "\n", - " push_result = domain_client.api.services.worker_image.push(workerimage.id)\n", + " push_result = datasite_client.api.services.worker_image.push(workerimage.id)\n", " assert isinstance(push_result, sy.SyftSuccess), str(push_result)" ] }, @@ -599,7 +599,7 @@ "outputs": [], "source": [ "worker_pool_name = \"opendp-pool\"\n", - "worker_pool_res = domain_client.api.services.worker_pool.launch(\n", + "worker_pool_res = datasite_client.api.services.worker_pool.launch(\n", " pool_name=worker_pool_name,\n", " image_uid=workerimage.id,\n", " num_workers=2,\n", @@ -638,7 +638,7 @@ "metadata": {}, "outputs": [], "source": [ - "worker_pool_list = domain_client.worker_pools\n", + "worker_pool_list = datasite_client.worker_pools\n", "worker_pool_list" ] }, @@ -649,7 +649,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert len(domain_client.worker_pools.get_all()) == 2\n", + "assert len(datasite_client.worker_pools.get_all()) == 2\n", "worker_pool = None\n", "for pool in worker_pool_list:\n", " if pool.name == worker_pool_name:\n", @@ -667,7 +667,7 @@ "outputs": [], "source": [ "# We can filter pools based on the image id upon which the pools were built\n", - "domain_client.api.services.worker_pool.filter_by_image_id(image_uid=workerimage.id)" + "datasite_client.api.services.worker_pool.filter_by_image_id(image_uid=workerimage.id)" ] }, { @@ -706,7 +706,7 @@ "metadata": {}, "outputs": [], "source": [ - "raw_worker_logs = domain_client.api.services.worker.logs(\n", + "raw_worker_logs = datasite_client.api.services.worker.logs(\n", " uid=second_worker.id,\n", " raw=True,\n", ")\n", @@ -730,7 +730,7 @@ "metadata": {}, "outputs": [], "source": [ - "worker_logs = domain_client.api.services.worker.logs(\n", + "worker_logs = datasite_client.api.services.worker.logs(\n", " uid=second_worker.id,\n", ")\n", "worker_logs" @@ -761,7 +761,7 @@ "metadata": {}, "outputs": [], "source": [ - "worker_delete_res = domain_client.api.services.worker.delete(\n", + "worker_delete_res = datasite_client.api.services.worker.delete(\n", " uid=second_worker.id, force=True\n", ")" ] @@ -795,7 +795,7 @@ "source": [ "# Refetch the worker pool\n", "# Ensure that the deleted worker's id is not present\n", - "for pool in domain_client.api.services.worker_pool.get_all():\n", + "for pool in datasite_client.api.services.worker_pool.get_all():\n", " if pool.name == worker_pool_name:\n", " worker_pool = pool\n", "assert len(worker_pool.workers) == 1\n", @@ -831,7 +831,7 @@ "data = np.array([1, 2, 3])\n", "data_action_obj = sy.ActionObject.from_obj(data)\n", "\n", - "data_pointer = data_action_obj.send(domain_client)\n", + "data_pointer = data_action_obj.send(datasite_client)\n", "data_pointer" ] }, @@ -880,7 +880,7 @@ "metadata": {}, "outputs": [], "source": [ - "request = domain_client.code.request_code_execution(custom_worker_func)\n", + "request = datasite_client.code.request_code_execution(custom_worker_func)\n", "request" ] }, @@ -891,7 +891,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.requests[-1].approve(approve_nested=True)" + "datasite_client.requests[-1].approve(approve_nested=True)" ] }, { @@ -901,7 +901,7 @@ "metadata": {}, "outputs": [], "source": [ - "job = domain_client.code.custom_worker_func(x=data_pointer, blocking=False)\n", + "job = datasite_client.code.custom_worker_func(x=data_pointer, blocking=False)\n", "job" ] }, @@ -912,7 +912,7 @@ "metadata": {}, "outputs": [], "source": [ - "worker_pool = domain_client.worker_pools[worker_pool_name]\n", + "worker_pool = datasite_client.worker_pools[worker_pool_name]\n", "worker_pool" ] }, @@ -943,7 +943,7 @@ "metadata": {}, "outputs": [], "source": [ - "job = domain_client.jobs[-1]\n", + "job = datasite_client.jobs[-1]\n", "job" ] }, @@ -988,7 +988,7 @@ "source": [ "# Once the work is done by the worker, its state is returned to idle again.\n", "consuming_worker_is_now_idle = False\n", - "for worker in domain_client.worker_pools[worker_pool_name].workers:\n", + "for worker in datasite_client.worker_pools[worker_pool_name].workers:\n", " if worker.id == job.job_worker_id:\n", " consuming_worker_is_now_idle = worker.consumer_state.value.lower() == \"idle\"\n", "\n", @@ -1025,7 +1025,7 @@ "source": [ "# delete the remaining workers\n", "for worker in worker_pool.workers:\n", - " res = domain_client.api.services.worker.delete(\n", + " res = datasite_client.api.services.worker.delete(\n", " uid=worker.id,\n", " )\n", " assert isinstance(res, sy.SyftSuccess), str(res)" @@ -1038,7 +1038,7 @@ "metadata": {}, "outputs": [], "source": [ - "delete_res = domain_client.api.services.worker_image.remove(workerimage.id)\n", + "delete_res = datasite_client.api.services.worker_image.remove(workerimage.id)\n", "delete_res" ] }, @@ -1095,7 +1095,7 @@ "metadata": {}, "outputs": [], "source": [ - "submit_result = domain_client.api.services.worker_image.submit(\n", + "submit_result = datasite_client.api.services.worker_image.submit(\n", " worker_config=docker_config_2\n", ")\n", "submit_result" @@ -1108,7 +1108,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.images" + "datasite_client.images" ] }, { @@ -1120,7 +1120,7 @@ "source": [ "# get the image that's not built\n", "workerimage_2 = None\n", - "for im in domain_client.images:\n", + "for im in datasite_client.images:\n", " if im.config == docker_config_2:\n", " workerimage_2 = im" ] @@ -1142,7 +1142,7 @@ "source": [ "docker_tag_2 = \"openmined/custom-worker-opendp:latest\"\n", "\n", - "docker_build_result = domain_client.api.services.worker_image.build(\n", + "docker_build_result = datasite_client.api.services.worker_image.build(\n", " image_uid=workerimage_2.id,\n", " tag=docker_tag_2,\n", " pull=pull,\n", @@ -1158,7 +1158,7 @@ "outputs": [], "source": [ "opendp_pool_name = \"second-opendp-pool\"\n", - "pool_create_request = domain_client.api.services.worker_pool.pool_creation_request(\n", + "pool_create_request = datasite_client.api.services.worker_pool.pool_creation_request(\n", " pool_name=opendp_pool_name, num_workers=2, image_uid=workerimage_2.id\n", ")\n", "pool_create_request" @@ -1203,7 +1203,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.worker_pools[opendp_pool_name]" + "datasite_client.worker_pools[opendp_pool_name]" ] }, { @@ -1213,8 +1213,8 @@ "metadata": {}, "outputs": [], "source": [ - "assert domain_client.worker_pools[opendp_pool_name]\n", - "assert len(domain_client.worker_pools[opendp_pool_name].workers) == 2" + "assert datasite_client.worker_pools[opendp_pool_name]\n", + "assert len(datasite_client.worker_pools[opendp_pool_name].workers) == 2" ] }, { @@ -1225,7 +1225,7 @@ "outputs": [], "source": [ "# default, opendp-pool, second-opendp-pool\n", - "assert len(domain_client.worker_pools.get_all()) == 3" + "assert len(datasite_client.worker_pools.get_all()) == 3" ] }, { @@ -1243,11 +1243,11 @@ "metadata": {}, "outputs": [], "source": [ - "for worker in domain_client.worker_pools[\"second-opendp-pool\"].workers:\n", - " res = domain_client.api.services.worker.delete(uid=worker.id, force=True)\n", + "for worker in datasite_client.worker_pools[\"second-opendp-pool\"].workers:\n", + " res = datasite_client.api.services.worker.delete(uid=worker.id, force=True)\n", " assert isinstance(res, sy.SyftSuccess), str(res)\n", "\n", - "assert len(domain_client.worker_pools[\"second-opendp-pool\"].workers) == 0" + "assert len(datasite_client.worker_pools[\"second-opendp-pool\"].workers) == 0" ] }, { @@ -1265,7 +1265,7 @@ "metadata": {}, "outputs": [], "source": [ - "delete_res = domain_client.api.services.worker_image.remove(workerimage_2.id)\n", + "delete_res = datasite_client.api.services.worker_image.remove(workerimage_2.id)\n", "delete_res" ] }, @@ -1315,7 +1315,7 @@ "source": [ "recordlinkage_pool_name = \"recordlinkage-pool\"\n", "pool_image_create_request = (\n", - " domain_client.api.services.worker_pool.create_image_and_pool_request(\n", + " datasite_client.api.services.worker_pool.create_image_and_pool_request(\n", " pool_name=recordlinkage_pool_name,\n", " num_workers=2,\n", " tag=docker_tag_3,\n", @@ -1370,7 +1370,7 @@ "outputs": [], "source": [ "# Get updated request object and status\n", - "for req in domain_client.requests:\n", + "for req in datasite_client.requests:\n", " if req.id == pool_image_create_request.id:\n", " pool_image_create_request = req\n", "\n", @@ -1387,7 +1387,7 @@ "image_exists = False\n", "recordlinkage_image = None\n", "\n", - "for im in domain_client.images.get_all():\n", + "for im in datasite_client.images.get_all():\n", " if im.image_identifier and im.image_identifier.repo_with_tag == docker_tag_3:\n", " image_exists = True\n", " recordlinkage_image = im\n", @@ -1403,7 +1403,7 @@ "metadata": {}, "outputs": [], "source": [ - "recordlinkage_pool = domain_client.worker_pools[recordlinkage_pool_name]\n", + "recordlinkage_pool = datasite_client.worker_pools[recordlinkage_pool_name]\n", "\n", "assert recordlinkage_pool\n", "assert len(recordlinkage_pool.workers) == 2" @@ -1425,7 +1425,7 @@ "outputs": [], "source": [ "for worker in recordlinkage_pool.workers:\n", - " res = domain_client.api.services.worker.delete(uid=worker.id, force=True)\n", + " res = datasite_client.api.services.worker.delete(uid=worker.id, force=True)\n", " assert isinstance(res, sy.SyftSuccess), str(res)" ] }, @@ -1444,7 +1444,7 @@ "metadata": {}, "outputs": [], "source": [ - "delete_res = domain_client.api.services.worker_image.remove(recordlinkage_image.id)\n", + "delete_res = datasite_client.api.services.worker_image.remove(recordlinkage_image.id)\n", "delete_res" ] }, @@ -1455,7 +1455,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain.land()" + "datasite.land()" ] }, { diff --git a/notebooks/api/0.8/11-container-images-k8s.ipynb b/notebooks/api/0.8/11-container-images-k8s.ipynb index 5b78acff06e..4c731807b44 100644 --- a/notebooks/api/0.8/11-container-images-k8s.ipynb +++ b/notebooks/api/0.8/11-container-images-k8s.ipynb @@ -93,8 +93,8 @@ "metadata": {}, "outputs": [], "source": [ - "domain = sy.orchestra.launch(\n", - " name=\"test-domain-1\",\n", + "datasite = sy.orchestra.launch(\n", + " name=\"test-datasite-1\",\n", " dev_mode=True,\n", ")" ] @@ -106,8 +106,8 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client = domain.login(email=\"info@openmined.org\", password=\"changethis\")\n", - "domain_client" + "datasite_client = datasite.login(email=\"info@openmined.org\", password=\"changethis\")\n", + "datasite_client" ] }, { @@ -133,7 +133,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.worker_pools" + "datasite_client.worker_pools" ] }, { @@ -151,7 +151,7 @@ "metadata": {}, "outputs": [], "source": [ - "result = domain_client.api.services.worker_pool.scale(\n", + "result = datasite_client.api.services.worker_pool.scale(\n", " number=3, pool_name=\"default-pool\"\n", ")\n", "assert not isinstance(result, sy.SyftError), str(result)\n", @@ -165,7 +165,7 @@ "metadata": {}, "outputs": [], "source": [ - "result = domain_client.api.services.worker_pool.get_by_name(pool_name=\"default-pool\")\n", + "result = datasite_client.api.services.worker_pool.get_by_name(pool_name=\"default-pool\")\n", "assert len(result.workers) == 3, str(result.to_dict())\n", "result" ] @@ -199,7 +199,7 @@ "metadata": {}, "outputs": [], "source": [ - "default_pool_scale_res = domain_client.api.services.worker_pool.scale(\n", + "default_pool_scale_res = datasite_client.api.services.worker_pool.scale(\n", " number=1, pool_name=\"default-pool\"\n", ")\n", "assert not isinstance(default_pool_scale_res, sy.SyftError), str(default_pool_scale_res)\n", @@ -213,7 +213,7 @@ "metadata": {}, "outputs": [], "source": [ - "result = domain_client.api.services.worker_pool.get_by_name(pool_name=\"default-pool\")\n", + "result = datasite_client.api.services.worker_pool.get_by_name(pool_name=\"default-pool\")\n", "assert len(result.workers) == 1, str(result.to_dict())\n", "result" ] @@ -225,7 +225,7 @@ "metadata": {}, "outputs": [], "source": [ - "default_worker_pool = domain_client.api.services.worker_pool.get_by_name(\n", + "default_worker_pool = datasite_client.api.services.worker_pool.get_by_name(\n", " pool_name=\"default-pool\"\n", ")\n", "default_worker_pool" @@ -300,7 +300,7 @@ "metadata": {}, "outputs": [], "source": [ - "submit_result = domain_client.api.services.worker_image.submit(\n", + "submit_result = datasite_client.api.services.worker_image.submit(\n", " worker_config=docker_config\n", ")\n", "submit_result" @@ -323,7 +323,7 @@ "metadata": {}, "outputs": [], "source": [ - "dockerfile_list = domain_client.images.get_all()\n", + "dockerfile_list = datasite_client.images.get_all()\n", "dockerfile_list" ] }, @@ -389,7 +389,7 @@ "metadata": {}, "outputs": [], "source": [ - "registry_add_result = domain_client.api.services.image_registry.add(external_registry)\n", + "registry_add_result = datasite_client.api.services.image_registry.add(external_registry)\n", "registry_add_result" ] }, @@ -410,7 +410,7 @@ "metadata": {}, "outputs": [], "source": [ - "image_registry_list = domain_client.api.services.image_registry.get_all()\n", + "image_registry_list = datasite_client.api.services.image_registry.get_all()\n", "image_registry_list" ] }, @@ -474,7 +474,7 @@ "docker_tag = \"openmined/custom-worker:0.7.8\"\n", "\n", "\n", - "docker_build_result = domain_client.api.services.worker_image.build(\n", + "docker_build_result = datasite_client.api.services.worker_image.build(\n", " image_uid=workerimage.id,\n", " tag=docker_tag,\n", " registry_uid=registry_uid,\n", @@ -499,7 +499,7 @@ "metadata": {}, "outputs": [], "source": [ - "image_list = domain_client.images.get_all()\n", + "image_list = datasite_client.images.get_all()\n", "image_list" ] }, @@ -545,7 +545,7 @@ "outputs": [], "source": [ "push_result = None\n", - "push_result = domain_client.api.services.worker_image.push(\n", + "push_result = datasite_client.api.services.worker_image.push(\n", " workerimage.id,\n", " username=external_registry_username,\n", " password=external_registry_password,\n", @@ -603,7 +603,7 @@ "worker_pool_name = \"custom-pool\"\n", "custom_pool_pod_annotations = {\"test-custom-pool\": \"Test annotation for custom pool\"}\n", "custom_pool_pod_labels = {\"test-custom-pool\": \"test_label_for_custom_pool\"}\n", - "worker_pool_res = domain_client.api.services.worker_pool.launch(\n", + "worker_pool_res = datasite_client.api.services.worker_pool.launch(\n", " pool_name=worker_pool_name,\n", " image_uid=workerimage.id,\n", " num_workers=3,\n", @@ -643,7 +643,7 @@ "metadata": {}, "outputs": [], "source": [ - "worker_pool_list = domain_client.worker_pools.get_all()\n", + "worker_pool_list = datasite_client.worker_pools.get_all()\n", "worker_pool_list" ] }, @@ -711,7 +711,7 @@ "outputs": [], "source": [ "# We can filter pools based on the image id upon which the pools were built\n", - "filtered_result = domain_client.api.services.worker_pool.filter_by_image_id(\n", + "filtered_result = datasite_client.api.services.worker_pool.filter_by_image_id(\n", " image_uid=workerimage.id\n", ")\n", "filtered_result" @@ -753,7 +753,7 @@ "metadata": {}, "outputs": [], "source": [ - "worker_logs = domain_client.api.services.worker.logs(\n", + "worker_logs = datasite_client.api.services.worker.logs(\n", " uid=second_worker.id,\n", ")\n", "worker_logs" @@ -797,7 +797,7 @@ "data = np.array([1, 2, 3])\n", "data_action_obj = sy.ActionObject.from_obj(data)\n", "\n", - "data_pointer = data_action_obj.send(domain_client)\n", + "data_pointer = data_action_obj.send(datasite_client)\n", "data_pointer" ] }, @@ -848,7 +848,7 @@ "metadata": {}, "outputs": [], "source": [ - "request = domain_client.code.request_code_execution(custom_worker_func)\n", + "request = datasite_client.code.request_code_execution(custom_worker_func)\n", "request" ] }, @@ -859,7 +859,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.requests[-1].approve(approve_nested=True)" + "datasite_client.requests[-1].approve(approve_nested=True)" ] }, { @@ -869,7 +869,7 @@ "metadata": {}, "outputs": [], "source": [ - "job = domain_client.code.custom_worker_func(x=data_pointer, blocking=False)\n", + "job = datasite_client.code.custom_worker_func(x=data_pointer, blocking=False)\n", "job" ] }, @@ -880,7 +880,7 @@ "metadata": {}, "outputs": [], "source": [ - "worker_pool = domain_client.worker_pools[worker_pool_name]\n", + "worker_pool = datasite_client.worker_pools[worker_pool_name]\n", "worker_pool" ] }, @@ -911,7 +911,7 @@ "metadata": {}, "outputs": [], "source": [ - "job_list = domain_client.jobs.get_by_user_code_id(job.user_code_id)" + "job_list = datasite_client.jobs.get_by_user_code_id(job.user_code_id)" ] }, { @@ -956,7 +956,7 @@ "outputs": [], "source": [ "# Scale Down the workers\n", - "custom_pool_scale_res = domain_client.api.services.worker_pool.scale(\n", + "custom_pool_scale_res = datasite_client.api.services.worker_pool.scale(\n", " number=1, pool_name=worker_pool_name\n", ")\n", "assert not isinstance(custom_pool_scale_res, sy.SyftError), str(custom_pool_scale_res)\n", @@ -970,7 +970,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert len(domain_client.worker_pools[worker_pool_name].worker_list) == 1" + "assert len(datasite_client.worker_pools[worker_pool_name].worker_list) == 1" ] }, { @@ -1005,7 +1005,7 @@ "outputs": [], "source": [ "submit_result = None\n", - "submit_result = domain_client.api.services.worker_image.submit(\n", + "submit_result = datasite_client.api.services.worker_image.submit(\n", " worker_config=docker_config_opendp\n", ")\n", "submit_result" @@ -1028,7 +1028,7 @@ "metadata": {}, "outputs": [], "source": [ - "_images = domain_client.images\n", + "_images = datasite_client.images\n", "assert not isinstance(_images, sy.SyftError), str(_images)" ] }, @@ -1063,7 +1063,7 @@ "source": [ "docker_tag_opendp = \"openmined/custom-worker-opendp:latest\"\n", "\n", - "docker_build_result = domain_client.api.services.worker_image.build(\n", + "docker_build_result = datasite_client.api.services.worker_image.build(\n", " image_uid=workerimage_opendp.id,\n", " tag=docker_tag_opendp,\n", " registry_uid=registry_uid,\n", @@ -1089,7 +1089,7 @@ "metadata": {}, "outputs": [], "source": [ - "_images = domain_client.images\n", + "_images = datasite_client.images\n", "assert not isinstance(_images, sy.SyftError), str(_images)" ] }, @@ -1125,7 +1125,7 @@ "source": [ "# Push OpenDP Image to registry\n", "push_result = None\n", - "push_result = domain_client.api.services.worker_image.push(\n", + "push_result = datasite_client.api.services.worker_image.push(\n", " workerimage_opendp.id,\n", " username=external_registry_username,\n", " password=external_registry_password,\n", @@ -1143,7 +1143,7 @@ "pool_name_opendp = \"opendp-pool\"\n", "opendp_pod_annotations = {\"test-opendp-pool\": \"Test annotation for opendp pool\"}\n", "opendp_pod_labels = {\"test-opendp-pool\": \"test_label_for_opendp_pool\"}\n", - "pool_create_request = domain_client.api.services.worker_pool.pool_creation_request(\n", + "pool_create_request = datasite_client.api.services.worker_pool.pool_creation_request(\n", " pool_name=pool_name_opendp,\n", " num_workers=3,\n", " image_uid=workerimage_opendp.id,\n", @@ -1196,7 +1196,7 @@ "metadata": {}, "outputs": [], "source": [ - "pool_opendp = domain_client.worker_pools[pool_name_opendp]\n", + "pool_opendp = datasite_client.worker_pools[pool_name_opendp]\n", "assert not isinstance(pool_opendp, sy.SyftError), str(pool_opendp)\n", "assert len(pool_opendp.worker_list) == 3" ] @@ -1208,7 +1208,7 @@ "metadata": {}, "outputs": [], "source": [ - "worker_pool_list = domain_client.worker_pools.get_all()\n", + "worker_pool_list = datasite_client.worker_pools.get_all()\n", "\n", "assert not isinstance(worker_pool_list, sy.SyftError), str(worker_pool_list)\n", "assert len(worker_pool_list) == 3" @@ -1251,7 +1251,7 @@ "outputs": [], "source": [ "# Scale Down the workers\n", - "opendp_pool_scale_res = domain_client.api.services.worker_pool.scale(\n", + "opendp_pool_scale_res = datasite_client.api.services.worker_pool.scale(\n", " number=1, pool_name=pool_name_opendp\n", ")\n", "assert not isinstance(opendp_pool_scale_res, sy.SyftError), str(opendp_pool_scale_res)\n", @@ -1265,7 +1265,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert len(domain_client.worker_pools[pool_name_opendp].worker_list) == 1" + "assert len(datasite_client.worker_pools[pool_name_opendp].worker_list) == 1" ] }, { @@ -1308,7 +1308,7 @@ "recordlinkage_pod_labels = {\n", " \"test-recordlinkage-pool\": \"test_label_for_recordlinkage_pool\"\n", "}\n", - "pool_image_create_request = domain_client.api.services.worker_pool.create_image_and_pool_request(\n", + "pool_image_create_request = datasite_client.api.services.worker_pool.create_image_and_pool_request(\n", " pool_name=pool_name_recordlinkage,\n", " num_workers=2,\n", " tag=docker_tag_recordlinkage,\n", @@ -1377,7 +1377,7 @@ "metadata": {}, "outputs": [], "source": [ - "_requests = domain_client.requests\n", + "_requests = datasite_client.requests\n", "assert not isinstance(_requests, sy.SyftError), str(_requests)" ] }, @@ -1430,7 +1430,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.images" + "datasite_client.images" ] }, { @@ -1441,7 +1441,7 @@ "outputs": [], "source": [ "image_exists = False\n", - "for im in domain_client.images.get_all():\n", + "for im in datasite_client.images.get_all():\n", " if (\n", " im.image_identifier\n", " and im.image_identifier.repo_with_tag == docker_tag_recordlinkage\n", @@ -1458,8 +1458,8 @@ "metadata": {}, "outputs": [], "source": [ - "assert domain_client.worker_pools[pool_name_recordlinkage]\n", - "assert len(domain_client.worker_pools[pool_name_recordlinkage].worker_list) == 2" + "assert datasite_client.worker_pools[pool_name_recordlinkage]\n", + "assert len(datasite_client.worker_pools[pool_name_recordlinkage].worker_list) == 2" ] }, { @@ -1470,7 +1470,7 @@ "outputs": [], "source": [ "# Scale down the workers\n", - "recordlinkage_pool_scale_res = domain_client.api.services.worker_pool.scale(\n", + "recordlinkage_pool_scale_res = datasite_client.api.services.worker_pool.scale(\n", " number=1, pool_name=pool_name_recordlinkage\n", ")\n", "assert not isinstance(recordlinkage_pool_scale_res, sy.SyftError), str(\n", @@ -1486,7 +1486,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert len(domain_client.worker_pools[pool_name_recordlinkage].worker_list) == 1" + "assert len(datasite_client.worker_pools[pool_name_recordlinkage].worker_list) == 1" ] } ], diff --git a/notebooks/api/0.8/12-custom-api-endpoint.ipynb b/notebooks/api/0.8/12-custom-api-endpoint.ipynb index 20c269ea286..60078a76342 100644 --- a/notebooks/api/0.8/12-custom-api-endpoint.ipynb +++ b/notebooks/api/0.8/12-custom-api-endpoint.ipynb @@ -29,7 +29,7 @@ "from syft import SyftSuccess\n", "\n", "node = sy.orchestra.launch(\n", - " name=\"test-domain-1\",\n", + " name=\"test-datasite-1\",\n", " dev_mode=True,\n", " create_producer=True,\n", " n_consumers=3,\n", @@ -37,14 +37,14 @@ " port=8081,\n", ")\n", "\n", - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")\n", - "domain_client.register(\n", + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")\n", + "datasite_client.register(\n", " email=\"user@openmined.org\",\n", " password=\"verysecurepassword\",\n", " password_verify=\"verysecurepassword\",\n", " name=\"New User\",\n", ")\n", - "domain_guest = node.login(email=\"user@openmined.org\", password=\"verysecurepassword\")" + "datasite_guest = node.login(email=\"user@openmined.org\", password=\"verysecurepassword\")" ] }, { @@ -74,7 +74,7 @@ "\n", "\n", "# Add it to the node.\n", - "response = domain_client.api.services.api.add(endpoint=public_endpoint_method)\n", + "response = datasite_client.api.services.api.add(endpoint=public_endpoint_method)\n", "response" ] }, @@ -93,7 +93,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.api.services.api.api_endpoints()" + "datasite_client.api.services.api.api_endpoints()" ] }, { @@ -102,7 +102,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert len(domain_client.api.services.api.api_endpoints()) == 1" + "assert len(datasite_client.api.services.api.api_endpoints()) == 1" ] }, { @@ -112,8 +112,8 @@ "outputs": [], "source": [ "# Once api refresh is done, remove this cell\n", - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")\n", - "domain_guest = node.login(email=\"user@openmined.org\", password=\"verysecurepassword\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")\n", + "datasite_guest = node.login(email=\"user@openmined.org\", password=\"verysecurepassword\")" ] }, { @@ -122,7 +122,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert domain_client.api.services.first.query(query=\"SELECT *\")" + "assert datasite_client.api.services.first.query(query=\"SELECT *\")" ] }, { @@ -131,7 +131,7 @@ "metadata": {}, "outputs": [], "source": [ - "result = domain_guest.api.services.first.query(query=\"SELECT *\")\n", + "result = datasite_guest.api.services.first.query(query=\"SELECT *\")\n", "result" ] }, @@ -172,7 +172,7 @@ ")\n", "\n", "# # Add it to the node.\n", - "response = domain_client.api.services.api.add(endpoint=new_endpoint)" + "response = datasite_client.api.services.api.add(endpoint=new_endpoint)" ] }, { @@ -181,7 +181,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.api.services.api.api_endpoints()" + "datasite_client.api.services.api.api_endpoints()" ] }, { @@ -191,7 +191,7 @@ "outputs": [], "source": [ "assert isinstance(response, SyftSuccess)\n", - "assert len(domain_client.api.services.api.api_endpoints()) == 2" + "assert len(datasite_client.api.services.api.api_endpoints()) == 2" ] }, { @@ -201,8 +201,8 @@ "outputs": [], "source": [ "# Once api refresh is done, remove this cell\n", - "domain_client.refresh()\n", - "domain_guest.refresh()" + "datasite_client.refresh()\n", + "datasite_guest.refresh()" ] }, { @@ -211,7 +211,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.api.services.third.query()" + "datasite_client.api.services.third.query()" ] }, { @@ -220,7 +220,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert domain_client.api.services.third.query() == \"Private Function Execution\"" + "assert datasite_client.api.services.third.query() == \"Private Function Execution\"" ] }, { @@ -229,7 +229,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert domain_guest.api.services.third.query() == \"Public Function Execution\"" + "assert datasite_guest.api.services.third.query() == \"Public Function Execution\"" ] }, { @@ -238,7 +238,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_guest.api.services.third.query()" + "datasite_guest.api.services.third.query()" ] }, { @@ -248,7 +248,7 @@ "outputs": [], "source": [ "@sy.syft_function_single_use(\n", - " endpoint=domain_guest.api.services.third.query,\n", + " endpoint=datasite_guest.api.services.third.query,\n", ")\n", "def job_function(endpoint):\n", " return endpoint()\n", @@ -258,10 +258,10 @@ "new_project = sy.Project(\n", " name=\"My Cool UN Project\",\n", " description=\"Hi, I want to calculate the trade volume in million's with my cool code.\",\n", - " members=[domain_guest],\n", + " members=[datasite_guest],\n", ")\n", "\n", - "result = new_project.create_code_request(job_function, domain_guest)\n", + "result = new_project.create_code_request(job_function, datasite_guest)\n", "assert isinstance(result, SyftSuccess)" ] }, @@ -272,7 +272,7 @@ "outputs": [], "source": [ "res = None\n", - "for r in domain_client.requests.get_all():\n", + "for r in datasite_client.requests.get_all():\n", " if r.requesting_user_email == \"user@openmined.org\":\n", " res = r.approve()\n", "assert res is not None, res\n", @@ -285,7 +285,9 @@ "metadata": {}, "outputs": [], "source": [ - "result = domain_guest.code.job_function(endpoint=domain_client.api.services.third.query)\n", + "result = datasite_guest.code.job_function(\n", + " endpoint=datasite_client.api.services.third.query\n", + ")\n", "result" ] }, @@ -295,7 +297,9 @@ "metadata": {}, "outputs": [], "source": [ - "result = domain_guest.code.job_function(endpoint=domain_client.api.services.third.query)\n", + "result = datasite_guest.code.job_function(\n", + " endpoint=datasite_client.api.services.third.query\n", + ")\n", "result" ] }, @@ -305,7 +309,7 @@ "metadata": {}, "outputs": [], "source": [ - "domain_client.api.services.third.query" + "datasite_client.api.services.third.query" ] }, { @@ -314,7 +318,9 @@ "metadata": {}, "outputs": [], "source": [ - "result = domain_guest.code.job_function(endpoint=domain_client.api.services.third.query)\n", + "result = datasite_guest.code.job_function(\n", + " endpoint=datasite_client.api.services.third.query\n", + ")\n", "result" ] }, @@ -342,7 +348,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert isinstance(domain_guest.api.services.third.query.private(), SyftError)" + "assert isinstance(datasite_guest.api.services.third.query.private(), SyftError)" ] }, { @@ -351,7 +357,7 @@ "metadata": {}, "outputs": [], "source": [ - "result = domain_client.api.services.api.delete(endpoint_path=\"third.query\")\n", + "result = datasite_client.api.services.api.delete(endpoint_path=\"third.query\")\n", "assert isinstance(result, SyftSuccess), result" ] }, @@ -361,7 +367,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert len(domain_client.api.services.api.api_endpoints()) == 1" + "assert len(datasite_client.api.services.api.api_endpoints()) == 1" ] }, { @@ -396,7 +402,7 @@ "\n", "\n", "# Add it to the node.\n", - "response = domain_client.api.services.api.add(endpoint=new_public_function)\n", + "response = datasite_client.api.services.api.add(endpoint=new_public_function)\n", "assert isinstance(response, SyftSuccess), response\n", "response" ] @@ -421,7 +427,7 @@ " return \"Updated Public Function Execution\"\n", "\n", "\n", - "response = domain_client.api.services.api.update(\n", + "response = datasite_client.api.services.api.update(\n", " endpoint_path=\"test.update\", mock_function=updated_public_function\n", ")\n", "assert isinstance(response, SyftSuccess), response\n", @@ -448,7 +454,7 @@ " return \"Updated Private Function Execution\"\n", "\n", "\n", - "response = domain_client.api.services.api.update(\n", + "response = datasite_client.api.services.api.update(\n", " endpoint_path=\"test.update\", private_function=updated_private_function\n", ")\n", "assert isinstance(response, SyftSuccess), response\n", @@ -478,7 +484,7 @@ " return \"Updated Private Function Execution\"\n", "\n", "\n", - "response = domain_client.api.services.api.update(\n", + "response = datasite_client.api.services.api.update(\n", " endpoint_path=\"test.update\",\n", " mock_function=new_sig_public_function,\n", " private_function=new_sig_private_function,\n", @@ -510,7 +516,7 @@ "metadata": {}, "outputs": [], "source": [ - "response = domain_client.api.services.api.update(endpoint_path=\"test.update\")\n", + "response = datasite_client.api.services.api.update(endpoint_path=\"test.update\")\n", "assert isinstance(response, SyftError), response" ] }, @@ -532,7 +538,7 @@ " return \"Updated Public Function Execution\"\n", "\n", "\n", - "response = domain_client.api.services.api.update(\n", + "response = datasite_client.api.services.api.update(\n", " endpoint_path=\"test.update\", mock_function=bad_public_function\n", ")\n", "assert isinstance(response, SyftError), response" @@ -551,7 +557,7 @@ "metadata": {}, "outputs": [], "source": [ - "response = domain_client.api.services.api.update(\n", + "response = datasite_client.api.services.api.update(\n", " endpoint_path=\"nonexistent\", mock_function=bad_public_function\n", ")\n", "assert isinstance(response, SyftError), response" diff --git a/notebooks/scenarios/enclave/01-primary-domain-setup.ipynb b/notebooks/scenarios/enclave/01-primary-datasite-setup.ipynb similarity index 100% rename from notebooks/scenarios/enclave/01-primary-domain-setup.ipynb rename to notebooks/scenarios/enclave/01-primary-datasite-setup.ipynb diff --git a/notebooks/scenarios/enclave/02-manual-enclave-setup.ipynb b/notebooks/scenarios/enclave/02-manual-enclave-setup.ipynb index 0f1b68dddf2..616688c5bb1 100644 --- a/notebooks/scenarios/enclave/02-manual-enclave-setup.ipynb +++ b/notebooks/scenarios/enclave/02-manual-enclave-setup.ipynb @@ -1,38 +1,38 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "fac336b0-c1a6-46a0-8133-3a2b0704a2b3", - "metadata": {}, - "outputs": [], - "source": [ - "# -- create enclave node\n", - "# -- attach to primary domain\n", - "# -- phase 2 launch python enclave dynamically instead\n", - "# -- phase 3 run on cloud enclave with k3d (dynamically after)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "fac336b0-c1a6-46a0-8133-3a2b0704a2b3", + "metadata": {}, + "outputs": [], + "source": [ + "# -- create enclave node\n", + "# -- attach to primary datasite\n", + "# -- phase 2 launch python enclave dynamically instead\n", + "# -- phase 3 run on cloud enclave with k3d (dynamically after)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/notebooks/scenarios/enclave/03-secondary-domain-setup.ipynb b/notebooks/scenarios/enclave/03-secondary-datasite-setup.ipynb similarity index 100% rename from notebooks/scenarios/enclave/03-secondary-domain-setup.ipynb rename to notebooks/scenarios/enclave/03-secondary-datasite-setup.ipynb diff --git a/notebooks/scenarios/enclave/04-data-scientist-join.ipynb b/notebooks/scenarios/enclave/04-data-scientist-join.ipynb index d49d09ccbe0..63e381836e9 100644 --- a/notebooks/scenarios/enclave/04-data-scientist-join.ipynb +++ b/notebooks/scenarios/enclave/04-data-scientist-join.ipynb @@ -1,51 +1,51 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "52c96d72-c333-4b5b-8631-caaf3c48e4d0", - "metadata": {}, - "outputs": [], - "source": [ - "# -- connect to domains\n", - "# -- associate domains?\n", - "# -- list enclaves\n", - "# -- find datasets\n", - "# -- execution policies\n", - "# -- phase 2 - add a hf model and custom worker image to execution policy\n", - "# -- phase 3 eager data scientist inference inputs in InputPolicy\n", - "# -- create usercode sum(a, b)\n", - "# -- submit project" - ] + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "52c96d72-c333-4b5b-8631-caaf3c48e4d0", + "metadata": {}, + "outputs": [], + "source": [ + "# -- connect to datasites\n", + "# -- associate datasites?\n", + "# -- list enclaves\n", + "# -- find datasets\n", + "# -- execution policies\n", + "# -- phase 2 - add a hf model and custom worker image to execution policy\n", + "# -- phase 3 eager data scientist inference inputs in InputPolicy\n", + "# -- create usercode sum(a, b)\n", + "# -- submit project" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ebf6dc1-6b71-4c6b-826b-c35018a041e7", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } }, - { - "cell_type": "code", - "execution_count": null, - "id": "0ebf6dc1-6b71-4c6b-826b-c35018a041e7", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/notebooks/scenarios/enclave/05-domains-review.ipynb b/notebooks/scenarios/enclave/05-datasites-review.ipynb similarity index 100% rename from notebooks/scenarios/enclave/05-domains-review.ipynb rename to notebooks/scenarios/enclave/05-datasites-review.ipynb diff --git a/notebooks/scenarios/enclave/07-audit-project-logs.ipynb b/notebooks/scenarios/enclave/07-audit-project-logs.ipynb index 3af993e7572..a044f10c62a 100644 --- a/notebooks/scenarios/enclave/07-audit-project-logs.ipynb +++ b/notebooks/scenarios/enclave/07-audit-project-logs.ipynb @@ -1,36 +1,36 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "c36fced0-3a9d-439f-b237-64a71a1ee3ac", - "metadata": {}, - "outputs": [], - "source": [ - "# -- domain owners view logs from enclave on domain\n", - "# -- step through execution policy at each step who did what" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "c36fced0-3a9d-439f-b237-64a71a1ee3ac", + "metadata": {}, + "outputs": [], + "source": [ + "# -- datasite owners view logs from enclave on datasite\n", + "# -- step through execution policy at each step who did what" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/notebooks/scenarios/getting-started/03-configuring-domain.ipynb b/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb similarity index 100% rename from notebooks/scenarios/getting-started/03-configuring-domain.ipynb rename to notebooks/scenarios/getting-started/03-configuring-datasite.ipynb diff --git a/notebooks/scenarios/reverse-tunnel/04-setup-domain-with-tunnel.ipynb b/notebooks/scenarios/reverse-tunnel/04-setup-datasite-with-tunnel.ipynb similarity index 100% rename from notebooks/scenarios/reverse-tunnel/04-setup-domain-with-tunnel.ipynb rename to notebooks/scenarios/reverse-tunnel/04-setup-datasite-with-tunnel.ipynb diff --git a/notebooks/scenarios/reverse-tunnel/06-proxy-clients.ipynb b/notebooks/scenarios/reverse-tunnel/06-proxy-clients.ipynb index 536dce15404..3c8d070e544 100644 --- a/notebooks/scenarios/reverse-tunnel/06-proxy-clients.ipynb +++ b/notebooks/scenarios/reverse-tunnel/06-proxy-clients.ipynb @@ -1,36 +1,36 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "1c3868bb-a140-451a-ac51-a4fd17bf2ab8", - "metadata": {}, - "outputs": [], - "source": [ - "# -- how to list domains on gateway\n", - "# -- getting a proxy client" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "1c3868bb-a140-451a-ac51-a4fd17bf2ab8", + "metadata": {}, + "outputs": [], + "source": [ + "# -- how to list datasites on gateway\n", + "# -- getting a proxy client" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/notebooks/tutorials/data-owner/01-uploading-private-data.ipynb b/notebooks/tutorials/data-owner/01-uploading-private-data.ipynb index 3a1863c0bdd..b44c31a72ca 100644 --- a/notebooks/tutorials/data-owner/01-uploading-private-data.ipynb +++ b/notebooks/tutorials/data-owner/01-uploading-private-data.ipynb @@ -51,7 +51,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"private-data-example-domain-1\", port=\"auto\", reset=True\n", + " name=\"private-data-example-datasite-1\", port=\"auto\", reset=True\n", ")" ] }, @@ -322,7 +322,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Cleanup local domain server\n", + "# Cleanup local datasite server\n", "if node.node_type.value == \"python\":\n", " node.land()" ] diff --git a/notebooks/tutorials/data-owner/02-account-management.ipynb b/notebooks/tutorials/data-owner/02-account-management.ipynb index a4e64b74698..a7e2ae2e533 100644 --- a/notebooks/tutorials/data-owner/02-account-management.ipynb +++ b/notebooks/tutorials/data-owner/02-account-management.ipynb @@ -49,7 +49,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"account-management-example-domain-1\", port=8041, reset=True\n", + " name=\"account-management-example-datasite-1\", port=8041, reset=True\n", ")" ] }, diff --git a/notebooks/tutorials/data-owner/03-messages-and-requests.ipynb b/notebooks/tutorials/data-owner/03-messages-and-requests.ipynb index c05d6f7d556..3c3c5c189b3 100644 --- a/notebooks/tutorials/data-owner/03-messages-and-requests.ipynb +++ b/notebooks/tutorials/data-owner/03-messages-and-requests.ipynb @@ -49,7 +49,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"messages-requests-example-domain-1-do\", port=7021, reset=True\n", + " name=\"messages-requests-example-datasite-1-do\", port=7021, reset=True\n", ")" ] }, diff --git a/notebooks/tutorials/data-owner/05-syft-services-api.ipynb b/notebooks/tutorials/data-owner/05-syft-services-api.ipynb index 7c3f409105a..98cbac0e43f 100644 --- a/notebooks/tutorials/data-owner/05-syft-services-api.ipynb +++ b/notebooks/tutorials/data-owner/05-syft-services-api.ipynb @@ -57,7 +57,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"services-api-example-domain-1\", port=\"auto\", reset=True\n", + " name=\"services-api-example-datasite-1\", port=\"auto\", reset=True\n", ")" ] }, diff --git a/notebooks/tutorials/data-scientist/02-finding-datasets.ipynb b/notebooks/tutorials/data-scientist/02-finding-datasets.ipynb index 30dcf080d8c..bfae6dbdb2d 100644 --- a/notebooks/tutorials/data-scientist/02-finding-datasets.ipynb +++ b/notebooks/tutorials/data-scientist/02-finding-datasets.ipynb @@ -21,7 +21,7 @@ "id": "2", "metadata": {}, "source": [ - "## Connecting to a Domain" + "## Connecting to a Datasite" ] }, { diff --git a/notebooks/tutorials/data-scientist/03-working-with-private-datasets.ipynb b/notebooks/tutorials/data-scientist/03-working-with-private-datasets.ipynb index acf4ec170df..f8302eaf4e7 100644 --- a/notebooks/tutorials/data-scientist/03-working-with-private-datasets.ipynb +++ b/notebooks/tutorials/data-scientist/03-working-with-private-datasets.ipynb @@ -49,7 +49,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"private-datasets-example-domain-1\", port=8062, reset=True\n", + " name=\"private-datasets-example-datasite-1\", port=8062, reset=True\n", ")" ] }, diff --git a/notebooks/tutorials/data-scientist/04-syft-functions.ipynb b/notebooks/tutorials/data-scientist/04-syft-functions.ipynb index cbee1755a3d..84f4ee15536 100644 --- a/notebooks/tutorials/data-scientist/04-syft-functions.ipynb +++ b/notebooks/tutorials/data-scientist/04-syft-functions.ipynb @@ -49,7 +49,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"syft-functions-example-domain-1\", port=7022, reset=True\n", + " name=\"syft-functions-example-datasite-1\", port=7022, reset=True\n", ")" ] }, @@ -252,7 +252,7 @@ "id": "23", "metadata": {}, "source": [ - "You have probably noticed that in the last example we also specified the output policy. Its purpose has to do with the release of information for a given function and controlling the parameters that this release comes with. For example, if a data owner and a data scientist agree on the content of a function run on a domain and on what private data that can be run on, their work might not be done yet. They might negotiate how many times that function can be run, whether or not the data scientist can have access or what happens before releasing the output (maybe we add some noise like in the case of differential privacy). At the moment we have policies that allow data scientist to ask for a certain amount of runs on function, but the ones you will find most often is `SingleExecutionExactOutput` that ask for a single use on a function. We have used it so much that we came with the `syft_function_single_use` decorator that use by default that output policy. What is also cool is that you can pass the input for an input policy to this decorator to get a shorter version like this:" + "You have probably noticed that in the last example we also specified the output policy. Its purpose has to do with the release of information for a given function and controlling the parameters that this release comes with. For example, if a data owner and a data scientist agree on the content of a function run on a datasite and on what private data that can be run on, their work might not be done yet. They might negotiate how many times that function can be run, whether or not the data scientist can have access or what happens before releasing the output (maybe we add some noise like in the case of differential privacy). At the moment we have policies that allow data scientist to ask for a certain amount of runs on function, but the ones you will find most often is `SingleExecutionExactOutput` that ask for a single use on a function. We have used it so much that we came with the `syft_function_single_use` decorator that use by default that output policy. What is also cool is that you can pass the input for an input policy to this decorator to get a shorter version like this:" ] }, { @@ -435,7 +435,7 @@ "id": "42", "metadata": {}, "source": [ - "Right! Our code was not approved, so we should wait for the review from the data owner. As we also deployed the domain, we will do that quickly here, but for more details on what is happening check the data owner sections under tutorials:" + "Right! Our code was not approved, so we should wait for the review from the data owner. As we also deployed the datasite, we will do that quickly here, but for more details on what is happening check the data owner sections under tutorials:" ] }, { @@ -509,7 +509,7 @@ "id": "50", "metadata": {}, "source": [ - "Notice that the result we see is still `1.0` which looks like the result on the mock data. That is because it actually is! The object returned is an `ActionObject` which here behaves like a pointer for the data on the domain:" + "Notice that the result we see is still `1.0` which looks like the result on the mock data. That is because it actually is! The object returned is an `ActionObject` which here behaves like a pointer for the data on the datasite:" ] }, { diff --git a/notebooks/tutorials/data-scientist/05-messaging-and-requests.ipynb b/notebooks/tutorials/data-scientist/05-messaging-and-requests.ipynb index 5d7ff62fa94..2b3c303473f 100644 --- a/notebooks/tutorials/data-scientist/05-messaging-and-requests.ipynb +++ b/notebooks/tutorials/data-scientist/05-messaging-and-requests.ipynb @@ -49,7 +49,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"messages-requests-example-domain-1-ds\", port=7023, reset=True\n", + " name=\"messages-requests-example-datasite-1-ds\", port=7023, reset=True\n", ")" ] }, diff --git a/notebooks/tutorials/deployments/01-deploy-python.ipynb b/notebooks/tutorials/deployments/01-deploy-python.ipynb index cd80e629126..2a51a5459de 100644 --- a/notebooks/tutorials/deployments/01-deploy-python.ipynb +++ b/notebooks/tutorials/deployments/01-deploy-python.ipynb @@ -59,9 +59,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Working with Python Domain\n", + "## Working with Python Datasite\n", "\n", - "`PySyft` makes it very easy to develop against a domain in a notebook by providing the `sy.orchestra` interface. It allows you to start a domain with a webserver in a notebook in the background, which is a lightweight version of a Domain that would be used in production. You can specify options such as what kind of database you are using, whether you want to use networking and how many processes you want to use. You can launch a Domain by simply executing:" + "`PySyft` makes it very easy to develop against a datasite in a notebook by providing the `sy.orchestra` interface. It allows you to start a datasite with a webserver in a notebook in the background, which is a lightweight version of a Datasite that would be used in production. You can specify options such as what kind of database you are using, whether you want to use networking and how many processes you want to use. You can launch a Datasite by simply executing:" ] }, { @@ -81,7 +81,7 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(\n", - " name=\"dev-mode-example-domain-1\", port=8020, reset=True, dev_mode=True\n", + " name=\"dev-mode-example-datasite-1\", port=8020, reset=True, dev_mode=True\n", ")" ] }, @@ -92,12 +92,12 @@ "If we don't need a webserver (for development this is true in many cases), we can omit the port and instead use\n", "\n", "```python\n", - "node = sy.orchestra.launch(name=\"dev-mode-example-domain-1\", dev_mode=True, reset=True)\n", + "node = sy.orchestra.launch(name=\"dev-mode-example-datasite-1\", dev_mode=True, reset=True)\n", "```\n", "\n", "One of the benefits of not using a port is that you can use a debugger and set breakpoints within api calls. This makes debugging way faster in many cases.\n", "\n", - "Now, we are ready to start using the domain. The domain comes with test login credentials for the admin." + "Now, we are ready to start using the datasite. The datasite comes with test login credentials for the admin." ] }, { @@ -113,7 +113,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Once you are logged in, you are ready to start using the domain, for instance for creating a dataset (this one is empty, just as a example)." + "Once you are logged in, you are ready to start using the datasite, for instance for creating a dataset (this one is empty, just as a example)." ] }, { @@ -130,7 +130,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Lastly to stop or terminate your Domain, we can execute the following command:" + "Lastly to stop or terminate your Datasite, we can execute the following command:" ] }, { @@ -157,7 +157,7 @@ "- [04-pytorch-example.ipynb](../../api/0.8/04-pytorch-example.ipynb)\n", "- [05-custom-policy.ipynb](../../api/0.8/05-custom-policy.ipynb)\n", "- [06-multiple-code-requests.ipynb](../../api/0.8/06-multiple-code-requests.ipynb)\n", - "- [07-domain-register-control-flow.ipynb](../../api/0.8/07-domain-register-control-flow.ipynb)\n", + "- [07-datasite-register-control-flow.ipynb](../../api/0.8/07-datasite-register-control-flow.ipynb)\n", "- [08-code-version.ipynb](../../api/0.8/08-code-version.ipynb)\n", "- [09-blob-storage.ipynb](../../api/0.8/09-blob-storage.ipynb)\n", "- [10-container-images.ipynb](../../api/0.8/10-container-images.ipynb)\n", diff --git a/notebooks/tutorials/deployments/02-deploy-container.ipynb b/notebooks/tutorials/deployments/02-deploy-container.ipynb index a8717135d3f..11114d0434c 100644 --- a/notebooks/tutorials/deployments/02-deploy-container.ipynb +++ b/notebooks/tutorials/deployments/02-deploy-container.ipynb @@ -58,14 +58,14 @@ "source": [ "``` bash\n", "docker run -it \\\n", - " -e NODE_NAME=syft-example-domain-1 \\\n", - " -e NODE_TYPE=domain \\\n", + " -e NODE_NAME=syft-example-datasite-1 \\\n", + " -e NODE_TYPE=datasite \\\n", " -e N_CONSUMERS=1 \\\n", " -e SINGLE_CONTAINER_MODE=true \\\n", " -e CREATE_PRODUCER=true \\\n", " -e INMEMORY_WORKERS=true \\\n", " -p 8080:80 --add-host=host.docker.internal:host-gateway \\\n", - " --name syft-example-domain-1 openmined/grid-backend:$SYFT_VERSION\n", + " --name syft-example-datasite-1 openmined/grid-backend:$SYFT_VERSION\n", "```" ] }, @@ -75,7 +75,7 @@ "source": [ "## Working with the single container deployment\n", "\n", - "PySyft makes it very simple to connect to any existing Syft cluster by providing the `sy.orchestra` interface. You can connect to the domain by executing these steps in your jupyter notebook:" + "PySyft makes it very simple to connect to any existing Syft cluster by providing the `sy.orchestra` interface. You can connect to the datasite by executing these steps in your jupyter notebook:" ] }, { @@ -86,7 +86,7 @@ "# syft absolute\n", "import syft as sy\n", "\n", - "node = sy.orchestra.launch(name=\"syft-example-domain-1\", deploy_to=\"remote\")\n", + "node = sy.orchestra.launch(name=\"syft-example-datasite-1\", deploy_to=\"remote\")\n", "```" ] }, @@ -107,7 +107,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now, we are ready to start using the domain. The domain comes with default login credentials for the admin." + "Now, we are ready to start using the datasite. The datasite comes with default login credentials for the admin." ] }, { @@ -123,7 +123,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Once you are logged in, you are ready to start using the domain, for instance for creating a dataset (this one is empty, just as a example)." + "Once you are logged in, you are ready to start using the datasite, for instance for creating a dataset (this one is empty, just as a example)." ] }, { @@ -151,7 +151,7 @@ "- [04-pytorch-example.ipynb](../../api/0.8/04-pytorch-example.ipynb)\n", "- [05-custom-policy.ipynb](../../api/0.8/05-custom-policy.ipynb)\n", "- [06-multiple-code-requests.ipynb](../../api/0.8/06-multiple-code-requests.ipynb)\n", - "- [07-domain-register-control-flow.ipynb](../../api/0.8/07-domain-register-control-flow.ipynb)\n", + "- [07-datasite-register-control-flow.ipynb](../../api/0.8/07-datasite-register-control-flow.ipynb)\n", "- [08-code-version.ipynb](../../api/0.8/08-code-version.ipynb)\n", "- [09-blob-storage.ipynb](../../api/0.8/09-blob-storage.ipynb)\n", "- [10-container-images.ipynb](../../api/0.8/10-container-images.ipynb)\n", diff --git a/notebooks/tutorials/deployments/03-deploy-k8s-k3d.ipynb b/notebooks/tutorials/deployments/03-deploy-k8s-k3d.ipynb index 3ba644ee5dc..333220966f4 100644 --- a/notebooks/tutorials/deployments/03-deploy-k8s-k3d.ipynb +++ b/notebooks/tutorials/deployments/03-deploy-k8s-k3d.ipynb @@ -104,7 +104,7 @@ "source": [ "## Working with the local Kubernetes deployment\n", "\n", - "PySyft makes it very simple to connect to your existing Syft cluster by providing the `sy.orchestra` interface. You can connect to the domain by executing these steps in your jupyter notebook:" + "PySyft makes it very simple to connect to your existing Syft cluster by providing the `sy.orchestra` interface. You can connect to the datasite by executing these steps in your jupyter notebook:" ] }, { @@ -115,7 +115,7 @@ "# syft absolute\n", "import syft as sy\n", "\n", - "node = sy.orchestra.launch(name=\"syft-example-domain-1\", deploy_to=\"remote\")\n", + "node = sy.orchestra.launch(name=\"syft-example-datasite-1\", deploy_to=\"remote\")\n", "```" ] }, @@ -137,7 +137,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now, we are ready to start using the domain. Since helm is a product grade deployement stack, the domain comes with a randomized password for the default email credentials for the admin. Either run with Step 5 with your custom password or to extract the randomized password using `kubectl`, run the following command (in case you use a custom cluster name in step 1, replace `--context=k3d-$CLUSTER_NAME` appropriately): \n", + "Now, we are ready to start using the datasite. Since helm is a product grade deployement stack, the datasite comes with a randomized password for the default email credentials for the admin. Either run with Step 5 with your custom password or to extract the randomized password using `kubectl`, run the following command (in case you use a custom cluster name in step 1, replace `--context=k3d-$CLUSTER_NAME` appropriately): \n", "\n", "```sh\n", "kubectl --context=k3d-syft get secret backend-secret -n syft -o jsonpath='{.data.defaultRootPassword}' | base64 --decode\n", @@ -164,7 +164,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Once you are logged in, you are ready to start using the domain, for instance for creating a dataset (this one is empty, just as a example)." + "Once you are logged in, you are ready to start using the datasite, for instance for creating a dataset (this one is empty, just as a example)." ] }, { @@ -192,7 +192,7 @@ "- [04-pytorch-example.ipynb](../../api/0.8/04-pytorch-example.ipynb)\n", "- [05-custom-policy.ipynb](../../api/0.8/05-custom-policy.ipynb)\n", "- [06-multiple-code-requests.ipynb](../../api/0.8/06-multiple-code-requests.ipynb)\n", - "- [07-domain-register-control-flow.ipynb](../../api/0.8/07-domain-register-control-flow.ipynb)\n", + "- [07-datasite-register-control-flow.ipynb](../../api/0.8/07-datasite-register-control-flow.ipynb)\n", "- [08-code-version.ipynb](../../api/0.8/08-code-version.ipynb)\n", "- [09-blob-storage.ipynb](../../api/0.8/09-blob-storage.ipynb)\n", "- [10-container-images.ipynb](../../api/0.8/10-container-images.ipynb)\n", diff --git a/notebooks/tutorials/deployments/07-deploy-devspace.ipynb b/notebooks/tutorials/deployments/07-deploy-devspace.ipynb index 29632c99dec..c1f3c5788d1 100644 --- a/notebooks/tutorials/deployments/07-deploy-devspace.ipynb +++ b/notebooks/tutorials/deployments/07-deploy-devspace.ipynb @@ -84,10 +84,10 @@ "\n", "#### Launching Different Node Types\n", "Alternatively, you can also use the following commands to launch different node types:\n", - "* Launching a Domain: `CLUSTER_NAME=testdomain1 CLUSTER_HTTP_PORT=9082 tox -e dev.k8s.launch.domain`\n", + "* Launching a Datasite: `CLUSTER_NAME=testdatasite1 CLUSTER_HTTP_PORT=9082 tox -e dev.k8s.launch.datasite`\n", "* Launching a Gateway: `CLUSTER_NAME=testgateway1 CLUSTER_HTTP_PORT=9081 tox -e dev.k8s.launch.gateway`\n", "* Launching a Enclave: `CLUSTER_NAME=testenclave1 CLUSTER_HTTP_PORT=9083 tox -e dev.k8s.launch.enclave`\n", - "* Launching Nodes with `hotreload` using tox posargs: `tox -e dev.k8s.launch.domain -- hotreload`" + "* Launching Nodes with `hotreload` using tox posargs: `tox -e dev.k8s.launch.datasite -- hotreload`" ] }, { @@ -105,7 +105,7 @@ "- [04-jax-example.ipynb](../../api/0.8/04-jax-example.ipynb)\n", "- [05-custom-policy.ipynb](../../api/0.8/05-custom-policy.ipynb)\n", "- [06-multiple-code-requests.ipynb](../../api/0.8/06-multiple-code-requests.ipynb)\n", - "- [07-domain-register-control-flow.ipynb](../../api/0.8/07-domain-register-control-flow.ipynb)\n", + "- [07-datasite-register-control-flow.ipynb](../../api/0.8/07-datasite-register-control-flow.ipynb)\n", "- [08-code-version.ipynb](../../api/0.8/08-code-version.ipynb)\n", "- [09-blob-storage.ipynb](../../api/0.8/09-blob-storage.ipynb)\n", "- [10-container-images.ipynb](../../api/0.8/10-container-images.ipynb)\n", diff --git a/notebooks/tutorials/hello-syft/01-hello-syft.ipynb b/notebooks/tutorials/hello-syft/01-hello-syft.ipynb index e51018e2be0..2a771031677 100644 --- a/notebooks/tutorials/hello-syft/01-hello-syft.ipynb +++ b/notebooks/tutorials/hello-syft/01-hello-syft.ipynb @@ -94,8 +94,8 @@ "outputs": [], "source": [ "node = sy.orchestra.launch(name=\"hello-syft-usa-server\", port=9000, reset=True)\n", - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")\n", - "root_domain_client.register(\n", + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")\n", + "root_datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"janedoe@caltech.edu\",\n", " password=\"abc123\",\n", @@ -114,7 +114,7 @@ "source": [ "## Data owner - Part 1\n", "\n", - "### Upload Data to Domain" + "### Upload Data to Datasite" ] }, { @@ -162,7 +162,7 @@ " )\n", " ],\n", ")\n", - "root_domain_client.upload_dataset(dataset)" + "root_datasite_client.upload_dataset(dataset)" ] }, { @@ -319,7 +319,7 @@ "metadata": {}, "outputs": [], "source": [ - "root_domain_client.requests" + "root_datasite_client.requests" ] }, { @@ -329,7 +329,7 @@ "metadata": {}, "outputs": [], "source": [ - "request = root_domain_client.requests[0]" + "request = root_datasite_client.requests[0]" ] }, { diff --git a/notebooks/tutorials/model-auditing/colab/01-user-log.ipynb b/notebooks/tutorials/model-auditing/colab/01-user-log.ipynb index 6e1e438c04e..f4fd21c67ec 100644 --- a/notebooks/tutorials/model-auditing/colab/01-user-log.ipynb +++ b/notebooks/tutorials/model-auditing/colab/01-user-log.ipynb @@ -13,7 +13,7 @@ "id": "1", "metadata": {}, "source": [ - "In this tutorial, we show how external parties can audit internal AI systems without accessing them — mitigating privacy, security, and IP costs and risks. **This tutorial uses syft 0.8.2.b0, with a domain setup that does not use networking, to run the tutorial with networking read more in section 1.1.1**\n", + "In this tutorial, we show how external parties can audit internal AI systems without accessing them — mitigating privacy, security, and IP costs and risks. **This tutorial uses syft 0.8.2.b0, with a datasite setup that does not use networking, to run the tutorial with networking read more in section 1.1.1**\n", "\n", "You can read more about this tutorial and the follow up tutorials here on the [blog post](https://blog.openmined.org/)." ] @@ -70,7 +70,7 @@ "id": "6", "metadata": {}, "source": [ - "### Launch PySyft domain server" + "### Launch PySyft datasite server" ] }, { @@ -78,7 +78,7 @@ "id": "7", "metadata": {}, "source": [ - "To start we launch a `PySyft` domain server. This is the backend that stores the private data." + "To start we launch a `PySyft` datasite server. This is the backend that stores the private data." ] }, { @@ -90,7 +90,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"syft-domain\", reset=True)" + "node = sy.orchestra.launch(name=\"syft-datasite\", reset=True)" ] }, { @@ -98,15 +98,15 @@ "id": "9", "metadata": {}, "source": [ - "There are 3 ways to launch a `PySyft` domain\n", + "There are 3 ways to launch a `PySyft` datasite\n", "\n", "**A) From a notebook, with simulated networking \\*\\*THIS NOTEBOOK\\*\\***\n", " - Apart from the network calls, this uses exactly the same code as other setups\n", - " - run orchestra **without a port**: `sy.orchestra.launch(name=\"syft-domain\")`\n", + " - run orchestra **without a port**: `sy.orchestra.launch(name=\"syft-datasite\")`\n", " \n", "**B) From a notebook with networking (also supports docker)**\n", " - This spawns a separate process that starts a uvicorn webserver\n", - " - run orchestra **with a port**:`sy.orchestra.launch(name=\"syft-domain\", port=8080)`\n", + " - run orchestra **with a port**:`sy.orchestra.launch(name=\"syft-datasite\", port=8080)`\n", " \n", "**C) From the command line (supports docker/kubernetes)**\n", " - setup for production\n", @@ -129,7 +129,7 @@ "id": "11", "metadata": {}, "source": [ - "We can now login to our domain using the default admin credentials. In production we would change these." + "We can now login to our datasite using the default admin credentials. In production we would change these." ] }, { @@ -157,7 +157,7 @@ "id": "14", "metadata": {}, "source": [ - "For this tutorial we allow other users to create their own account. New accounts will get limited permissions and will only be able to see the mock version of any datasets we upload to the domain." + "For this tutorial we allow other users to create their own account. New accounts will get limited permissions and will only be able to see the mock version of any datasets we upload to the datasite." ] }, { @@ -223,7 +223,7 @@ "id": "21", "metadata": {}, "source": [ - "To upload our dataset to the domain we need to wrap it in a `Syft Dataset` object. We can add some metadata to the object." + "To upload our dataset to the datasite we need to wrap it in a `Syft Dataset` object. We can add some metadata to the object." ] }, { diff --git a/notebooks/tutorials/model-training/00-data-owner-upload-data.ipynb b/notebooks/tutorials/model-training/00-data-owner-upload-data.ipynb index 10287b41fe5..4f7c17a37b3 100644 --- a/notebooks/tutorials/model-training/00-data-owner-upload-data.ipynb +++ b/notebooks/tutorials/model-training/00-data-owner-upload-data.ipynb @@ -26,7 +26,7 @@ "id": "1", "metadata": {}, "source": [ - "## 1. Launch the domain, upload the data" + "## 1. Launch the datasite, upload the data" ] }, { @@ -36,7 +36,7 @@ "metadata": {}, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"mnist-torch-domain\", dev_mode=True, reset=True)\n", + "node = sy.orchestra.launch(name=\"mnist-torch-datasite\", dev_mode=True, reset=True)\n", "root_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, diff --git a/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb b/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb index 7b65d033cbc..ded7a2fbdd5 100644 --- a/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb +++ b/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb @@ -20,7 +20,7 @@ "id": "1", "metadata": {}, "source": [ - "## 1. DS logins to the domain with the credentials created by the DO" + "## 1. DS logins to the datasite with the credentials created by the DO" ] }, { @@ -30,7 +30,7 @@ "metadata": {}, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"mnist-torch-domain\", dev_mode=True)\n", + "node = sy.orchestra.launch(name=\"mnist-torch-datasite\", dev_mode=True)\n", "ds_client = node.login(email=\"sheldon@caltech.edu\", password=\"changethis\")" ] }, @@ -39,7 +39,7 @@ "id": "3", "metadata": {}, "source": [ - "### Inspect the datasets on the domain" + "### Inspect the datasets on the datasite" ] }, { diff --git a/notebooks/tutorials/model-training/02-data-owner-review-approve-code.ipynb b/notebooks/tutorials/model-training/02-data-owner-review-approve-code.ipynb index d4a9c70cc5e..ad4294e82f6 100644 --- a/notebooks/tutorials/model-training/02-data-owner-review-approve-code.ipynb +++ b/notebooks/tutorials/model-training/02-data-owner-review-approve-code.ipynb @@ -21,7 +21,7 @@ "metadata": {}, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"mnist-torch-domain\", dev_mode=True)\n", + "node = sy.orchestra.launch(name=\"mnist-torch-datasite\", dev_mode=True)\n", "root_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, diff --git a/notebooks/tutorials/model-training/03-data-scientist-download-results.ipynb b/notebooks/tutorials/model-training/03-data-scientist-download-results.ipynb index de5c4270d2e..7305f29ce96 100644 --- a/notebooks/tutorials/model-training/03-data-scientist-download-results.ipynb +++ b/notebooks/tutorials/model-training/03-data-scientist-download-results.ipynb @@ -22,7 +22,7 @@ "metadata": {}, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"mnist-torch-domain\", dev_mode=True)\n", + "node = sy.orchestra.launch(name=\"mnist-torch-datasite\", dev_mode=True)\n", "ds_client = node.login(email=\"sheldon@caltech.edu\", password=\"changethis\")" ] }, diff --git a/notebooks/tutorials/pandas-cookbook/01-reading-from-a-csv.ipynb b/notebooks/tutorials/pandas-cookbook/01-reading-from-a-csv.ipynb index 368d7090d57..fd8e8d1aa49 100644 --- a/notebooks/tutorials/pandas-cookbook/01-reading-from-a-csv.ipynb +++ b/notebooks/tutorials/pandas-cookbook/01-reading-from-a-csv.ipynb @@ -54,7 +54,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"pandas-test-domain-1\", port=7081, reset=True)" + "node = sy.orchestra.launch(name=\"pandas-test-datasite-1\", port=7081, reset=True)" ] }, { @@ -74,7 +74,7 @@ }, "outputs": [], "source": [ - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -256,7 +256,7 @@ " name=\"test\",\n", " asset_list=[sy.Asset(name=\"bikes\", data=fixed_df, mock=mock, mock_is_real=False)],\n", ")\n", - "root_domain_client.upload_dataset(dataset)" + "root_datasite_client.upload_dataset(dataset)" ] }, { @@ -276,7 +276,7 @@ }, "outputs": [], "source": [ - "user = root_domain_client.register(\n", + "user = root_datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -307,7 +307,7 @@ }, "outputs": [], "source": [ - "guest_domain_client = node.client" + "guest_datasite_client = node.client" ] }, { @@ -319,7 +319,7 @@ }, "outputs": [], "source": [ - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -355,8 +355,8 @@ }, "outputs": [], "source": [ - "guest_domain_client = node.client\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_datasite_client = node.client\n", + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -368,7 +368,7 @@ }, "outputs": [], "source": [ - "ds = guest_domain_client.datasets[0]" + "ds = guest_datasite_client.datasets[0]" ] }, { @@ -632,7 +632,7 @@ }, "outputs": [], "source": [ - "domain_client = node.client.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.client.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -644,7 +644,7 @@ }, "outputs": [], "source": [ - "notifications = domain_client.notifications.get_all_unread()" + "notifications = datasite_client.notifications.get_all_unread()" ] }, { @@ -750,7 +750,7 @@ }, "outputs": [], "source": [ - "real_data = domain_client.datasets[0].assets[0].data" + "real_data = datasite_client.datasets[0].assets[0].data" ] }, { diff --git a/notebooks/tutorials/pandas-cookbook/02-selecting-data-finding-common-complain.ipynb b/notebooks/tutorials/pandas-cookbook/02-selecting-data-finding-common-complain.ipynb index c7a8d83c7f6..ad7df40b144 100644 --- a/notebooks/tutorials/pandas-cookbook/02-selecting-data-finding-common-complain.ipynb +++ b/notebooks/tutorials/pandas-cookbook/02-selecting-data-finding-common-complain.ipynb @@ -54,7 +54,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"pandas-test-domain-2\", port=9082, reset=True)" + "node = sy.orchestra.launch(name=\"pandas-test-datasite-2\", port=9082, reset=True)" ] }, { @@ -74,7 +74,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -340,7 +340,7 @@ " sy.Asset(name=\"complaints\", data=complaints, mock=mock, mock_is_real=False)\n", " ],\n", ")\n", - "domain_client.upload_dataset(dataset)" + "datasite_client.upload_dataset(dataset)" ] }, { @@ -360,7 +360,7 @@ }, "outputs": [], "source": [ - "user = domain_client.register(\n", + "user = datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -371,9 +371,9 @@ "\n", "# todo: give user data scientist role\n", "\n", - "guest_domain_client = node.client\n", + "guest_datasite_client = node.client\n", "\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -409,7 +409,7 @@ }, "outputs": [], "source": [ - "guest_domain_client = node.client" + "guest_datasite_client = node.client" ] }, { @@ -421,8 +421,8 @@ }, "outputs": [], "source": [ - "# guest_domain_client = worker.guest_client\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "# guest_datasite_client = worker.guest_client\n", + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -434,7 +434,7 @@ }, "outputs": [], "source": [ - "ds = guest_domain_client.datasets[0]" + "ds = guest_datasite_client.datasets[0]" ] }, { @@ -830,7 +830,7 @@ }, "outputs": [], "source": [ - "domain_client = node.client.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.client.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -850,7 +850,7 @@ }, "outputs": [], "source": [ - "notifications = domain_client.notifications.get_all_unread()" + "notifications = datasite_client.notifications.get_all_unread()" ] }, { @@ -925,7 +925,7 @@ }, "outputs": [], "source": [ - "real_data = domain_client.datasets[0].assets[0].data" + "real_data = datasite_client.datasets[0].assets[0].data" ] }, { diff --git a/notebooks/tutorials/pandas-cookbook/03-which-borough-has-the-most-noise-complaints.ipynb b/notebooks/tutorials/pandas-cookbook/03-which-borough-has-the-most-noise-complaints.ipynb index 407f6507c3a..191d23fbae3 100644 --- a/notebooks/tutorials/pandas-cookbook/03-which-borough-has-the-most-noise-complaints.ipynb +++ b/notebooks/tutorials/pandas-cookbook/03-which-borough-has-the-most-noise-complaints.ipynb @@ -57,7 +57,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"pandas-test-domain-3\", port=7083, reset=True)" + "node = sy.orchestra.launch(name=\"pandas-test-datasite-3\", port=7083, reset=True)" ] }, { @@ -77,7 +77,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -355,7 +355,7 @@ " sy.Asset(name=\"complaints\", data=complaints, mock=mock, mock_is_real=False)\n", " ],\n", ")\n", - "domain_client.upload_dataset(dataset)" + "datasite_client.upload_dataset(dataset)" ] }, { @@ -375,7 +375,7 @@ }, "outputs": [], "source": [ - "user = domain_client.register(\n", + "user = datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -386,9 +386,9 @@ "\n", "# todo: give user data scientist role\n", "\n", - "guest_domain_client = node.client\n", + "guest_datasite_client = node.client\n", "\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -424,8 +424,8 @@ }, "outputs": [], "source": [ - "guest_domain_client = node.client\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_datasite_client = node.client\n", + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -437,7 +437,7 @@ }, "outputs": [], "source": [ - "ds = guest_domain_client.datasets[0]" + "ds = guest_datasite_client.datasets[0]" ] }, { @@ -955,7 +955,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -967,7 +967,7 @@ }, "outputs": [], "source": [ - "notifications = domain_client.notifications.get_all_unread()" + "notifications = datasite_client.notifications.get_all_unread()" ] }, { @@ -1042,7 +1042,7 @@ }, "outputs": [], "source": [ - "real_data = domain_client.datasets[0].assets[0].data" + "real_data = datasite_client.datasets[0].assets[0].data" ] }, { diff --git a/notebooks/tutorials/pandas-cookbook/04-weekday-bike-most-groupby-aggregate.ipynb b/notebooks/tutorials/pandas-cookbook/04-weekday-bike-most-groupby-aggregate.ipynb index daed660972d..393606c49a2 100644 --- a/notebooks/tutorials/pandas-cookbook/04-weekday-bike-most-groupby-aggregate.ipynb +++ b/notebooks/tutorials/pandas-cookbook/04-weekday-bike-most-groupby-aggregate.ipynb @@ -46,7 +46,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"pandas-test-domain-4\", port=9084, reset=True)" + "node = sy.orchestra.launch(name=\"pandas-test-datasite-4\", port=9084, reset=True)" ] }, { @@ -66,7 +66,7 @@ }, "outputs": [], "source": [ - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -211,7 +211,7 @@ " name=\"bikes2\",\n", " asset_list=[sy.Asset(name=\"bikes\", data=df, mock=mock, mock_is_real=False)],\n", ")\n", - "root_domain_client.upload_dataset(dataset)" + "root_datasite_client.upload_dataset(dataset)" ] }, { @@ -231,7 +231,7 @@ }, "outputs": [], "source": [ - "user = root_domain_client.register(\n", + "user = root_datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -242,9 +242,9 @@ "\n", "# todo: give user data scientist role\n", "\n", - "guest_domain_client = node.client\n", + "guest_datasite_client = node.client\n", "\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -288,7 +288,7 @@ }, "outputs": [], "source": [ - "ds = guest_domain_client.datasets[0]" + "ds = guest_datasite_client.datasets[0]" ] }, { @@ -716,7 +716,7 @@ }, "outputs": [], "source": [ - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -736,7 +736,7 @@ }, "outputs": [], "source": [ - "notifications = root_domain_client.notifications.get_all_unread()" + "notifications = root_datasite_client.notifications.get_all_unread()" ] }, { @@ -811,7 +811,7 @@ }, "outputs": [], "source": [ - "real_data = root_domain_client.datasets[0].assets[0].data" + "real_data = root_datasite_client.datasets[0].assets[0].data" ] }, { diff --git a/notebooks/tutorials/pandas-cookbook/05-combining-dataframes-scraping-weather-data.ipynb b/notebooks/tutorials/pandas-cookbook/05-combining-dataframes-scraping-weather-data.ipynb index 0bff86b5c06..6a44c71caee 100644 --- a/notebooks/tutorials/pandas-cookbook/05-combining-dataframes-scraping-weather-data.ipynb +++ b/notebooks/tutorials/pandas-cookbook/05-combining-dataframes-scraping-weather-data.ipynb @@ -54,7 +54,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"pandas-test-domain-5\", port=9085, reset=True)" + "node = sy.orchestra.launch(name=\"pandas-test-datasite-5\", port=9085, reset=True)" ] }, { @@ -74,7 +74,7 @@ }, "outputs": [], "source": [ - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -298,7 +298,7 @@ "outputs": [], "source": [ "dataset = sy.Dataset(name=\"test\", asset_list=assets)\n", - "root_domain_client.upload_dataset(dataset)" + "root_datasite_client.upload_dataset(dataset)" ] }, { @@ -330,7 +330,7 @@ }, "outputs": [], "source": [ - "user = root_domain_client.register(\n", + "user = root_datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -341,9 +341,9 @@ "\n", "# todo: give user data scientist role\n", "\n", - "guest_domain_client = node.client\n", + "guest_datasite_client = node.client\n", "\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -382,7 +382,7 @@ }, "outputs": [], "source": [ - "ds = guest_domain_client.datasets[-1]" + "ds = guest_datasite_client.datasets[-1]" ] }, { @@ -903,7 +903,7 @@ }, "outputs": [], "source": [ - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -923,7 +923,7 @@ }, "outputs": [], "source": [ - "notifications = root_domain_client.notifications.get_all_unread()" + "notifications = root_datasite_client.notifications.get_all_unread()" ] }, { @@ -999,8 +999,8 @@ "outputs": [], "source": [ "real_data1, real_data2 = (\n", - " root_domain_client.datasets[-1].assets[\"weather1\"].data,\n", - " root_domain_client.datasets[-1].assets[\"weather2\"].data,\n", + " root_datasite_client.datasets[-1].assets[\"weather1\"].data,\n", + " root_datasite_client.datasets[-1].assets[\"weather2\"].data,\n", ")" ] }, @@ -1070,7 +1070,7 @@ }, "outputs": [], "source": [ - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { diff --git a/notebooks/tutorials/pandas-cookbook/06-string-operations-which-month-was-the-snowiest.ipynb b/notebooks/tutorials/pandas-cookbook/06-string-operations-which-month-was-the-snowiest.ipynb index 896f842e6cb..a2b1d086061 100644 --- a/notebooks/tutorials/pandas-cookbook/06-string-operations-which-month-was-the-snowiest.ipynb +++ b/notebooks/tutorials/pandas-cookbook/06-string-operations-which-month-was-the-snowiest.ipynb @@ -54,7 +54,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"pandas-test-domain-6\", port=9086, reset=True)" + "node = sy.orchestra.launch(name=\"pandas-test-datasite-6\", port=9086, reset=True)" ] }, { @@ -74,7 +74,7 @@ }, "outputs": [], "source": [ - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -287,7 +287,7 @@ " sy.Asset(name=\"weather\", data=weather_2012_final, mock=mock, mock_is_real=False)\n", " ],\n", ")\n", - "root_domain_client.upload_dataset(dataset)" + "root_datasite_client.upload_dataset(dataset)" ] }, { @@ -319,7 +319,7 @@ }, "outputs": [], "source": [ - "user = root_domain_client.register(\n", + "user = root_datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -328,8 +328,8 @@ " website=\"https://www.caltech.edu/\",\n", ")\n", "# todo: give user data scientist role\n", - "guest_domain_client = node.client\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_datasite_client = node.client\n", + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -368,7 +368,7 @@ }, "outputs": [], "source": [ - "ds = guest_domain_client.datasets[0]" + "ds = guest_datasite_client.datasets[0]" ] }, { @@ -805,7 +805,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -826,7 +826,7 @@ }, "outputs": [], "source": [ - "notifications = domain_client.notifications.get_all_unread()" + "notifications = datasite_client.notifications.get_all_unread()" ] }, { @@ -901,7 +901,7 @@ }, "outputs": [], "source": [ - "real_data = domain_client.datasets[0].assets[0].data" + "real_data = datasite_client.datasets[0].assets[0].data" ] }, { diff --git a/notebooks/tutorials/pandas-cookbook/07-cleaning-up-messy-data.ipynb b/notebooks/tutorials/pandas-cookbook/07-cleaning-up-messy-data.ipynb index dab79f0c217..60f480b722a 100644 --- a/notebooks/tutorials/pandas-cookbook/07-cleaning-up-messy-data.ipynb +++ b/notebooks/tutorials/pandas-cookbook/07-cleaning-up-messy-data.ipynb @@ -54,7 +54,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"pandas-test-domain-7\", port=9087, reset=True)" + "node = sy.orchestra.launch(name=\"pandas-test-datasite-7\", port=9087, reset=True)" ] }, { @@ -74,7 +74,7 @@ }, "outputs": [], "source": [ - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -307,7 +307,7 @@ " )\n", " ],\n", ")\n", - "root_domain_client.upload_dataset(dataset)" + "root_datasite_client.upload_dataset(dataset)" ] }, { @@ -327,7 +327,7 @@ }, "outputs": [], "source": [ - "user = root_domain_client.register(\n", + "user = root_datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -336,8 +336,8 @@ " website=\"https://www.caltech.edu/\",\n", ")\n", "# todo: give user data scientist role\n", - "guest_domain_client = node.client\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_datasite_client = node.client\n", + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -860,7 +860,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -881,7 +881,7 @@ }, "outputs": [], "source": [ - "notifications = domain_client.notifications.get_all_unread()" + "notifications = datasite_client.notifications.get_all_unread()" ] }, { @@ -956,7 +956,7 @@ }, "outputs": [], "source": [ - "real_data = domain_client.datasets[0].assets[0].data" + "real_data = datasite_client.datasets[0].assets[0].data" ] }, { diff --git a/notebooks/tutorials/pandas-cookbook/08-how-to-deal-with-timestamps.ipynb b/notebooks/tutorials/pandas-cookbook/08-how-to-deal-with-timestamps.ipynb index 32beba9af48..3266e8a954d 100644 --- a/notebooks/tutorials/pandas-cookbook/08-how-to-deal-with-timestamps.ipynb +++ b/notebooks/tutorials/pandas-cookbook/08-how-to-deal-with-timestamps.ipynb @@ -56,7 +56,7 @@ }, "outputs": [], "source": [ - "node = sy.orchestra.launch(name=\"pandas-test-domain-8\", port=9088, reset=True)" + "node = sy.orchestra.launch(name=\"pandas-test-datasite-8\", port=9088, reset=True)" ] }, { @@ -77,7 +77,7 @@ }, "outputs": [], "source": [ - "root_domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "root_datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -328,7 +328,7 @@ " )\n", " ],\n", ")\n", - "root_domain_client.upload_dataset(dataset)" + "root_datasite_client.upload_dataset(dataset)" ] }, { @@ -361,7 +361,7 @@ }, "outputs": [], "source": [ - "user = root_domain_client.register(\n", + "user = root_datasite_client.register(\n", " name=\"Jane Doe\",\n", " email=\"jane@caltech.edu\",\n", " password=\"abc123\",\n", @@ -370,8 +370,8 @@ " website=\"https://www.caltech.edu/\",\n", ")\n", "# todo: give user data scientist role\n", - "guest_domain_client = node.client\n", - "guest_client = guest_domain_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" + "guest_datasite_client = node.client\n", + "guest_client = guest_datasite_client.login(email=\"jane@caltech.edu\", password=\"abc123\")" ] }, { @@ -425,7 +425,7 @@ }, "outputs": [], "source": [ - "ds = guest_domain_client.datasets[0]" + "ds = guest_datasite_client.datasets[0]" ] }, { @@ -811,7 +811,7 @@ }, "outputs": [], "source": [ - "domain_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" + "datasite_client = node.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, { @@ -832,7 +832,7 @@ }, "outputs": [], "source": [ - "notifications = domain_client.notifications.get_all_unread()" + "notifications = datasite_client.notifications.get_all_unread()" ] }, { @@ -907,7 +907,7 @@ }, "outputs": [], "source": [ - "real_data = domain_client.datasets[0].assets[0].data" + "real_data = datasite_client.datasets[0].assets[0].data" ] }, { diff --git a/packages/grid/backend/backend.dockerfile b/packages/grid/backend/backend.dockerfile index 606569c49f4..8c284a7369c 100644 --- a/packages/grid/backend/backend.dockerfile +++ b/packages/grid/backend/backend.dockerfile @@ -74,7 +74,7 @@ ENV \ # Syft APPDIR="/root/app" \ NODE_NAME="default_node_name" \ - NODE_TYPE="domain" \ + NODE_TYPE="datasite" \ SERVICE_NAME="backend" \ RELEASE="production" \ DEV_MODE="False" \ diff --git a/packages/grid/backend/grid/core/config.py b/packages/grid/backend/grid/core/config.py index 619637c06c6..f31deefce2a 100644 --- a/packages/grid/backend/grid/core/config.py +++ b/packages/grid/backend/grid/core/config.py @@ -99,11 +99,11 @@ def get_emails_enabled(self) -> Self: NODE_NAME: str = "default_node_name" STREAM_QUEUE: bool = False - NODE_TYPE: str = "domain" + NODE_TYPE: str = "datasite" OPEN_REGISTRATION: bool = True - # DOMAIN_ASSOCIATION_REQUESTS_AUTOMATICALLY_ACCEPTED: bool = True + # DATASITE_ASSOCIATION_REQUESTS_AUTOMATICALLY_ACCEPTED: bool = True USE_BLOB_STORAGE: bool = ( True if os.getenv("USE_BLOB_STORAGE", "false").lower() == "true" else False ) @@ -124,7 +124,7 @@ def get_emails_enabled(self) -> Self: # STORE_DB_ID: int = int(os.getenv("STORE_DB_ID", 0)) # LEDGER_DB_ID: int = int(os.getenv("LEDGER_DB_ID", 1)) # NETWORK_CHECK_INTERVAL: int = int(os.getenv("NETWORK_CHECK_INTERVAL", 60)) - # DOMAIN_CHECK_INTERVAL: int = int(os.getenv("DOMAIN_CHECK_INTERVAL", 60)) + # DATASITE_CHECK_INTERVAL: int = int(os.getenv("DATASITE_CHECK_INTERVAL", 60)) CONTAINER_HOST: str = str(os.getenv("CONTAINER_HOST", "docker")) MONGO_HOST: str = str(os.getenv("MONGO_HOST", "")) MONGO_PORT: int = int(os.getenv("MONGO_PORT", 27017)) diff --git a/packages/grid/backend/grid/core/node.py b/packages/grid/backend/grid/core/node.py index 926cbbc5556..2f9143a9469 100644 --- a/packages/grid/backend/grid/core/node.py +++ b/packages/grid/backend/grid/core/node.py @@ -1,7 +1,7 @@ # syft absolute from syft.abstract_node import NodeType -from syft.node.domain import Domain -from syft.node.domain import Node +from syft.node.datasite import Datasite +from syft.node.datasite import Node from syft.node.enclave import Enclave from syft.node.gateway import Gateway from syft.node.node import get_default_bucket_name @@ -79,7 +79,7 @@ def seaweedfs_config() -> SeaweedFSConfig: enable_warnings = get_enable_warnings() worker_classes = { - NodeType.DOMAIN: Domain, + NodeType.DATASITE: Datasite, NodeType.GATEWAY: Gateway, NodeType.ENCLAVE: Enclave, } diff --git a/packages/grid/backend/grid/start.sh b/packages/grid/backend/grid/start.sh index 4b3d5de4cf2..f77b419c82a 100755 --- a/packages/grid/backend/grid/start.sh +++ b/packages/grid/backend/grid/start.sh @@ -7,7 +7,7 @@ APP_MODULE=grid.main:app LOG_LEVEL=${LOG_LEVEL:-info} HOST=${HOST:-0.0.0.0} PORT=${PORT:-80} -NODE_TYPE=${NODE_TYPE:-domain} +NODE_TYPE=${NODE_TYPE:-datasite} APPDIR=${APPDIR:-$HOME/app} RELOAD="" DEBUG_CMD="" diff --git a/packages/grid/default.env b/packages/grid/default.env index 0aae09f1026..d601c369c13 100644 --- a/packages/grid/default.env +++ b/packages/grid/default.env @@ -1,7 +1,7 @@ #!/bin/bash -DOMAIN=localhost +DATASITE=localhost NODE_NAME=default_node_name -NODE_TYPE=domain +NODE_TYPE=datasite FRONTEND_TARGET=grid-ui-development PORT=80 HTTP_PORT=80 @@ -44,9 +44,9 @@ SMTP_HOST= SMTP_USERNAME= SMTP_PASSWORD= EMAIL_SENDER= -SERVER_HOST="https://${DOMAIN}" +SERVER_HOST="https://${DATASITE}" NETWORK_CHECK_INTERVAL=60 -DOMAIN_CHECK_INTERVAL=60 +DATASITE_CHECK_INTERVAL=60 ASSOCIATION_TIMEOUT=10 USERS_OPEN_REGISTRATION=False DEV_MODE=False diff --git a/packages/grid/devspace.yaml b/packages/grid/devspace.yaml index 8bbf3487daf..9b084663c29 100644 --- a/packages/grid/devspace.yaml +++ b/packages/grid/devspace.yaml @@ -117,16 +117,16 @@ dev: localPort: 3480 profiles: - - name: domain-low - description: "Deploy a low-side domain" + - name: datasite-low + description: "Deploy a low-side datasite" patches: - op: add path: deployments.syft.helm.values.node value: side: low - - name: domain-tunnel - description: "Deploy a domain with tunneling enabled" + - name: datasite-tunnel + description: "Deploy a datasite with tunneling enabled" patches: # enable rathole image - op: add @@ -143,7 +143,7 @@ profiles: # use rathole client-specific chart values - op: add path: deployments.syft.helm.valuesFiles - value: ./helm/examples/dev/domain.tunnel.yaml + value: ./helm/examples/dev/datasite.tunnel.yaml - name: gateway description: "Deploy a Gateway Node with tunnel enabled" @@ -194,7 +194,7 @@ profiles: value: 2334:2333 - name: gcp - description: "Deploy a high-side domain on GCP" + description: "Deploy a high-side datasite on GCP" patches: - op: replace path: deployments.syft.helm.valuesFiles @@ -202,7 +202,7 @@ profiles: - ./helm/examples/gcp/gcp.high.yaml - name: gcp-low - description: "Deploy a low-side domain on GCP" + description: "Deploy a low-side datasite on GCP" patches: - op: replace path: deployments.syft.helm.valuesFiles @@ -210,7 +210,7 @@ profiles: - ./helm/examples/gcp/gcp.low.yaml - name: azure - description: "Deploy a high-side domain on AKS" + description: "Deploy a high-side datasite on AKS" patches: - op: replace path: deployments.syft.helm.valuesFiles diff --git a/packages/grid/frontend/README.md b/packages/grid/frontend/README.md index e912f1dd172..d9c01c76c19 100644 --- a/packages/grid/frontend/README.md +++ b/packages/grid/frontend/README.md @@ -1,7 +1,7 @@ # PyGrid UI The PyGrid UI is the user interface that allows data owners to manage their -**deployed** PyGrid domains and networks. +**deployed** PyGrid datasites and networks. ## Installation diff --git a/packages/grid/frontend/src/_routes/(app)/account/+page.svelte b/packages/grid/frontend/src/_routes/(app)/account/+page.svelte index 10780f2c120..74960f8f47f 100644 --- a/packages/grid/frontend/src/_routes/(app)/account/+page.svelte +++ b/packages/grid/frontend/src/_routes/(app)/account/+page.svelte @@ -85,8 +85,8 @@

When you delete your user account all information relating to you will be deleted as well - as any permissions and requests. If you are the domain owner the domain node will be - deleted as well and will be closed to all users. To transfer ownership of a domain node + as any permissions and requests. If you are the datasite owner the datasite node will be + deleted as well and will be closed to all users. To transfer ownership of a datasite node before deleting your account you can follow the instructions here

@@ -134,10 +134,10 @@

Are you sure you want to delete your node?

- Because you are the domain owner, the domain node along with all uploaded datasets, user + Because you are the datasite owner, the datasite node along with all uploaded datasets, user accounts, and requests will be deleted. All network memberships will also be removed. If you - would like to keep this domain node but no longer want to be an owner press “cancel” and - follow the instructions here to transfer ownership of your domain node. + would like to keep this datasite node but no longer want to be an owner press “cancel” and + follow the instructions here to transfer ownership of your datasite node.

- {#if openModal === "domain_name"} - + {#if openModal === "datasite_name"} + {:else if openModal === "organization"} { diff --git a/packages/grid/frontend/src/_routes/(app)/users/[slug]/+page.svelte b/packages/grid/frontend/src/_routes/(app)/users/[slug]/+page.svelte index f893eece0e9..a261ab5ebae 100644 --- a/packages/grid/frontend/src/_routes/(app)/users/[slug]/+page.svelte +++ b/packages/grid/frontend/src/_routes/(app)/users/[slug]/+page.svelte @@ -3,7 +3,7 @@ import Badge from "$lib/components/Badge.svelte" import CaretLeft from "$lib/components/icons/CaretLeft.svelte" import { getInitials, getUserRole } from "$lib/utils" - import type { UserView } from "../../../../types/domain/users" + import type { UserView } from "../../../../types/datasite/users" import type { PageData } from "./$types" export let data: PageData diff --git a/packages/grid/frontend/src/_routes/(auth)/login/+page.svelte b/packages/grid/frontend/src/_routes/(auth)/login/+page.svelte index 1b6ddaf5b69..14cc012889d 100644 --- a/packages/grid/frontend/src/_routes/(auth)/login/+page.svelte +++ b/packages/grid/frontend/src/_routes/(auth)/login/+page.svelte @@ -2,10 +2,10 @@ import { enhance } from "$app/forms" import Button from "$lib/components/Button.svelte" import Modal from "$lib/components/Modal.svelte" - import DomainMetadataPanel from "$lib/components/authentication/DomainMetadataPanel.svelte" + import DatasiteMetadataPanel from "$lib/components/authentication/DatasiteMetadataPanel.svelte" import Input from "$lib/components/Input.svelte" - import DomainOnlineIndicator from "$lib/components/DomainOnlineIndicator.svelte" - import type { DomainOnlineStatus } from "../../../types/domain/onlineIndicator" + import DatasiteOnlineIndicator from "$lib/components/DatasiteOnlineIndicator.svelte" + import type { DatasiteOnlineStatus } from "../../../types/datasite/onlineIndicator" import type { PageData, ActionData } from "./$types" export let data: PageData @@ -13,13 +13,13 @@ const { metadata } = data - let status: DomainOnlineStatus = "online" + let status: DatasiteOnlineStatus = "online"
- +
@@ -38,12 +38,12 @@

{/if}
- +

{#if status === "pending"} Checking connection {:else} - Domain {status} + Datasite {status} {/if}

diff --git a/packages/grid/frontend/src/_routes/(auth)/signup/+page.svelte b/packages/grid/frontend/src/_routes/(auth)/signup/+page.svelte index 500249f1b8f..24a963b0fab 100644 --- a/packages/grid/frontend/src/_routes/(auth)/signup/+page.svelte +++ b/packages/grid/frontend/src/_routes/(auth)/signup/+page.svelte @@ -1,7 +1,7 @@ diff --git a/packages/grid/frontend/src/lib/components/Datasets/DatasetNoneFound.svelte b/packages/grid/frontend/src/lib/components/Datasets/DatasetNoneFound.svelte index fe02b87ef03..2e651c2ab3d 100644 --- a/packages/grid/frontend/src/lib/components/Datasets/DatasetNoneFound.svelte +++ b/packages/grid/frontend/src/lib/components/Datasets/DatasetNoneFound.svelte @@ -1,7 +1,7 @@

No Datasets Uploaded

- To begin adding datasets to this domain node please click the "+" button and follow + To begin adding datasets to this datasite node please click the "+" button and follow instructions.

diff --git a/packages/grid/frontend/src/lib/components/DomainOnlineIndicator.svelte b/packages/grid/frontend/src/lib/components/DatasiteOnlineIndicator.svelte similarity index 68% rename from packages/grid/frontend/src/lib/components/DomainOnlineIndicator.svelte rename to packages/grid/frontend/src/lib/components/DatasiteOnlineIndicator.svelte index 1232283ac6c..b534a481813 100644 --- a/packages/grid/frontend/src/lib/components/DomainOnlineIndicator.svelte +++ b/packages/grid/frontend/src/lib/components/DatasiteOnlineIndicator.svelte @@ -1,6 +1,6 @@
diff --git a/packages/grid/frontend/src/lib/components/Navigation/SideNavDOHandbook.svelte b/packages/grid/frontend/src/lib/components/Navigation/SideNavDOHandbook.svelte index f72f9dddd45..cef3c840ab9 100644 --- a/packages/grid/frontend/src/lib/components/Navigation/SideNavDOHandbook.svelte +++ b/packages/grid/frontend/src/lib/components/Navigation/SideNavDOHandbook.svelte @@ -27,7 +27,7 @@

Data Owner handbook

Check out the data owner handbook to learn more tips & tricks about how to manage your - domain node. + datasite node.

diff --git a/packages/grid/frontend/src/lib/components/Navigation/TopNav.svelte b/packages/grid/frontend/src/lib/components/Navigation/TopNav.svelte index 9e127766cf3..1a3dc762b4e 100644 --- a/packages/grid/frontend/src/lib/components/Navigation/TopNav.svelte +++ b/packages/grid/frontend/src/lib/components/Navigation/TopNav.svelte @@ -13,7 +13,7 @@ { href: "", icon: BellIcon, disabled: true }, ] - $: domainInitials = getInitials(metadata.name) + $: datasiteInitials = getInitials(metadata.name) $: userInitials = getInitials(user.name) @@ -21,7 +21,7 @@ class="w-full py-2 px-6 flex items-center justify-between tablet:justify-end shadow-topbar-1 tablet:shadow-none" >
- +
    {#each links as link} diff --git a/packages/grid/frontend/src/lib/components/OnboardingModal.svelte b/packages/grid/frontend/src/lib/components/OnboardingModal.svelte index 8e381c18630..40a885c8634 100644 --- a/packages/grid/frontend/src/lib/components/OnboardingModal.svelte +++ b/packages/grid/frontend/src/lib/components/OnboardingModal.svelte @@ -23,15 +23,15 @@ website: "", } - let domainSettings = { + let datasiteSettings = { name: "", description: "", organization: "", on_board: false, } - let checkRequiredDomainFields = () => { - return domainSettings.name !== "" ? true : false + let checkRequiredDatasiteFields = () => { + return datasiteSettings.name !== "" ? true : false } let checkRequiredUserFields = () => { @@ -49,7 +49,7 @@ headers: { "Content-Type": "application/json", }, - body: JSON.stringify(domainSettings), + body: JSON.stringify(datasiteSettings), }) await fetch(`/_syft_api/users/${userSettings.id}`, { @@ -86,7 +86,7 @@ website: "", } - domainSettings = { + datasiteSettings = { name: "", description: "", organization: "", @@ -151,7 +151,7 @@
-

Domain Profile

+

Datasite Profile

Step 2 of 4

@@ -182,28 +182,28 @@

- Let's begin by describing some basic information about this domain + Let's begin by describing some basic information about this datasite node. This information will be shown to outside users to help them - find and understand what your domain offers. + find and understand what your datasite offers.

@@ -232,7 +232,7 @@

- Now that we have described our domain, let's update our password and + Now that we have described our datasite, let's update our password and describe some basic information about ourselves for our "User Profile". User profile information will be shown to teammates and collaborators when working on studies together. diff --git a/packages/grid/frontend/src/lib/components/Users/UserCreateModal.svelte b/packages/grid/frontend/src/lib/components/Users/UserCreateModal.svelte index 77ebcc3fb70..60274ed4cbd 100644 --- a/packages/grid/frontend/src/lib/components/Users/UserCreateModal.svelte +++ b/packages/grid/frontend/src/lib/components/Users/UserCreateModal.svelte @@ -16,13 +16,13 @@ roleId: 2, title: "Data Scientist", description: - "This role is for users who will be performing computations on your datasets. They may be users you know directly or those who found your domain through search and discovery. By default this user can see a list of your datasets and can request to get results.", + "This role is for users who will be performing computations on your datasets. They may be users you know directly or those who found your datasite through search and discovery. By default this user can see a list of your datasets and can request to get results.", }, { roleId: 32, title: "Data Owner", description: - "This role is for users on your team who will be responsible for uploading data to the domain.", + "This role is for users on your team who will be responsible for uploading data to the datasite.", }, { roleId: 128, @@ -105,7 +105,7 @@

To begin let's select the role this user is going to have on your - domain node. + datasite node.

{#each cardsContent as { title, description, roleId }} @@ -221,8 +221,8 @@ Welcome to {metadata?.name} {name},
- You are formally invited you to join {metadata?.name} Domain. Below is - your login credentials and the URL to the domain. After logging in you + You are formally invited you to join {metadata?.name} Datasite. Below is + your login credentials and the URL to the datasite. After logging in you will be prompted to customize your account.

{href} diff --git a/packages/grid/frontend/src/lib/components/Users/UserListItem.svelte b/packages/grid/frontend/src/lib/components/Users/UserListItem.svelte index b5ca6737d6f..ad34edaf1cb 100644 --- a/packages/grid/frontend/src/lib/components/Users/UserListItem.svelte +++ b/packages/grid/frontend/src/lib/components/Users/UserListItem.svelte @@ -1,6 +1,6 @@
{#if metadata}
- +
- +

{metadata.name}

{#if metadata.organization} diff --git a/packages/grid/frontend/src/lib/utils.ts b/packages/grid/frontend/src/lib/utils.ts index 2ffed30dec5..38ffbc1c284 100644 --- a/packages/grid/frontend/src/lib/utils.ts +++ b/packages/grid/frontend/src/lib/utils.ts @@ -1,4 +1,4 @@ -import { ServiceRoles } from "../types/domain/users" +import { ServiceRoles } from "../types/datasite/users" import { COOKIES } from "./constants" import type { CookieSerializeOptions } from "cookie" import type { Cookies } from "@sveltejs/kit" diff --git a/packages/grid/frontend/src/routes/[...all]/+page.svelte b/packages/grid/frontend/src/routes/[...all]/+page.svelte index b1bb3b1cb01..58d3d7ba901 100644 --- a/packages/grid/frontend/src/routes/[...all]/+page.svelte +++ b/packages/grid/frontend/src/routes/[...all]/+page.svelte @@ -1,6 +1,6 @@
- PyGrid + Syft UI
diff --git a/packages/grid/frontend/static/assets/2023_welcome_to_pygrid.png b/packages/grid/frontend/static/assets/2023_welcome_to_syft_ui.png similarity index 100% rename from packages/grid/frontend/static/assets/2023_welcome_to_pygrid.png rename to packages/grid/frontend/static/assets/2023_welcome_to_syft_ui.png diff --git a/packages/grid/frontend/static/images/pygrid-logo.png b/packages/grid/frontend/static/images/pygrid-logo.png deleted file mode 100644 index d783862d8739822401f7da1ed9376ff478902f6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4507 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 diff --git a/packages/grid/frontend/tests/e2e/page.spec.ts b/packages/grid/frontend/tests/e2e/page.spec.ts index 9df184cda24..993ad4fa818 100644 --- a/packages/grid/frontend/tests/e2e/page.spec.ts +++ b/packages/grid/frontend/tests/e2e/page.spec.ts @@ -3,11 +3,11 @@ import { test, expect } from "@playwright/test" test("should display the page correctly", async ({ page }) => { await page.goto("/") const title = await page.title() - expect(title).toBe("PyGrid") + expect(title).toBe("Syft UI") }) test("should navigate to login page", async ({ page }) => { await page.goto("/login") const title = await page.title() - expect(title).toBe("PyGrid") + expect(title).toBe("Syft UI") }) diff --git a/packages/syft/PYPI.md b/packages/syft/PYPI.md index a28654af8e2..48e37c0e8d8 100644 --- a/packages/syft/PYPI.md +++ b/packages/syft/PYPI.md @@ -138,7 +138,7 @@ helm install ... --set ingress.class="gce" # Install Notes - PySyft 0.8.6 Requires: 🐍 `python 3.10 - 3.12` - Run: `pip install -U syft` -- PyGrid Requires: 🐳 `docker` or ☸️ `kubernetes` +- Syft Server Requires: 🐳 `docker` or ☸️ `kubernetes` # Versions @@ -159,7 +159,7 @@ Deprecated: - `0.5.1` - Course 2 + M1 Hotfix - `0.2.0` - `0.5.0` -PySyft and PyGrid use the same `version` and its best to match them up where possible. We release weekly betas which can be used in each context: +PySyft and Syft Server use the same `version` and its best to match them up where possible. We release weekly betas which can be used in each context: PySyft (Stable): `pip install -U syft` @@ -230,7 +230,7 @@ No more cold calls to get `access` to a dataset. No more weeks of `wait times` t - Deploy to GCP - Deploy to Kubernetes - Customize Networking -- Modify PyGrid UI +- Modify Syft UI diff --git a/packages/syft/src/syft/client/client.py b/packages/syft/src/syft/client/client.py index 0a6f92241b4..0406189d119 100644 --- a/packages/syft/src/syft/client/client.py +++ b/packages/syft/src/syft/client/client.py @@ -50,7 +50,7 @@ from ..service.user.user import UserView from ..service.user.user_roles import ServiceRole from ..service.user.user_service import UserService -from ..types.grid_url import GridURL +from ..types.server_url import ServerURL from ..types.syft_object import SYFT_OBJECT_VERSION_3 from ..types.uid import UID from ..util.telemetry import instrument @@ -73,12 +73,12 @@ from ..service.network.server_peer import ServerPeer -def upgrade_tls(url: GridURL, response: Response) -> GridURL: +def upgrade_tls(url: ServerURL, response: Response) -> ServerURL: try: if response.url.startswith("https://") and url.protocol == "http": # we got redirected to https - https_url = GridURL.from_url(response.url).with_path("") - logger.debug(f"GridURL Upgraded to HTTPS. {https_url}") + https_url = ServerURL.from_url(response.url).with_path("") + logger.debug(f"ServerURL Upgraded to HTTPS. {https_url}") return https_url except Exception as e: print(f"Failed to upgrade to HTTPS. {e}") @@ -115,8 +115,8 @@ def forward_message_to_proxy( API_PATH = "/api/v2" -DEFAULT_PYGRID_PORT = 80 -DEFAULT_PYGRID_ADDRESS = f"http://localhost:{DEFAULT_PYGRID_PORT}" +DEFAULT_SYFT_UI_PORT = 80 +DEFAULT_SYFT_UI_ADDRESS = f"http://localhost:{DEFAULT_SYFT_UI_PORT}" INTERNAL_PROXY_TO_RATHOLE = "http://proxy:80/rtunnel/" @@ -135,7 +135,7 @@ class HTTPConnection(ServerConnection): __canonical_name__ = "HTTPConnection" __version__ = SYFT_OBJECT_VERSION_3 - url: GridURL + url: ServerURL proxy_target_uid: UID | None = None routes: type[Routes] = Routes session_cache: Session | None = None @@ -146,8 +146,8 @@ class HTTPConnection(ServerConnection): @classmethod def make_url(cls, v: Any) -> Any: return ( - GridURL.from_url(v).as_container_host() - if isinstance(v, str | GridURL) + ServerURL.from_url(v).as_container_host() + if isinstance(v, str | ServerURL) else v ) @@ -161,7 +161,7 @@ def with_proxy(self, proxy_target_uid: UID) -> Self: rtunnel_token=self.rtunnel_token, ) - def stream_via(self, proxy_uid: UID, url_path: str) -> GridURL: + def stream_via(self, proxy_uid: UID, url_path: str) -> ServerURL: # Update the presigned url path to # // # url_path_bytes = _serialize(url_path, to_bytes=True) @@ -174,10 +174,10 @@ def get_cache_key(self) -> str: return str(self.url) @property - def api_url(self) -> GridURL: + def api_url(self) -> ServerURL: return self.url.with_path(self.routes.ROUTE_API_CALL.value) - def to_blob_route(self, path: str, **kwargs: Any) -> GridURL: + def to_blob_route(self, path: str, **kwargs: Any) -> ServerURL: _path = self.routes.ROUTE_BLOB_STORE.value + path return self.url.with_path(_path) @@ -202,7 +202,7 @@ def _make_get( if self.rtunnel_token: self.headers = {} if self.headers is None else self.headers - url = GridURL.from_url(INTERNAL_PROXY_TO_RATHOLE) + url = ServerURL.from_url(INTERNAL_PROXY_TO_RATHOLE) self.headers["Host"] = self.url.host_or_ip url = url.with_path(path) @@ -231,7 +231,7 @@ def _make_get_no_params(self, path: str, stream: bool = False) -> bytes | Iterab if self.rtunnel_token: self.headers = {} if self.headers is None else self.headers - url = GridURL.from_url(INTERNAL_PROXY_TO_RATHOLE) + url = ServerURL.from_url(INTERNAL_PROXY_TO_RATHOLE) self.headers["Host"] = self.url.host_or_ip url = url.with_path(path) @@ -262,7 +262,7 @@ def _make_put( url = self.url if self.rtunnel_token: - url = GridURL.from_url(INTERNAL_PROXY_TO_RATHOLE) + url = ServerURL.from_url(INTERNAL_PROXY_TO_RATHOLE) self.headers = {} if self.headers is None else self.headers self.headers["Host"] = self.url.host_or_ip @@ -294,7 +294,7 @@ def _make_post( url = self.url if self.rtunnel_token: - url = GridURL.from_url(INTERNAL_PROXY_TO_RATHOLE) + url = ServerURL.from_url(INTERNAL_PROXY_TO_RATHOLE) self.headers = {} if self.headers is None else self.headers self.headers["Host"] = self.url.host_or_ip @@ -409,7 +409,7 @@ def make_call(self, signed_call: SignedSyftAPICall) -> Any | SyftError: msg_bytes: bytes = _serialize(obj=signed_call, to_bytes=True) if self.rtunnel_token: - api_url = GridURL.from_url(INTERNAL_PROXY_TO_RATHOLE) + api_url = ServerURL.from_url(INTERNAL_PROXY_TO_RATHOLE) api_url = api_url.with_path(self.routes.ROUTE_API_CALL.value) self.headers = {} if self.headers is None else self.headers self.headers["Host"] = self.url.host_or_ip @@ -484,12 +484,12 @@ def get_server_metadata( else: return self.server.metadata.to(ServerMetadataJSON) - def to_blob_route(self, path: str, host: str | None = None) -> GridURL: + def to_blob_route(self, path: str, host: str | None = None) -> ServerURL: # TODO: FIX! if host is not None: - return GridURL(host_or_ip=host, port=8333).with_path(path) + return ServerURL(host_or_ip=host, port=8333).with_path(path) else: - return GridURL(port=8333).with_path(path) + return ServerURL(port=8333).with_path(path) def get_api( self, @@ -711,8 +711,8 @@ def verify_key(self) -> SyftVerifyKey: return self.credentials.verify_key @classmethod - def from_url(cls, url: str | GridURL) -> Self: - return cls(connection=HTTPConnection(url=GridURL.from_url(url))) + def from_url(cls, url: str | ServerURL) -> Self: + return cls(connection=HTTPConnection(url=ServerURL.from_url(url))) @classmethod def from_server(cls, server: AbstractServer) -> Self: @@ -1060,14 +1060,14 @@ def refresh_callback() -> SyftAPI: @instrument def connect( - url: str | GridURL = DEFAULT_PYGRID_ADDRESS, + url: str | ServerURL = DEFAULT_SYFT_UI_ADDRESS, server: AbstractServer | None = None, port: int | None = None, ) -> SyftClient: if server: connection = PythonConnection(server=server) else: - url = GridURL.from_url(url) + url = ServerURL.from_url(url) if isinstance(port, int | str): url.set_port(int(port)) connection = HTTPConnection(url=url) @@ -1082,7 +1082,7 @@ def connect( @instrument def register( - url: str | GridURL, + url: str | ServerURL, port: int, name: str, email: str, @@ -1103,7 +1103,7 @@ def register( @instrument def login_as_guest( # HTTPConnection - url: str | GridURL = DEFAULT_PYGRID_ADDRESS, + url: str | ServerURL = DEFAULT_SYFT_UI_ADDRESS, port: int | None = None, # PythonConnection server: AbstractServer | None = None, @@ -1131,7 +1131,7 @@ def login_as_guest( def login( email: str, # HTTPConnection - url: str | GridURL = DEFAULT_PYGRID_ADDRESS, + url: str | ServerURL = DEFAULT_SYFT_UI_ADDRESS, port: int | None = None, # PythonConnection server: AbstractServer | None = None, diff --git a/packages/syft/src/syft/client/registry.py b/packages/syft/src/syft/client/registry.py index 20707f74389..48627172eeb 100644 --- a/packages/syft/src/syft/client/registry.py +++ b/packages/syft/src/syft/client/registry.py @@ -17,7 +17,7 @@ from ..service.network.server_peer import ServerPeer from ..service.network.server_peer import ServerPeerConnectionStatus from ..service.response import SyftException -from ..types.grid_url import GridURL +from ..types.server_url import ServerURL from ..util.constants import DEFAULT_TIMEOUT from .client import SyftClient as Client @@ -77,7 +77,7 @@ def check_network(network: dict) -> dict[Any, Any] | None: url = "http://" + network["host_or_ip"] + ":" + str(network["port"]) + "/" try: res = requests.get(url, timeout=DEFAULT_TIMEOUT) # nosec - online = "This is a PyGrid Network server." in res.text + online = "This is a Syft Gateway server." in res.text except Exception: online = False @@ -165,8 +165,8 @@ def create_client(network: dict[str, Any]) -> Client: port = int(network["port"]) protocol = network["protocol"] host_or_ip = network["host_or_ip"] - grid_url = GridURL(port=port, protocol=protocol, host_or_ip=host_or_ip) - client = connect(url=str(grid_url)) + server_url = ServerURL(port=port, protocol=protocol, host_or_ip=host_or_ip) + client = connect(url=str(server_url)) return client.guest() except Exception as e: raise SyftException(f"Failed to login with: {network}. {e}") @@ -212,7 +212,7 @@ def check_network(network: dict) -> dict[Any, Any] | None: url = "http://" + network["host_or_ip"] + ":" + str(network["port"]) + "/" try: res = requests.get(url, timeout=DEFAULT_TIMEOUT) - online = "This is a PyGrid Network server." in res.text + online = "This is a Syft Gateway server." in res.text except Exception: online = False @@ -431,8 +431,8 @@ def create_client(enclave: dict[str, Any]) -> Client: port = int(enclave["port"]) protocol = enclave["protocol"] host_or_ip = enclave["host_or_ip"] - grid_url = GridURL(port=port, protocol=protocol, host_or_ip=host_or_ip) - client = connect(url=str(grid_url)) + server_url = ServerURL(port=port, protocol=protocol, host_or_ip=host_or_ip) + client = connect(url=str(server_url)) return client.guest() except Exception as e: raise SyftException(f"Failed to login with: {enclave}. {e}") diff --git a/packages/syft/src/syft/protocol/data_protocol.py b/packages/syft/src/syft/protocol/data_protocol.py index 4cf71ab8ac7..0590db599bc 100644 --- a/packages/syft/src/syft/protocol/data_protocol.py +++ b/packages/syft/src/syft/protocol/data_protocol.py @@ -152,12 +152,13 @@ def read_history(self) -> dict: return protocol_history def save_history(self, history: dict) -> None: - for file_path in protocol_release_dir().iterdir(): - for version in self.read_json(file_path): - # Skip adding file if the version is not part of the history - if version not in history.keys(): - continue - history[version] = {"release_name": file_path.name} + if os.path.exists(protocol_release_dir()): + for file_path in protocol_release_dir().iterdir(): + for version in self.read_json(file_path): + # Skip adding file if the version is not part of the history + if version not in history.keys(): + continue + history[version] = {"release_name": file_path.name} self.file_path.write_text(json.dumps(history, indent=2) + "\n") @property diff --git a/packages/syft/src/syft/protocol/releases/.gitignore b/packages/syft/src/syft/protocol/releases/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/syft/src/syft/service/network/network_service.py b/packages/syft/src/syft/service/network/network_service.py index c712e728985..1d313bbe362 100644 --- a/packages/syft/src/syft/service/network/network_service.py +++ b/packages/syft/src/syft/service/network/network_service.py @@ -23,7 +23,7 @@ from ...store.document_store import PartitionKey from ...store.document_store import PartitionSettings from ...store.document_store import QueryKeys -from ...types.grid_url import GridURL +from ...types.server_url import ServerURL from ...types.transforms import TransformContext from ...types.transforms import keep from ...types.transforms import make_set_default @@ -948,7 +948,7 @@ def _get_association_requests_by_peer_id( SERVICE_TO_TYPES[NetworkService].update({ServerPeer}) -def from_grid_url(context: TransformContext) -> TransformContext: +def from_server_url(context: TransformContext) -> TransformContext: if context.obj is not None and context.output is not None: url = context.obj.url.as_container_host() context.output["host_or_ip"] = url.host_or_ip @@ -964,7 +964,7 @@ def from_grid_url(context: TransformContext) -> TransformContext: @transform(HTTPConnection, HTTPServerRoute) def http_connection_to_server_route() -> list[Callable]: - return [from_grid_url] + return [from_server_url] def get_python_server_route(context: TransformContext) -> TransformContext: @@ -993,7 +993,7 @@ def server_route_to_python_connection( def server_route_to_http_connection( obj: Any, context: TransformContext | None = None ) -> list[Callable]: - url = GridURL( + url = ServerURL( protocol=obj.protocol, host_or_ip=obj.host_or_ip, port=obj.port ).as_container_host() return HTTPConnection( diff --git a/packages/syft/src/syft/service/network/reverse_tunnel_service.py b/packages/syft/src/syft/service/network/reverse_tunnel_service.py index 839f29933c5..e155dd3f5b5 100644 --- a/packages/syft/src/syft/service/network/reverse_tunnel_service.py +++ b/packages/syft/src/syft/service/network/reverse_tunnel_service.py @@ -1,5 +1,5 @@ # relative -from ...types.grid_url import GridURL +from ...types.server_url import ServerURL from .rathole_config_builder import RatholeConfigBuilder from .routes import ServerRoute from .server_peer import ServerPeer @@ -21,7 +21,7 @@ def set_client_config( + f"Peer: {self_server_peer} has no rathole route: {rathole_route}" ) - remote_url = GridURL( + remote_url = ServerURL( host_or_ip=remote_server_route.host_or_ip, port=remote_server_route.port ) rathole_remote_addr = remote_url.as_container_host() diff --git a/packages/syft/src/syft/store/blob_storage/__init__.py b/packages/syft/src/syft/store/blob_storage/__init__.py index 2affff7a36a..891aee269d0 100644 --- a/packages/syft/src/syft/store/blob_storage/__init__.py +++ b/packages/syft/src/syft/store/blob_storage/__init__.py @@ -64,7 +64,7 @@ from ...types.blob_storage import CreateBlobStorageEntry from ...types.blob_storage import DEFAULT_CHUNK_SIZE from ...types.blob_storage import SecureFilePathLocation -from ...types.grid_url import GridURL +from ...types.server_url import ServerURL from ...types.syft_migration import migrate from ...types.syft_object import SYFT_OBJECT_VERSION_2 from ...types.syft_object import SYFT_OBJECT_VERSION_3 @@ -119,7 +119,7 @@ def read(self, _deserialize: bool = True) -> SyftObject | SyftError: def syft_iter_content( - blob_url: str | GridURL, + blob_url: str | ServerURL, chunk_size: int, max_retries: int = MAX_RETRIES, timeout: int = DEFAULT_TIMEOUT, @@ -154,7 +154,7 @@ class BlobRetrievalByURLV4(BlobRetrieval): __canonical_name__ = "BlobRetrievalByURL" __version__ = SYFT_OBJECT_VERSION_4 - url: GridURL | str + url: ServerURL | str @serializable() @@ -162,7 +162,7 @@ class BlobRetrievalByURL(BlobRetrieval): __canonical_name__ = "BlobRetrievalByURL" __version__ = SYFT_OBJECT_VERSION_5 - url: GridURL | str + url: ServerURL | str proxy_server_uid: UID | None = None def read(self) -> SyftObject | SyftError: @@ -192,7 +192,7 @@ def _read_data( user_verify_key=self.syft_client_verify_key, ) - if api and api.connection and isinstance(self.url, GridURL): + if api and api.connection and isinstance(self.url, ServerURL): if self.proxy_server_uid is None: blob_url = api.connection.to_blob_route( self.url.url_path, host=self.url.host_or_ip diff --git a/packages/syft/src/syft/store/blob_storage/seaweedfs.py b/packages/syft/src/syft/store/blob_storage/seaweedfs.py index 53730b1780e..35b330f6bb7 100644 --- a/packages/syft/src/syft/store/blob_storage/seaweedfs.py +++ b/packages/syft/src/syft/store/blob_storage/seaweedfs.py @@ -37,7 +37,7 @@ from ...types.blob_storage import CreateBlobStorageEntry from ...types.blob_storage import SeaweedSecureFilePathLocation from ...types.blob_storage import SecureFilePathLocation -from ...types.grid_url import GridURL +from ...types.server_url import ServerURL from ...types.syft_object import SYFT_OBJECT_VERSION_4 from ...types.uid import UID from ...util.constants import DEFAULT_TIMEOUT @@ -55,7 +55,7 @@ class SeaweedFSBlobDeposit(BlobDeposit): __canonical_name__ = "SeaweedFSBlobDeposit" __version__ = SYFT_OBJECT_VERSION_4 - urls: list[GridURL] + urls: list[ServerURL] size: int proxy_server_uid: UID | None = None @@ -187,8 +187,8 @@ class SeaweedFSClientConfig(BlobStorageClientConfig): @property def endpoint_url(self) -> str: - grid_url = GridURL(host_or_ip=self.host, port=self.port) - return grid_url.url + server_url = ServerURL(host_or_ip=self.host, port=self.port) + return server_url.url @property def mount_url(self) -> str: @@ -280,7 +280,7 @@ def write(self, obj: BlobStorageEntry) -> BlobDeposit: total_parts = math.ceil(obj.file_size / DEFAULT_FILE_PART_SIZE) urls = [ - GridURL.from_url( + ServerURL.from_url( self.client.generate_presigned_url( ClientMethod="upload_part", Params={ diff --git a/packages/syft/src/syft/types/blob_storage.py b/packages/syft/src/syft/types/blob_storage.py index c05a6a0efe4..364a3428b0b 100644 --- a/packages/syft/src/syft/types/blob_storage.py +++ b/packages/syft/src/syft/types/blob_storage.py @@ -33,7 +33,7 @@ from ..service.response import SyftError from ..service.response import SyftException from ..service.service import from_api_or_context -from ..types.grid_url import GridURL +from ..types.server_url import ServerURL from ..types.transforms import drop from ..types.transforms import keep from ..types.transforms import make_set_default @@ -261,7 +261,7 @@ def generate_url( from ..store.blob_storage import BlobRetrievalByURL return BlobRetrievalByURL( - url=GridURL.from_url(url), file_name=Path(self.path).name, type_=type_ + url=ServerURL.from_url(url), file_name=Path(self.path).name, type_=type_ ) except BotoClientError as e: raise SyftException(e) diff --git a/packages/syft/src/syft/types/grid_url.py b/packages/syft/src/syft/types/server_url.py similarity index 88% rename from packages/syft/src/syft/types/grid_url.py rename to packages/syft/src/syft/types/server_url.py index 510a95d36c4..0ccaeb10c23 100644 --- a/packages/syft/src/syft/types/grid_url.py +++ b/packages/syft/src/syft/types/server_url.py @@ -20,10 +20,10 @@ @serializable(attrs=["protocol", "host_or_ip", "port", "path", "query"]) -class GridURL: +class ServerURL: @classmethod - def from_url(cls, url: str | GridURL) -> GridURL: - if isinstance(url, GridURL): + def from_url(cls, url: str | ServerURL) -> ServerURL: + if isinstance(url, ServerURL): return url try: # urlparse doesnt handle no protocol properly @@ -38,7 +38,7 @@ def from_url(cls, url: str | GridURL) -> GridURL: host_or_ip = host_or_ip_parts[0] if parts.scheme == "https": port = 443 - return GridURL( + return ServerURL( host_or_ip=host_or_ip, path=parts.path, port=port, @@ -46,7 +46,7 @@ def from_url(cls, url: str | GridURL) -> GridURL: query=getattr(parts, "query", ""), ) except Exception as e: - logger.error(f"Failed to convert url: {url} to GridURL. {e}") + logger.error(f"Failed to convert url: {url} to ServerURL. {e}") raise e def __init__( @@ -61,11 +61,11 @@ def __init__( # port was included in the supplied host_or_ip:port combo passed in earlier match_port = re.search(":[0-9]{1,5}", host_or_ip) if match_port: - sub_grid_url: GridURL = GridURL.from_url(host_or_ip) - host_or_ip = str(sub_grid_url.host_or_ip) # type: ignore - port = int(sub_grid_url.port) # type: ignore - protocol = str(sub_grid_url.protocol) # type: ignore - path = str(sub_grid_url.path) # type: ignore + sub_server_url: ServerURL = ServerURL.from_url(host_or_ip) + host_or_ip = str(sub_server_url.host_or_ip) # type: ignore + port = int(sub_server_url.port) # type: ignore + protocol = str(sub_server_url.protocol) # type: ignore + path = str(sub_server_url.path) # type: ignore prtcl_pattrn = "://" if prtcl_pattrn in host_or_ip: @@ -146,7 +146,7 @@ def url_no_protocol(self) -> str: def url_path(self) -> str: return f"{self.path}{self.query_string}" - def to_tls(self) -> GridURL: + def to_tls(self) -> ServerURL: if self.protocol == "https": return self @@ -170,7 +170,7 @@ def __str__(self) -> str: def __hash__(self) -> int: return hash(self.__str__()) - def __copy__(self) -> GridURL: + def __copy__(self) -> ServerURL: return self.__class__.from_url(self.url) def set_port(self, port: int) -> Self: diff --git a/packages/syft/src/syft/types/transforms.py b/packages/syft/src/syft/types/transforms.py index fa5d8063f4a..60e9722a029 100644 --- a/packages/syft/src/syft/types/transforms.py +++ b/packages/syft/src/syft/types/transforms.py @@ -11,7 +11,7 @@ from ..server.credentials import SyftVerifyKey from ..service.context import AuthedServiceContext from ..service.context import ServerServiceContext -from .grid_url import GridURL +from .server_url import ServerURL from .syft_object import Context from .syft_object import SyftBaseObject from .syft_object_registry import SyftObjectRegistry @@ -157,7 +157,7 @@ def generate_action_object_id(context: TransformContext) -> TransformContext: def validate_url(context: TransformContext) -> TransformContext: if context.output and context.output["url"] is not None: - context.output["url"] = GridURL.from_url(context.output["url"]).url_no_port + context.output["url"] = ServerURL.from_url(context.output["url"]).url_no_port return context @@ -167,11 +167,11 @@ def validate_email(context: TransformContext) -> TransformContext: return context -def str_url_to_grid_url(context: TransformContext) -> TransformContext: +def str_url_to_server_url(context: TransformContext) -> TransformContext: if context.output: url = context.output.get("url", None) if url is not None and isinstance(url, str): - context.output["url"] = GridURL.from_url(str) + context.output["url"] = ServerURL.from_url(str) return context diff --git a/packages/syft/tests/conftest.py b/packages/syft/tests/conftest.py index 396c0c6f8e4..dcca9d8f113 100644 --- a/packages/syft/tests/conftest.py +++ b/packages/syft/tests/conftest.py @@ -113,10 +113,11 @@ def stage_protocol(protocol_file: Path): dp.save_history(dp.protocol_history) # Cleanup release dir, remove unused released files - for _file_path in protocol_release_dir().iterdir(): - for version in dp.read_json(_file_path): - if version not in dp.protocol_history.keys(): - _file_path.unlink() + if os.path.exists(protocol_release_dir()): + for _file_path in protocol_release_dir().iterdir(): + for version in dp.read_json(_file_path): + if version not in dp.protocol_history.keys(): + _file_path.unlink() @pytest.fixture diff --git a/packages/syft/tests/syft/migrations/protocol_communication_test.py b/packages/syft/tests/syft/migrations/protocol_communication_test.py index 81bd074f5b2..d7b9bd3ad79 100644 --- a/packages/syft/tests/syft/migrations/protocol_communication_test.py +++ b/packages/syft/tests/syft/migrations/protocol_communication_test.py @@ -1,5 +1,6 @@ # stdlib from copy import deepcopy +import os from pathlib import Path from unittest import mock @@ -174,10 +175,11 @@ def my_stage_protocol(protocol_file: Path): dp.save_history(dp.protocol_history) # Cleanup release dir, remove unused released files - for _file_path in protocol_release_dir().iterdir(): - for version in dp.read_json(_file_path): - if version not in dp.protocol_history.keys(): - _file_path.unlink() + if os.path.exists(protocol_release_dir()): + for _file_path in protocol_release_dir().iterdir(): + for version in dp.read_json(_file_path): + if version not in dp.protocol_history.keys(): + _file_path.unlink() @pytest.mark.skip( diff --git a/packages/syft/tests/syft/grid_url_test.py b/packages/syft/tests/syft/server_url_test.py similarity index 61% rename from packages/syft/tests/syft/grid_url_test.py rename to packages/syft/tests/syft/server_url_test.py index bb87c2d0d07..c23670f9f12 100644 --- a/packages/syft/tests/syft/grid_url_test.py +++ b/packages/syft/tests/syft/server_url_test.py @@ -2,7 +2,7 @@ import pytest # syft absolute -from syft.types.grid_url import GridURL +from syft.types.server_url import ServerURL test_suite = [ ("http://0.0.0.0", 8081, "http://0.0.0.0:8081"), @@ -16,12 +16,12 @@ @pytest.mark.parametrize("url, port, ground_truth", test_suite) -def test_grid_url(url, port, ground_truth) -> None: +def test_server_url(url, port, ground_truth) -> None: if not url and not port: - assert GridURL().base_url == ground_truth + assert ServerURL().base_url == ground_truth elif not url: - assert GridURL(port=port).base_url == ground_truth + assert ServerURL(port=port).base_url == ground_truth elif not port: - assert GridURL(host_or_ip=url).base_url == ground_truth + assert ServerURL(host_or_ip=url).base_url == ground_truth else: - assert GridURL(host_or_ip=url, port=port).base_url == ground_truth + assert ServerURL(host_or_ip=url, port=port).base_url == ground_truth diff --git a/tests/integration/frontend/frontend_start_test.py b/tests/integration/frontend/frontend_start_test.py index 198a45a9d5f..54490db450f 100644 --- a/tests/integration/frontend/frontend_start_test.py +++ b/tests/integration/frontend/frontend_start_test.py @@ -14,7 +14,7 @@ @pytest.mark.frontend def test_serves_datasite_frontend() -> None: - title_str = "PyGrid" + title_str = "Syft UI" url = f"http://{HOST_IP}:{DATASITE_PORT}" result = requests.get(url) assert result.status_code == 200 @@ -23,7 +23,7 @@ def test_serves_datasite_frontend() -> None: @pytest.mark.frontend def test_serves_network_frontend() -> None: - title_str = "PyGrid" + title_str = "Syft UI" url = f"http://localhost:{NETWORK_PORT}" result = requests.get(url) assert result.status_code == 200 From 09ab586eebeb5cf479f108ef76a8628cc8f2a1b0 Mon Sep 17 00:00:00 2001 From: Madhava Jay Date: Fri, 12 Jul 2024 16:50:56 +1000 Subject: [PATCH 044/117] Renamed grid-* container images to syft-* --- .github/workflows/cd-syft-dev.yml | 42 +-- .github/workflows/cd-syft.yml | 128 ++++----- .isort.cfg | 6 +- .../api_reference/syft.types.server_url.rst | 29 ++ notebooks/api/0.8/00-load-data.ipynb | 9 + notebooks/api/0.8/10-container-images.ipynb | 6 +- .../api/0.8/11-container-images-k8s.ipynb | 2 +- .../deployments/02-deploy-container.ipynb | 2 +- packages/grid/backend/backend.dockerfile | 2 +- packages/grid/backend/grid/api/new/new.py | 2 +- packages/grid/backend/grid/api/router.py | 2 +- .../grid/backend/grid/core/celery_config.py | 13 - .../grid/backend/grid/core/celery_serde.py | 46 ---- packages/grid/backend/grid/core/server.py | 2 +- .../backend/grid/images/worker_cpu.dockerfile | 4 +- packages/grid/backend/grid/main.py | 2 +- packages/grid/default.env | 20 +- packages/grid/devspace.yaml | 12 +- packages/grid/frontend/frontend.dockerfile | 6 +- .../static/assets/small-grid-symbol-logo.png | Bin 41764 -> 0 bytes .../frontend/static/assets/small-logo.png | Bin 26289 -> 24772 bytes .../static/assets/small-syft-symbol-logo.png | Bin 0 -> 33965 bytes .../backend/backend-statefulset.yaml | 6 +- .../frontend/frontend-deployment.yaml | 2 +- .../rathole/rathole-statefulset.yaml | 2 +- .../seaweedfs/seaweedfs-statefulset.yaml | 2 +- packages/grid/quickstart/template.json | 260 ------------------ .../grid/scripts/backup_server_credentials.sh | 2 +- .../assets/img/small-grid-symbol-logo.png | Bin 41764 -> 0 bytes .../assets/img/small-syft-symbol-logo.png | Bin 0 -> 33965 bytes packages/syft/src/syft/client/client.py | 2 +- .../syft/src/syft/client/enclave_client.py | 4 +- .../syft/src/syft/client/gateway_client.py | 4 +- .../src/syft/protocol/protocol_version.json | 42 ++- packages/syft/src/syft/server/uvicorn.py | 2 +- .../syft/service/settings/settings_service.py | 2 +- .../syft/src/syft/service/worker/utils.py | 2 +- packages/syft/src/syft/util/schema.py | 2 +- packages/syft/tests/syft/assets_test.py | 2 +- .../tests/syft/custom_worker/config_test.py | 2 +- .../worker_pool/worker_pool_service_test.py | 2 +- .../tests/syft/worker_pool/worker_test.py | 2 +- packages/syftcli/manifest.yml | 4 +- scripts/build_images.sh | 6 +- scripts/flush_queue.sh | 2 - .../container_workload/pool_image_test.py | 2 +- tox.ini | 6 +- 47 files changed, 224 insertions(+), 473 deletions(-) create mode 100644 docs/source/api_reference/syft.types.server_url.rst delete mode 100644 packages/grid/backend/grid/core/celery_config.py delete mode 100644 packages/grid/backend/grid/core/celery_serde.py delete mode 100644 packages/grid/frontend/static/assets/small-grid-symbol-logo.png create mode 100644 packages/grid/frontend/static/assets/small-syft-symbol-logo.png delete mode 100644 packages/grid/quickstart/template.json delete mode 100644 packages/syft/src/syft/assets/img/small-grid-symbol-logo.png create mode 100644 packages/syft/src/syft/assets/img/small-syft-symbol-logo.png delete mode 100755 scripts/flush_queue.sh diff --git a/.github/workflows/cd-syft-dev.yml b/.github/workflows/cd-syft-dev.yml index b28510a2906..0b9ce3fe27d 100644 --- a/.github/workflows/cd-syft-dev.yml +++ b/.github/workflows/cd-syft-dev.yml @@ -77,11 +77,11 @@ jobs: username: ${{ secrets.ACR_USERNAME }} password: ${{ secrets.ACR_PASSWORD }} - - name: Set Grid package version - id: grid + - name: Set Server package version + id: server shell: bash run: | - echo "GRID_VERSION=$(python packages/grid/VERSION)" >> $GITHUB_OUTPUT + echo "SERVER_VERSION=$(python packages/grid/VERSION)" >> $GITHUB_OUTPUT - name: Build and push `syft` image to registry uses: docker/build-push-action@v6 @@ -92,9 +92,9 @@ jobs: tags: | ${{ secrets.ACR_SERVER }}/openmined/syft-client:dev ${{ secrets.ACR_SERVER }}/openmined/syft-client:dev-${{ github.sha }} - ${{ secrets.ACR_SERVER }}/openmined/syft-client:${{ steps.grid.outputs.GRID_VERSION }} + ${{ secrets.ACR_SERVER }}/openmined/syft-client:${{ steps.server.outputs.SERVER_VERSION }} - - name: Build and push `grid-backend` image to registry + - name: Build and push `syft-backend` image to registry uses: docker/build-push-action@v6 with: context: ./packages @@ -102,43 +102,43 @@ jobs: push: true target: backend tags: | - ${{ secrets.ACR_SERVER }}/openmined/grid-backend:dev - ${{ secrets.ACR_SERVER }}/openmined/grid-backend:dev-${{ github.sha }} - ${{ secrets.ACR_SERVER }}/openmined/grid-backend:${{ steps.grid.outputs.GRID_VERSION }} + ${{ secrets.ACR_SERVER }}/openmined/syft-backend:dev + ${{ secrets.ACR_SERVER }}/openmined/syft-backend:dev-${{ github.sha }} + ${{ secrets.ACR_SERVER }}/openmined/syft-backend:${{ steps.syft.outputs.SERVER_VERSION }} - - name: Build and push `grid-frontend` image to registry + - name: Build and push `syft-frontend` image to registry uses: docker/build-push-action@v6 with: context: ./packages/grid/frontend file: ./packages/grid/frontend/frontend.dockerfile push: true tags: | - ${{ secrets.ACR_SERVER }}/openmined/grid-frontend:dev - ${{ secrets.ACR_SERVER }}/openmined/grid-frontend:dev-${{ github.sha }} - ${{ secrets.ACR_SERVER }}/openmined/grid-frontend:${{ steps.grid.outputs.GRID_VERSION }} - target: grid-ui-development + ${{ secrets.ACR_SERVER }}/openmined/syft-frontend:dev + ${{ secrets.ACR_SERVER }}/openmined/syft-frontend:dev-${{ github.sha }} + ${{ secrets.ACR_SERVER }}/openmined/syft-frontend:${{ steps.syft.outputs.SERVER_VERSION }} + target: syft-ui-development - - name: Build and push `grid-seaweedfs` image to registry + - name: Build and push `syft-seaweedfs` image to registry uses: docker/build-push-action@v6 with: context: ./packages/grid/seaweedfs file: ./packages/grid/seaweedfs/seaweedfs.dockerfile push: true tags: | - ${{ secrets.ACR_SERVER }}/openmined/grid-seaweedfs:dev - ${{ secrets.ACR_SERVER }}/openmined/grid-seaweedfs:dev-${{ github.sha }} - ${{ secrets.ACR_SERVER }}/openmined/grid-seaweedfs:${{ steps.grid.outputs.GRID_VERSION }} + ${{ secrets.ACR_SERVER }}/openmined/syft-seaweedfs:dev + ${{ secrets.ACR_SERVER }}/openmined/syft-seaweedfs:dev-${{ github.sha }} + ${{ secrets.ACR_SERVER }}/openmined/syft-seaweedfs:${{ steps.syft.outputs.SERVER_VERSION }} - - name: Build and push `grid-enclave-attestation` image to registry + - name: Build and push `syft-enclave-attestation` image to registry uses: docker/build-push-action@v6 with: context: ./packages/grid/enclave/attestation file: ./packages/grid/enclave/attestation/attestation.dockerfile push: true tags: | - ${{ secrets.ACR_SERVER }}/openmined/grid-enclave-attestation:dev - ${{ secrets.ACR_SERVER }}/openmined/grid-enclave-attestation:dev-${{ github.sha }} - ${{ secrets.ACR_SERVER }}/openmined/grid-enclave-attestation:${{ steps.grid.outputs.GRID_VERSION }} + ${{ secrets.ACR_SERVER }}/openmined/syft-enclave-attestation:dev + ${{ secrets.ACR_SERVER }}/openmined/syft-enclave-attestation:dev-${{ github.sha }} + ${{ secrets.ACR_SERVER }}/openmined/syft-enclave-attestation:${{ steps.syft.outputs.SERVER_VERSION }} - name: Build Helm Chart & Copy to infra if: github.ref == 'refs/heads/dev' || github.event.inputs.deploy-helm == 'true' diff --git a/.github/workflows/cd-syft.yml b/.github/workflows/cd-syft.yml index d0610ac7956..f9b0cd12295 100644 --- a/.github/workflows/cd-syft.yml +++ b/.github/workflows/cd-syft.yml @@ -90,7 +90,7 @@ jobs: outputs: release_tag: ${{ steps.get_release_tag.outputs.release_tag }} - grid_version: ${{ steps.release_metadata.outputs.grid_version }} + server_version: ${{ steps.release_metadata.outputs.server_version }} steps: - uses: actions/checkout@v4 @@ -166,7 +166,7 @@ jobs: echo "release_platform=linux/arm64" >> $GITHUB_OUTPUT echo "short_release_platform=arm64" >> $GITHUB_OUTPUT fi - echo "grid_version=$(python packages/grid/VERSION)" >> $GITHUB_OUTPUT + echo "server_version=$(python packages/grid/VERSION)" >> $GITHUB_OUTPUT # TODO: Optimize redundant bump protocol version checks - name: Check and Bump Protocol Version @@ -185,79 +185,79 @@ jobs: username: ${{ secrets.DOCKER_LOGIN }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Build and push `grid-backend` image to DockerHub - id: grid-backend-build + - name: Build and push `syft-backend` image to DockerHub + id: syft-backend-build uses: docker/build-push-action@v6 with: context: ./packages file: ./packages/grid/backend/backend.dockerfile platforms: ${{ steps.release_metadata.outputs.release_platform }} target: backend - outputs: type=image,name=openmined/grid-backend,push-by-digest=true,name-canonical=true,push=true - cache-from: type=registry,ref=openmined/grid-backend:cache-${{ steps.release_metadata.outputs.short_release_platform }} - cache-to: type=registry,ref=openmined/grid-backend:cache-${{ steps.release_metadata.outputs.short_release_platform }},mode=max + outputs: type=image,name=openmined/syft-backend,push-by-digest=true,name-canonical=true,push=true + cache-from: type=registry,ref=openmined/syft-backend:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-backend:cache-${{ steps.release_metadata.outputs.short_release_platform }},mode=max - - name: Export digest for grid-backend + - name: Export digest for syft-backend run: | - mkdir -p /tmp/digests/grid-backend - digest="${{ steps.grid-backend-build.outputs.digest }}" - touch "/tmp/digests/grid-backend/${digest#sha256:}" + mkdir -p /tmp/digests/syft-backend + digest="${{ steps.syft-backend-build.outputs.digest }}" + touch "/tmp/digests/syft-backend/${digest#sha256:}" - - name: Build and push `grid-frontend` image to DockerHub - id: grid-frontend-build + - name: Build and push `syft-frontend` image to DockerHub + id: syft-frontend-build uses: docker/build-push-action@v6 with: context: ./packages/grid/frontend file: ./packages/grid/frontend/frontend.dockerfile platforms: ${{ steps.release_metadata.outputs.release_platform }} - outputs: type=image,name=openmined/grid-frontend,push-by-digest=true,name-canonical=true,push=true - target: grid-ui-development - cache-from: type=registry,ref=openmined/grid-frontend:cache-${{ steps.release_metadata.outputs.short_release_platform }} - cache-to: type=registry,ref=openmined/grid-frontend:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max + outputs: type=image,name=openmined/syft-frontend,push-by-digest=true,name-canonical=true,push=true + target: syft-ui-development + cache-from: type=registry,ref=openmined/syft-frontend:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-frontend:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max - - name: Export digest for grid-frontend + - name: Export digest for syft-frontend run: | - mkdir -p /tmp/digests/grid-frontend - digest="${{ steps.grid-frontend-build.outputs.digest }}" - touch "/tmp/digests/grid-frontend/${digest#sha256:}" + mkdir -p /tmp/digests/syft-frontend + digest="${{ steps.syft-frontend-build.outputs.digest }}" + touch "/tmp/digests/syft-frontend/${digest#sha256:}" - - name: Build and push `grid-seaweedfs` image to DockerHub - id: grid-seaweedfs-build + - name: Build and push `syft-seaweedfs` image to DockerHub + id: syft-seaweedfs-build uses: docker/build-push-action@v6 with: context: ./packages/grid/seaweedfs file: ./packages/grid/seaweedfs/seaweedfs.dockerfile platforms: ${{ steps.release_metadata.outputs.release_platform }} - outputs: type=image,name=openmined/grid-seaweedfs,push-by-digest=true,name-canonical=true,push=true - cache-from: type=registry,ref=openmined/grid-seaweedfs:cache-${{ steps.release_metadata.outputs.short_release_platform }} - cache-to: type=registry,ref=openmined/grid-seaweedfs:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max + outputs: type=image,name=openmined/syft-seaweedfs,push-by-digest=true,name-canonical=true,push=true + cache-from: type=registry,ref=openmined/syft-seaweedfs:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-seaweedfs:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max - - name: Export digest for grid-seaweedfs + - name: Export digest for syft-seaweedfs run: | - mkdir -p /tmp/digests/grid-seaweedfs - digest="${{ steps.grid-seaweedfs-build.outputs.digest }}" - touch "/tmp/digests/grid-seaweedfs/${digest#sha256:}" + mkdir -p /tmp/digests/syft-seaweedfs + digest="${{ steps.syft-seaweedfs-build.outputs.digest }}" + touch "/tmp/digests/syft-seaweedfs/${digest#sha256:}" - # Some of the dependencies of grid-enclave-attestation are not available for arm64 - # Hence, we are building grid-enclave-attestation only for x64 (see the `if` conditional) - - name: Build and push `grid-enclave-attestation` image to DockerHub + # Some of the dependencies of syft-enclave-attestation are not available for arm64 + # Hence, we are building syft-enclave-attestation only for x64 (see the `if` conditional) + - name: Build and push `syft-enclave-attestation` image to DockerHub if: ${{ endsWith(matrix.runner, '-x64') }} - id: grid-enclave-attestation-build + id: syft-enclave-attestation-build uses: docker/build-push-action@v6 with: context: ./packages/grid/enclave/attestation file: ./packages/grid/enclave/attestation/attestation.dockerfile platforms: ${{ steps.release_metadata.outputs.release_platform }} - outputs: type=image,name=openmined/grid-enclave-attestation,push-by-digest=true,name-canonical=true,push=true - cache-from: type=registry,ref=openmined/grid-enclave-attestation:cache-${{ steps.release_metadata.outputs.short_release_platform }} - cache-to: type=registry,ref=openmined/grid-enclave-attestation:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max + outputs: type=image,name=openmined/syft-enclave-attestation,push-by-digest=true,name-canonical=true,push=true + cache-from: type=registry,ref=openmined/syft-enclave-attestation:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-enclave-attestation:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max - - name: Export digest for grid-enclave-attestation + - name: Export digest for syft-enclave-attestation if: ${{ endsWith(matrix.runner, '-x64') }} run: | - mkdir -p /tmp/digests/grid-enclave-attestation - digest="${{ steps.grid-enclave-attestation-build.outputs.digest }}" - touch "/tmp/digests/grid-enclave-attestation/${digest#sha256:}" + mkdir -p /tmp/digests/syft-enclave-attestation + digest="${{ steps.syft-enclave-attestation-build.outputs.digest }}" + touch "/tmp/digests/syft-enclave-attestation/${digest#sha256:}" - name: Build and push `syft` image to registry id: syft-build @@ -279,7 +279,7 @@ jobs: - name: Upload digests uses: actions/upload-artifact@v4 with: - name: digests-${{ steps.release_metadata.outputs.grid_version }}-${{ steps.release_metadata.outputs.short_release_platform }} + name: digests-${{ steps.release_metadata.outputs.server_version }}-${{ steps.release_metadata.outputs.short_release_platform }} path: /tmp/digests/* if-no-files-found: error retention-days: 1 @@ -299,7 +299,7 @@ jobs: uses: actions/download-artifact@v4 with: path: /tmp/digests - pattern: digests-${{ needs.build-and-push-docker-images.outputs.grid_version }}-* + pattern: digests-${{ needs.build-and-push-docker-images.outputs.server_version }}-* merge-multiple: true - name: Set up Docker Buildx @@ -311,43 +311,43 @@ jobs: username: ${{ secrets.DOCKER_LOGIN }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Create manifest list and push for grid-backend - working-directory: /tmp/digests/grid-backend + - name: Create manifest list and push for syft-backend + working-directory: /tmp/digests/syft-backend run: | docker buildx imagetools create \ - -t openmined/grid-backend:${{ needs.build-and-push-docker-images.outputs.grid_version }} \ - -t openmined/grid-backend:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ - $(printf 'openmined/grid-backend@sha256:%s ' *) + -t openmined/syft-backend:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + -t openmined/syft-backend:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ + $(printf 'openmined/syft-backend@sha256:%s ' *) - - name: Create manifest list and push for grid-frontend - working-directory: /tmp/digests/grid-frontend + - name: Create manifest list and push for syft-frontend + working-directory: /tmp/digests/syft-frontend run: | docker buildx imagetools create \ - -t openmined/grid-frontend:${{ needs.build-and-push-docker-images.outputs.grid_version }} \ - -t openmined/grid-frontend:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ - $(printf 'openmined/grid-frontend@sha256:%s ' *) + -t openmined/syft-frontend:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + -t openmined/syft-frontend:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ + $(printf 'openmined/syft-frontend@sha256:%s ' *) - - name: Create manifest list and push for grid-seaweedfs - working-directory: /tmp/digests/grid-seaweedfs + - name: Create manifest list and push for syft-seaweedfs + working-directory: /tmp/digests/syft-seaweedfs run: | docker buildx imagetools create \ - -t openmined/grid-seaweedfs:${{ needs.build-and-push-docker-images.outputs.grid_version }} \ - -t openmined/grid-seaweedfs:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ - $(printf 'openmined/grid-seaweedfs@sha256:%s ' *) + -t openmined/syft-seaweedfs:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + -t openmined/syft-seaweedfs:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ + $(printf 'openmined/syft-seaweedfs@sha256:%s ' *) - - name: Create manifest list and push for grid-enclave-attestation - working-directory: /tmp/digests/grid-enclave-attestation + - name: Create manifest list and push for syft-enclave-attestation + working-directory: /tmp/digests/syft-enclave-attestation run: | docker buildx imagetools create \ - -t openmined/grid-enclave-attestation:${{ needs.build-and-push-docker-images.outputs.grid_version }} \ - -t openmined/grid-enclave-attestation:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ - $(printf 'openmined/grid-enclave-attestation@sha256:%s ' *) + -t openmined/syft-enclave-attestation:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + -t openmined/syft-enclave-attestation:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ + $(printf 'openmined/syft-enclave-attestation@sha256:%s ' *) - name: Create manifest list and push for syft working-directory: /tmp/digests/syft run: | docker buildx imagetools create \ - -t openmined/syft-client:${{ needs.build-and-push-docker-images.outputs.grid_version }} \ + -t openmined/syft-client:${{ needs.build-and-push-docker-images.outputs.server_version }} \ -t openmined/syft-client:${{ needs.build-and-push-docker-images.outputs.release_tag }} \ $(printf 'openmined/syft-client@sha256:%s ' *) diff --git a/.isort.cfg b/.isort.cfg index 5c9360d3549..aeb09bb8f36 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -2,18 +2,18 @@ profile=black force_single_line=True known_syft=syft -known_grid=grid +known_server=grid known_syftcli=syftcli known_first_party=src remove_redundant_aliases=True -sections=FUTURE,STDLIB,THIRDPARTY,SYFT,GRID,SYFTCLI,FIRSTPARTY,LOCALFOLDER +sections=FUTURE,STDLIB,THIRDPARTY,SYFT,SERVER,SYFTCLI,FIRSTPARTY,LOCALFOLDER lines_between_types=0 force_sort_within_sections=True import_heading_future=future import_heading_stdlib=stdlib import_heading_thirdparty=third party import_heading_syft=syft absolute -import_heading_grid=grid absolute +import_heading_server=server absolute import_heading_syftcli=syftcli absolute import_heading_firstparty=first party import_heading_localfolder=relative diff --git a/docs/source/api_reference/syft.types.server_url.rst b/docs/source/api_reference/syft.types.server_url.rst new file mode 100644 index 00000000000..c9ad2ab0625 --- /dev/null +++ b/docs/source/api_reference/syft.types.server_url.rst @@ -0,0 +1,29 @@ +syft.types.server\_url +==================== + +.. automodule:: syft.types.server_url + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + + ServerURL + + + + + + + + + diff --git a/notebooks/api/0.8/00-load-data.ipynb b/notebooks/api/0.8/00-load-data.ipynb index 57f38ceaafb..5370bd2e595 100644 --- a/notebooks/api/0.8/00-load-data.ipynb +++ b/notebooks/api/0.8/00-load-data.ipynb @@ -84,6 +84,15 @@ "datasite_client = server.login(email=\"info@openmined.org\", password=\"changethis\")" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "datasite_client" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/notebooks/api/0.8/10-container-images.ipynb b/notebooks/api/0.8/10-container-images.ipynb index f3412e4def9..22e4706bf7f 100644 --- a/notebooks/api/0.8/10-container-images.ipynb +++ b/notebooks/api/0.8/10-container-images.ipynb @@ -169,7 +169,7 @@ "outputs": [], "source": [ "opendp_dockerfile_str = f\"\"\"\n", - "FROM openmined/grid-backend:{syft_base_worker_tag}\n", + "FROM openmined/syft-backend:{syft_base_worker_tag}\n", "\n", "RUN uv pip install opendp\n", "\n", @@ -1080,7 +1080,7 @@ "outputs": [], "source": [ "custom_dockerfile_str_2 = f\"\"\"\n", - "FROM openmined/grid-backend:{syft_base_worker_tag}\n", + "FROM openmined/syft-backend:{syft_base_worker_tag}\n", "\n", "RUN uv pip install opendp\n", "\"\"\".strip()\n", @@ -1296,7 +1296,7 @@ "outputs": [], "source": [ "custom_dockerfile_str_3 = f\"\"\"\n", - "FROM openmined/grid-backend:{syft_base_worker_tag}\n", + "FROM openmined/syft-backend:{syft_base_worker_tag}\n", "\n", "RUN uv pip install recordlinkage\n", "\"\"\".strip()\n", diff --git a/notebooks/api/0.8/11-container-images-k8s.ipynb b/notebooks/api/0.8/11-container-images-k8s.ipynb index a2ec5be3920..68620d9c114 100644 --- a/notebooks/api/0.8/11-container-images-k8s.ipynb +++ b/notebooks/api/0.8/11-container-images-k8s.ipynb @@ -250,7 +250,7 @@ "from syft.util.util import get_latest_tag\n", "\n", "registry = os.getenv(\"SYFT_BASE_IMAGE_REGISTRY\", \"docker.io\")\n", - "repo = \"openmined/grid-backend\"\n", + "repo = \"openmined/syft-backend\"\n", "\n", "if \"k3d\" in registry:\n", " tag = get_latest_tag(registry, repo)\n", diff --git a/notebooks/tutorials/deployments/02-deploy-container.ipynb b/notebooks/tutorials/deployments/02-deploy-container.ipynb index c677b1b6fc2..6c8b5bbfdb8 100644 --- a/notebooks/tutorials/deployments/02-deploy-container.ipynb +++ b/notebooks/tutorials/deployments/02-deploy-container.ipynb @@ -65,7 +65,7 @@ " -e CREATE_PRODUCER=true \\\n", " -e INMEMORY_WORKERS=true \\\n", " -p 8080:80 --add-host=host.docker.internal:host-gateway \\\n", - " --name syft-example-datasite-1 openmined/grid-backend:$SYFT_VERSION\n", + " --name syft-example-datasite-1 openmined/syft-backend:$SYFT_VERSION\n", "```" ] }, diff --git a/packages/grid/backend/backend.dockerfile b/packages/grid/backend/backend.dockerfile index 28af9aeb24c..256fdfd447b 100644 --- a/packages/grid/backend/backend.dockerfile +++ b/packages/grid/backend/backend.dockerfile @@ -60,7 +60,7 @@ WORKDIR /root/app/ # Copy pre-built syft dependencies COPY --from=syft_deps /root/app/.venv .venv -# copy grid +# copy server COPY grid/backend/grid ./grid/ # copy syft diff --git a/packages/grid/backend/grid/api/new/new.py b/packages/grid/backend/grid/api/new/new.py index 3bb7b35abf1..3ff61bb041b 100644 --- a/packages/grid/backend/grid/api/new/new.py +++ b/packages/grid/backend/grid/api/new/new.py @@ -1,7 +1,7 @@ # syft absolute from syft.server.routes import make_routes -# grid absolute +# server absolute from grid.core.server import worker router = make_routes(worker=worker) diff --git a/packages/grid/backend/grid/api/router.py b/packages/grid/backend/grid/api/router.py index 020491323a6..8412869db53 100644 --- a/packages/grid/backend/grid/api/router.py +++ b/packages/grid/backend/grid/api/router.py @@ -7,7 +7,7 @@ # third party from fastapi import APIRouter -# grid absolute +# server absolute from grid.api.new.new import router as new_router api_router = APIRouter() diff --git a/packages/grid/backend/grid/core/celery_config.py b/packages/grid/backend/grid/core/celery_config.py deleted file mode 100644 index 20fa3f55544..00000000000 --- a/packages/grid/backend/grid/core/celery_config.py +++ /dev/null @@ -1,13 +0,0 @@ -worker_send_task_event = False -task_ignore_result = True -task_time_limit = 1500 # Rasswanth: should modify after optimizing PC -task_acks_late = True -broker_pool_limit = 500 -worker_prefetch_multiplier = 1 -task_routes = { - "grid.worker.msg_without_reply": "main-queue", - "delivery_mode": "transient", -} -accept_content = ["application/syft"] -task_serializer = "syft" -result_serializer = "syft" diff --git a/packages/grid/backend/grid/core/celery_serde.py b/packages/grid/backend/grid/core/celery_serde.py deleted file mode 100644 index 005e4a4f514..00000000000 --- a/packages/grid/backend/grid/core/celery_serde.py +++ /dev/null @@ -1,46 +0,0 @@ -# stdlib -from typing import Any - -# third party -from kombu import serialization - -# syft absolute -import syft as sy -from syft.logger import error - - -def loads(data: bytes) -> Any: - # original payload might have nested bytes in the args - org_payload = sy.deserialize(data, from_bytes=True) - # original payload is found at org_payload[0][0] - if ( - len(org_payload) > 0 - and len(org_payload[0]) > 0 - and isinstance(org_payload[0][0], bytes) - ): - try: - nested_data = org_payload[0][0] - org_obj = sy.deserialize(nested_data, from_bytes=True) - org_payload[0][0] = org_obj - except Exception as e: - error(f"Unable to deserialize nested payload. {e}") - raise e - - return org_payload - - -def dumps(obj: Any) -> bytes: - # this is usually a Tuple of args where the first one is what we send to the task - # but it can also get other arbitrary data which we need to serde - # since we might get bytes directly from the web endpoint we can avoid double - # unserializing it by keeping it inside the nested args list org_payload[0][0] - return sy.serialize(obj, to_bytes=True) - - -serialization.register( - "syft", - dumps, - loads, - content_type="application/syft", - content_encoding="binary", -) diff --git a/packages/grid/backend/grid/core/server.py b/packages/grid/backend/grid/core/server.py index 1e692de29a7..9802eece8e8 100644 --- a/packages/grid/backend/grid/core/server.py +++ b/packages/grid/backend/grid/core/server.py @@ -20,7 +20,7 @@ from syft.store.sqlite_document_store import SQLiteStoreConfig from syft.types.uid import UID -# grid absolute +# server absolute from grid.core.config import settings diff --git a/packages/grid/backend/grid/images/worker_cpu.dockerfile b/packages/grid/backend/grid/images/worker_cpu.dockerfile index 94297fee0a9..3095c703e22 100644 --- a/packages/grid/backend/grid/images/worker_cpu.dockerfile +++ b/packages/grid/backend/grid/images/worker_cpu.dockerfile @@ -2,11 +2,11 @@ # Build as-is to create a base worker image # Build with args to create a custom worker image -# NOTE: This dockerfile will be built inside a grid-backend container in PROD +# NOTE: This dockerfile will be built inside a syft-backend container in PROD # Hence COPY will not work the same way in DEV vs. PROD ARG SYFT_VERSION_TAG="0.8.7-beta.13" -FROM openmined/grid-backend:${SYFT_VERSION_TAG} +FROM openmined/syft-backend:${SYFT_VERSION_TAG} # should match base image python version ARG PYTHON_VERSION="3.12" diff --git a/packages/grid/backend/grid/main.py b/packages/grid/backend/grid/main.py index 461e76de6b0..497a2dd7a90 100644 --- a/packages/grid/backend/grid/main.py +++ b/packages/grid/backend/grid/main.py @@ -11,7 +11,7 @@ # syft absolute from syft.protocol.data_protocol import stage_protocol_changes -# grid absolute +# server absolute from grid.api.router import api_router from grid.core.config import settings from grid.core.server import worker diff --git a/packages/grid/default.env b/packages/grid/default.env index 29f73b65900..e3edfdc38df 100644 --- a/packages/grid/default.env +++ b/packages/grid/default.env @@ -2,7 +2,7 @@ DATASITE=localhost SERVER_NAME=default_server_name SERVER_TYPE=datasite -FRONTEND_TARGET=grid-ui-development +FRONTEND_TARGET=syft-ui-development PORT=80 HTTP_PORT=80 HTTPS_PORT=443 @@ -15,26 +15,26 @@ IGNORE_TLS_ERRORS=False TRAEFIK_TLS_CONF=./traefik/dynamic-configurations TRAEFIK_TLS_CERTS=./traefik/certs TRAEFIK_PUBLIC_NETWORK=traefik-public -TRAEFIK_TAG=grid.openmined.org +TRAEFIK_TAG=syft.openmined.org TRAEFIK_PUBLIC_TAG=traefik-public -STACK_NAME=grid-openmined-org -DOCKER_IMAGE_BACKEND=openmined/grid-backend -DOCKER_IMAGE_FRONTEND=openmined/grid-frontend -DOCKER_IMAGE_RATHOLE=openmined/grid-rathole +STACK_NAME=syft-openmined-org +DOCKER_IMAGE_BACKEND=openmined/syft-backend +DOCKER_IMAGE_FRONTEND=openmined/syft-frontend +DOCKER_IMAGE_RATHOLE=openmined/syft-rathole DOCKER_IMAGE_TRAEFIK=traefik TRAEFIK_VERSION=v2.11.0 REDIS_VERSION=6.2 RABBITMQ_VERSION=3 -DOCKER_IMAGE_SEAWEEDFS=openmined/grid-seaweedfs +DOCKER_IMAGE_SEAWEEDFS=openmined/syft-seaweedfs VERSION=latest VERSION_HASH=unknown STACK_API_KEY="" # Backend -BACKEND_CORS_ORIGINS='["http://localhost","http://localhost:4200","http://localhost:3000","http://localhost:8080","https://localhost","https://localhost:4200","https://localhost:3000","https://localhost:8080","http://dev.grid.openmined.org","https://stag.grid.openmined.org","https://grid.openmined.org"]' +BACKEND_CORS_ORIGINS='["http://localhost","http://localhost:4200","http://localhost:3000","http://localhost:8080","https://localhost","https://localhost:4200","https://localhost:3000","https://localhost:8080","http://dev.syft.openmined.org","https://stag.syft.openmined.org","https://syft.openmined.org"]' SEAWEED_MOUNT_PORT=4001 -PROJECT_NAME=grid +PROJECT_NAME=syft SECRET_KEY=changethis DEFAULT_ROOT_EMAIL=info@openmined.org DEFAULT_ROOT_PASSWORD=changethis @@ -110,7 +110,7 @@ USE_BLOB_STORAGE=False ENABLE_SIGNUP=False # Enclave Attestation -DOCKER_IMAGE_ENCLAVE_ATTESTATION=openmined/grid-enclave-attestation +DOCKER_IMAGE_ENCLAVE_ATTESTATION=openmined/syft-enclave-attestation # Rathole Config RATHOLE_PORT=2333 \ No newline at end of file diff --git a/packages/grid/devspace.yaml b/packages/grid/devspace.yaml index 63623d712ff..0a00e7767f7 100644 --- a/packages/grid/devspace.yaml +++ b/packages/grid/devspace.yaml @@ -22,11 +22,11 @@ pipelines: create_deployments --all vars: - DOCKER_IMAGE_BACKEND: openmined/grid-backend - DOCKER_IMAGE_FRONTEND: openmined/grid-frontend - DOCKER_IMAGE_SEAWEEDFS: openmined/grid-seaweedfs - DOCKER_IMAGE_RATHOLE: openmined/grid-rathole - DOCKER_IMAGE_ENCLAVE_ATTESTATION: openmined/grid-enclave-attestation + DOCKER_IMAGE_BACKEND: openmined/syft-backend + DOCKER_IMAGE_FRONTEND: openmined/syft-frontend + DOCKER_IMAGE_SEAWEEDFS: openmined/syft-seaweedfs + DOCKER_IMAGE_RATHOLE: openmined/syft-rathole + DOCKER_IMAGE_ENCLAVE_ATTESTATION: openmined/syft-enclave-attestation CONTAINER_REGISTRY: "docker.io" VERSION: "0.8.7-beta.13" PLATFORM: $(uname -m | grep -q 'arm64' && echo "arm64" || echo "amd64") @@ -48,7 +48,7 @@ images: buildKit: args: ["--platform", "linux/${PLATFORM}"] dockerfile: ./frontend/frontend.dockerfile - target: "grid-ui-production" + target: "syft-ui-production" context: ./frontend tags: - dev-${DEVSPACE_TIMESTAMP} diff --git a/packages/grid/frontend/frontend.dockerfile b/packages/grid/frontend/frontend.dockerfile index 4dd570dd206..7dd46d4a888 100644 --- a/packages/grid/frontend/frontend.dockerfile +++ b/packages/grid/frontend/frontend.dockerfile @@ -22,14 +22,14 @@ FROM base AS dependencies RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile -FROM dependencies as grid-ui-tests +FROM dependencies as syft-ui-tests COPY vite.config.ts ./ COPY ./tests ./tests COPY ./src/ ./src CMD pnpm test:unit -FROM dependencies as grid-ui-development +FROM dependencies as syft-ui-development ENV SERVER_ENV=development @@ -41,7 +41,7 @@ FROM dependencies AS builder COPY . . RUN pnpm build -FROM base AS grid-ui-production +FROM base AS syft-ui-production ENV SERVER_ENV=production diff --git a/packages/grid/frontend/static/assets/small-grid-symbol-logo.png b/packages/grid/frontend/static/assets/small-grid-symbol-logo.png deleted file mode 100644 index b8956c2adec8f91eae3cc718be1626a5e39f2808..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41764 zcmV*qKt;caP)@~0drDELIAGL9O(c600d`2O+f$vv5yPRMRq}~MO*sQbW?2=MU+xnw3TZOi6tQ+68r8{?LvYiBxq8*8@1%GC@QJ8 zD50(DqP3)!h=lC9%Q;hQ?sFGhsj5g-SQy#*%T z)uFewoc8t8K7tx*NEtN(tfAX6@3nc~XMmHD!GY8S>xldS{iaA_5dLMLd0B2PJUMpc z*mkI)hLlhvz#6&*h{zs%b?!FBI`%VSyK{;3h7;*&mY-P;;WtIJe?DZup3&;et4|nl z!n=$ygc@q7GHL`^L+ZHq<$DKWUExqVoI)*bS4-{js!vIP4&9MT{E$M-z(U=9r|f>* zhfqTeRYZ*dYe)?(EiLu9!K#c%vNCgl6b64X#bCr~568mfYpH}myc>sEUkInABc(g+^Wb&de}Q4f&-%ML_>>}`f@w#nM& zjNfg1E7VX!g{To=4PC%Y4}~k(9Wlk+8>w-eu7zX58fAqF)9tf6B3=9Rg_+gag6YCYqr32o;Q9QXt%xIxzl5TzM_J^`{| zc*OPOJf9Wus_}b{c?W8!Ap$i5tRXQT{mZn$tkkqWHJfXQY_=vsYeEItkx7~^0s7`| zm`X%SbBPWxv%}OLTKV+bOKT&>HKw7vI-+GueNGHL`^LnNMfW!8>FXj7<w2s!8b_NmDE<_}HA~Uz_ zr&flf9Ls4}ZxBRn0wb4@aLiyCns^UuUw_5KkrUTL4I4db1XzQBg>TO6-`>XdBgOP{ z;*GB(3lbHt=+JQ!{1hfIaN%VFl#ktmPy&=kfB_Wq1jS?DyPWrbOcQR^bEStTetYaP zs9~c;jR0#X!y>+pcH9X}?Q9e9$K*7?C%JF}1m{>Jz@P#whf}CVo;(4%i2&`Bwe<5k zWq#M7_4w%V2iB&|Y>cQ8U=8rpOVhU3^tvfT6UQNFL*;%uS*gVmAOy({r1YvvfT1RG zBmug91sWuI6wsJHX|J&_Lk$}hY6Q3uiw&IJ*wi+6{BGlmP(zCRGT)_cTpq2jRXr8&+a#{)OHTt^07oh+w-HdJOT1#<^GyZ zD={HBjYTFjUNyRLcyl*x0z@v6DDzkC5AwEKD;a3_VVic<|?ODsXF-Jf!i06ol8VZw6UoVfSs?+s{f4|^EXR*n58PP-rp@$D)CjN-fXJ`0v2nl=bUP=~!@9fWChp589(OMRR!;#| zOn^c<)gwU3B!3T0oK-Be-f_VJ^l7o}qN*XD-p@7CC7wvt*f1rlUqDFwd z2(SJ5hW)@`Q%GeTM8uPmRiAro|3(vF+4OY$-HFgLskz~ORhL{b#t|TZzq?FDCU7SR zknhh+l!tq<5F|k1T$QKqVN$+tAR1S<;=7O5MvJov4Ql8WSiE?49U8DFJy|2@G#7Xh zJ@_8{+l_ymeM8p&Rs98#;e7P*LIWX1*j2VFGWjBi@xKQ?{016atG5>cOKo!?X6*7 znFNCbD4wGTcTVR&p=Ea{jyj`0Z-8)btz&?PNUb<#`2K7_uW*$cm<50_uAB|Nl zh4YR(Nr3X+fAWBaDs8putb7!>I|xvfKM(XTs6fSe6pZ5Zvq#o;l|eEt-uifTw-{W)&|d>Tl=O+uSAUi`xxGQGhe@c{eb;R^;`wkSKYvQm<3ZfI31?5 z1Zcq`Fnf-mL~0@GG8F<05Lvhaj9NJYQEJhTw1nbaYnTm>pEt6(_EouFj2Z#+1&`!5BM_?(#15TYSTBGrb{K)3o$Zj7%Z5m7;#mJHQ_CjIZgN9*_rAK!GJ-x-ysVBU&@*TSH zcEpf#go;xN7ArnAp8OPk5EdUpXFnQLj#q%;;C=`8`?|*J zuB6kEV0{D$qD|Xq1sA6P-88%22dFkzS%jY)kA?0K6W{-bC31V+H1YcWo3t*dO>60U zs1e{sgco1DX=q7f`_WCmnjZeoQy*Q~0+7vJnZS~)^EInQfT2WI0Rbw^->9^C@^i|G zG{ErzBHooVv|mmddEAFkL!U&A08_%h7Us8a1X#8MnWB&}EPUnq;X39{WT1^F64)*| z0fwtZRezxyuA)A`ln9Ww@?!{ay@_mou28&c()Y)_0~tjAsRy=)#`a~kuhn%OH3FwRS6Jz6E-;kQgy7MI(c5x;F{uk{AbptwOHL4_51Dc1uWE^O!Ac47d&ekINPi% zzE&f`&Z9*X>2jN4y#Mwm+X6Hv9lexCl8&D&_F2Y)u`>m};>`l$_LV7TF zr-nJe_VGs`>47iN=|AXEzZRhB`7i8w?sCWwEH(Jdi&HnNugi@>Q$L-YwkJYsbO%DR zK!85Ug|7mMG=Jqdw(MJGGV`unu6WmHPkr=1QduTs2&1TNeSO$r`!dwdNBdI;13XVp z@gh~V_IDbnzNVyWzpD{pWvCHg7x3Z2%eN`%`uRi>N7CtL!UI``LxRkEI19uRPov2$ z{Nmmh{}VEZg)dFp-qdt!N!_JHHub7?zNRp5Fi9UEAHQ>hAila&%mL)j6A&ON^Af42 zhXA!1D~rXyX3>PaZsEP#l#pG(kXc{$8!C9p*JYn|0BBE{h*w;8z%hS;8WN#KfStg5 zFXgv~B0G^WHib_6TW+3N=7jMcLi=|c7MfPtOUuEv zq;9sS>dS?yK9EQdK$vGs53ywyF98!DFG^71RhY0p44fZzR&&OG8GA2=+&- z6WTH3_{Jy`p6llITQOd>xK(dGrtBXEm{X0S@#_&I^O;*^@Z`(43}hNRlpf3}L|(f_ zE5OVV;D@GZ&H!D%Z_@7Bo6nbDxG>iMOZTPgI)}=;Kbht_@1K+aQ4zroivOVco{DYp<-<5X&#M^Pi)&T{%1^D^_ZC z@9(k4S#6LZsp=m@GGz%6lSR%YdX)X5t92%Yz^)0z|gXGItp>uUPc{6E9`W z+_l&`zA@Xu>hAyQ9_OrJ_GZtS!GguJ`!N&0Pp^eD zsl0pA$Zn%gZvLjJX24B7iY(LvMiC%@a)}!P4VvQn%+#iqjKbq*>~&J+`n_f@oY{Yk zF=T(x@KU;lofzM?qR0=`geZg!SAU|1NwlkJ|E3z8!3xHc7ax4=`&nyS-H93ja#+4F z|MgN1&!^V&BPfr+`Tblj+y@XKISB?7AB$CiHZdR+h&)~}5U%>l_byxn8AQtqw`|tX zlpBpuo~yPwzb_!K04x!vg&*X2@>6?7*WQgpCv%Jpm&1#Vp$ozJw-D0S%6$ z3MqfWFx-??xG{w?bUcFO79>IBZi6acQdcDn*dL09`EzYq@ud;X`2u7NkH2)s7G|9} zk;;1-m3>&J2{4HX>=Gp6dQzW{mvY8+r+;(In^{vb)^}Up-J-AyUEm}t=P~5e&-Rhp zPbbu0yz=w&iOIvH8}j=S;^lh7TQ6;F-!I;%3DDX`eizL=j2^1<=t12TtnckQh$1|h z+{$j1n!+r39yVc?k3S#vd^96JbUjwdfb(H|SLVk)9ZSeJ$O(hto;Fb8LmX7JX(hP9bEg;xIcg0L>Bz%WvDiNiVnCw1gZH41Hyeq&@llT#ZW zes%VVz_f`p^tx+YA7Cf}qJQn2++IS5w{0jE?mTOclUG8hm-HnUL?;0G^GX=>;gv^DBx-b6TrE`G4@>ywg; z;G0)gX$sO}Y9*&~6G|^E0a`&!AafUINbDNOH+FXY@LI`*o^)v{V1mLz-E-=_`9*{03wY_q{Ur>zZz!Ol79Q5*(P60G$Dj5}>xg zK;w>O8~*oP7W=5KUpRL-V*Ml<5g$v}Gu(Aokzd(8aG-eEhOkvd>aP<7D3z_94juv> zZp!a}OeWh_SJCGQ&>}ufGse*UJf0Y2XCf#qsO)%DMuM)JZ=pfF=?mc`7-w!vD$qGb zdS3JoX$)YV!OUN-ZtwVTWX6c%mM3p%7&g5B?k3_{RP6o8gzqmBxkP|i-a+S8>Y={@ zvETFKcgx^5RSV}1Zi4#bNa0QZ)7%-#`ziY9l=?%38}HQ#^6Lcg$zK1Xi+LP!xjCT! z^FMuQprp?dAhwLsmk;~W?o0=3!-5~vUp*+uOLfjqT2_aTHiau05b;QiB}?BWLH}GN z5K>bM>Ete>ad69S8T^Jt%i`IC3asvQQh}rhVfzpQY&FolU9U6eob7ibE-$6eiO2RrmWPA-|~f1(^6JqWIf}Z@RvvuY4b+ z&k>-tKi~dCzPz>3U|vQ~(?N7sw?bgjb+T9zbVq7c{z<0BbY@gIE(~u92UVa?q;%Xy zm;5AYs2O!1Z+J0lBgV5A&#r4|XxL6Gm=jH=9Y&a^zG-9Ol;2oPKH^`C8NoJGCtR$tRD0e|5vjs%mL!mfLOxR@VVNq7)cfk{S%y}T6P z>j04iEkgO2EdG0;BX{*TMo!7xh+ckSKDYgl?RTYz>OwN&hY+FMZkUB%XHi|uUc9(& zUE5n^>cTi0Kr6Q`o;;#e9D{iCRTU4C#p??BC6tI5%<*G-5&ycRw_khJ_s4t$y%c?d z09QVH?I1I^?r_kxi|7@#Q<$miB0xM!KhB@2{1mDW{J<^|Ripx)=y73OGdQRM9pYnh zSnU&rIH%P#Z{KUL^J`lpRe)=sojr)BO0b3k+z1-n)f>0n>eU4J(Sm%x#sS5zGL2noT3ZP*s8=PfM|RsSpSeu}vV{DC1^osLUHerq?6w7N z+mZ5hkRK+T1Uok>%)51dZeTRQqL8+-FHrJx6{7hFpg!x{ zdz}3{s3Cyse>d;*TAh9Y-H2vH=C!RZ5nzStFP=2JIO5wyvXGaHSNFcCUr*c$Ea!6+TCwaMQK7`Zw&c~ z=ba}%RXp)D1LTLH&eqrJ-lv}jn1Oe|;{Rs4ZS@)gMCvgAl(qd(gWQ=6*!KhevO|ax zj8b~Ce-sG@(@ACuyKXKiiRUT;j7~eQFVJ!`xp-n6D-(RnWH8+@jQgm6a2;%fum)o` z$$gR97M@9!@_nBqxEGCzXwp=Fq2%YM-6`@*5I9L%$9m6V{LRFJqJo&-?{7j6ps8>ohl2;1ofRiHby zCg2AA7u!6)cE+?9OJLquY-@aBp3fhetLsC;%Ccv<~0;&#pwa1si-IM?n(`d@S)>N4Vx(2s?=R0RD zhCYnzUzt0+zL1+}ARf&?`@Gt`4Iw}|tPrO210R_tzXTb@1X)j|f071DuFC%~JIm@a zNq}n?=7$-qIHA0V9&tO_KUmQ*L|6q9l>LK~mpS(sH`Sns7)BlpQ4_LS1xh2sjQ^aa zM0hMffG+74OcQQ}9L)OOx6gVP`VgiroINa8*EE5;_f8@L^4eCA0E6bQNRB=#9{EKG zZ-1fW7JTEzagwSGk>NTWAW;w(1u*eetqy194>-2R+g9cXaP6W?ze|-l!36UNa5g6m zLudmD3zLR995980X(yc;BdSFfD6g1@NRD<{)TXejB>C_9ngIf|(=wgnWBIe4%vy_k z)w2J+_;hmyzoA8Y2L45g^X65nJ2EILd@BpC0nB0>9@ z1$v^DKwnhlLmuZ+CS449o!2y%bfnFd%lGxJAn>Qq06ba z+ydVe0iFnxkNj5L_lFVfNg1bd<)sE~E$7`UUN;I$y1lH|#h6v+LVmW*`$p!rb1XMwPpywu#QqUw0n!(b8DV5Dv zmugd3COivfOxSW5``miYKSND>3>e=0``@hkXV$09SZ!@jL`H^WQ+?$)-YK@Wi% z4x6%X`!{ne_o!ChJr}oCk)MSmEX{;)@pqpo;zvbbAz_)5Ua&kE2rDHSIAKEiev22~ zBNI}lsroDXAu2Vl5XS!*MmOzbQc?@|{NbPQCAW9Z4X>qk8T|? z76k9EBEN{Zq4{D=m<*9$3MjWN1U%U^aUtx!^HI=^=rIDc#D`JD|4?1uK^6X2s`ZYj znolZK{fC#=MY5mm#e~;ykmO`iRg<8jnNW5Qk{|=$Fm}I-0RT!8^237=Mn$aRb)kan zFz_puOMSh-#VP+GEMZ{GY$_IBfQ*CG?b}r1I}p)nTOkNxC{#$bV2g6WVw9XZVl-JL zZShId?BCz^2`^gWH(^9N z(#ty#9wX91MH+mcofsyVo;v^`_W6aSA8rb(@)u2AJEFnMLkdMT4%N+{8lK8Ijl|F5-=y)eI<+g6VgpbKlI$7<}@lWFW?I{hY;zo}3y60{Iw z+OS~w&_)YPNrC`Oxsj?r0hx=d7zp9RhLND_7VHm9*cTWa;D{IuVFvxaVi=g;pyysb zc=t(bp%=oM@I1Kw^WOjiE}`q+i>^=jUWZ6cQetz(AJ<_%^Lx3)b2pd;x9S3X3uA@r&g6$gDLzmRAYl9`9mXF6r%c*o~SpnuL3@x=zKB0*jWB8bEi zFmqX$S*;>Q-#qo*<@iBUnEx<2IPqn*XZq#%&_MP$<#pK}dz_WI&rVhYGZ(h>Z`aCg z>vXg>H?_Xy;SyjB`IVid#u7?s6_KBxUKW&JD&&ViWQUJxESJw8)SQX7m01F`VD0d{ zVT-n%i>RMMBbLq7P`9X#8mzouFbN6r?!H^7But zZ}w)1_^2;-1^v8A5@!0cP1h}&lc62IGfjXl7E&M1H=y`+(9Cn_i9VE^ni7#%tbatm zAPW*EMx=uQcb90wRhsJ-wSB&7paiAzsnU0k-MN1JUvPQ+ z`+i8;u;vT)+vkg4rD{5#>ftaVxhBh9MXw@27oYw9;%#-r)2R5T zfHgr^f#d{eAzBIg=TUuvqMym4RUhvrlC7F3Wm1eA5aG{FdDmzLYv>_=fK=a%$DeEe z*T%jXDvuj}d-vu>9XpO`+J#hE!_=f!*|e8f@>9f7K}EWuVG?^J@~!}AeQM!1l-|$v zm;aObw$&>M&;pX_vTC2gF4Pn!Qy=zWY!2wguchvRQrZzn%W z=N+Bl)o7Rx_tbp8&Z5^7po=$Y#CV&{It~S71K9(Pu&qSwrzNMwUahP!c^*vugr@K*w=K|z~ptz?HZTco4zzmb0 zHLL1FdU^daSKQ=={Go^T%C8Le83J^%_WAR6HdyWyjj=Q6CfDv<-!-K_$9D^bvY3AiNa5XvW{2CwQUwm*3B z-jh~9MsU@0_gm9uE~X;>0HpQBE<*bPxkiv0`Gt5^f%w{~^oyyl@6vy)d*l!E`@kl- zeU<<%SX=9xT46tu6lVj&uh8W-xqivjU{aGfAqfg`Dknic3?GNmX(Oklh5^%yO{IrN zd^?|sLDSxd;ZLTCbC%-Z|2J)q<~GOx zrY^jHSX&XlO=kQgD(gPr>|V~B#Nr{79h7ZQ6+bjgLXWNzAKeG*L+8s7&0m%_$<4lI z@8-Q`XhQSV_hv^(Ljdyn4t3`sHF;@d_07_M7ryt`F@F`KnOf(C3 zePN%gK7fqiu2*L5r~#Zs{g9)n?gyIUCaZ}E&^k8l3oTK+1)2#rpR?!5nc0r(x<5WP zpxCYK35N6uhPp{}1RWAwN954LN_guI%=`x%nJ+;P!`g!C zf!F42T0(O?mN#U89mz>66Pdg@14nia$$>i zL@EThdeKF9=>WUZTVy(RH2lAT2VTA^OVZg=DJ!4K4`5BjLv_YTsle{!oU4i&th7%s zLJ2BJkj4+#QW_<_vEJzT^;Uad`C%67)tc5aqTi-pFKXIZL{tY*fi|TwGM@MV93taX zpigX~$t#%0f}5-yVFQJE2~Bg_nl|%K*BvlE8`FFiEa<28TmMrk=Xk0HYrv;GC9CS> zS54xh4nAvXB*nc=*9-SvzW?zbWX;^Q>b0o1?MB7AhMGqID}Q*@*Px3?g#gzqyl@^> z-U(I%rS|@uY3RQgyx%WggA8KDAJ5w=SIV8ltR1NV26b5py5}MNg6fISER-aDH!K<^ z+(mZP%dKG4-Oo$NdK~g8VZNY^7=DNnmPcQyB-T!c<%Nb%wF1tD;C1eV4B5GxG-? zm6^81!AI=?T|}w`$Yo+pXnop1cGaNY*S*d%xIXaH z-(9)2uC-oBiGJ#u0rI2glKqwjs;;>Fz$5>XImJhPtFZenJC@LxK;;}w7wE0~?^OiI zW%rH==Hprkt{%AmHJ?GofGe7<&RLJ)3*V&n{(~j{EPNKArtM)T1^6j3SV&X8Xf%wBt13;ta< zwOdfrp32JRq&)J!ePr{JS^6;p<4n50U*Y|nYh7|x?;}7j+ka3~pII!L_YXbbx=i%j z$XK)RVr$3XQ|Uq6OZE#kwqzs3p=)^|pakDH0jCxW?VcS*=2t^Tu;7*H-=YFqiti{Y zZ=GszgWr8xRDc`-a(*0f0Yr=jyKZVT7!>`3-JQPsUqb##s1*8X7rCu1|ywp>^*iozzPeRNH`lFUCkwDx8K zEMokW8vYwOAfzyCeAwO$?Lu0L! z!E>x+OoLb7{$tj*sj|M;QY_pS-1k4JnR7(56t? zcjZ5;88CU7g5)GKIF0}T!sq`f2@rsrEX~c4L~)rN*lr(Eo->Mwzr1Ge6Em}tA^+6< zUnLSeiz@a=l-ibuE-F7FlqU_qxw$p^f_w%)b&!8_?%-lm;{=AxQpMZyei7H0VFG;q z0#O0R6QR{!|4YqvR=dXL4|~4;ldKJtd_et!n-u!(uQ8ZNs%Y=mY1lgnw z4u*Kd>5^nfINqdI^$(H`GEpniNYX&i{_Nx%^z7ZLf%f?22ad|rR5T0umYMyF1Bd>Enbv9{Z3Nw{N_KGSMFc41 z$l^-$BC*0gbsZ^am;>-2%F}c6bIhXtU96!F_P&8?on%E*#pvk$F%PJ9| z{>J%13?P%^W@+SZB2c1(j^{W4qfw?!FQ?v-!J*TcXsoda9pt+d^v) zBL-AIf2D_cidGmfIg8{sd-3AB(uSQ+&=}68>OZ1V@{6I1P9r@92z(!4f=E${kioko z7iMnI%zL)n`th;50jO=p!=9~HY)vKF! z1)WS?WXF<9t8P@^8Pm!e$FslF>BJnlQK1v!h*GKx1-58NY80! zqG|47%^;{Gegx@NMFDmX0d^)=i4d*TB-E(?MCsoA8P+|U6(VtAiJ4W;U%VaN-k;Dt zvvvj9iLPO}Y2y8c#^!9cF!xRt26n7zEib-!!;VDMClUFKHBH!@Dpw0mV{xaqsE8|Q z1_$T=Da_}{!H{qQ5Y24zTTN~3d4}2*O)tFj_e}H;(ml&R zbI)c5yeU zb|F12+o}5FQQrF>p zdceO*&v;Wn=}F2>B(C^rEUJMLSv6KV7?NyKbc7oKD3{rVo58a3q<1a6XQFmPou)m} z@Aq#n&B|vxFV9HZa$#8(KmUIZY+BIa6pd*oP#u2JvMl1`LB(*QEV-sv5MXC=s!S2S zMwK{yVB5O+SzArg)3D6)*Iv4MXU)X3k!eSm5vCQCL#ER(OO z^8DRk%4s@^FMfv@5LS!$q#8OJERrICY*M!q+bl8|UjOm(Ctm0a-@>RiF8Y5Dd|%Vp z1ggHDCgHR$5TA=)Mu43yK>{+Q#@?!F_(Z9s&Hm`K+#j=7q;ZBtW2BfDOgIh@SPDO7?dVbR*(=n78T3>pz5z0B8SHGyRU>}>8`@TWI*J5|y@O)zgN)R_y0?Rnk$ zzV<~c3)ZeRZ|QZrFdfI!!#kQTaDZs0Rz_S=gCRaSs)$Z8P{P9d88MJARDFjS*UcwR zKVJDdLd;;Tv06wGMm zAKNB8BQqEeLIWSdV*lGF{_dV#N41R7p%3Abrytm}-zxJ~Lo*+zhIbGs$gff}x3lK0 z`*Nz5c1uM8t|A4fvGP7=mJ&-Iv8#$OJd8<-bQ!(LA7UEbKHz&-|F<`*!FQfLe^73d z{@*JZ<^@#2-=OR2=b4$RL53>L@smf0-LxV%KUGa}focqfh;9kC%a0rk32vtqpQo%m zDNlof{M#(yJ*YR`KIeeuOm6m@1eWT%c)Qk(8R5%3a5a)HkzTy5%(itow9WD)>qJ5cZ+O--Kesl6u^N!w^x+tI*;^LgW5g0k&Uiz+^!EXH=KN-9aDbyeHB5bqNcdcW2qfx^Bk2x2Y-&UuFI+ z;L~*6(I*?1(qtk*&JDfr>f0i_p%a;L36}TD_O2A{{S=*mj72|?e*N%iVmT3^oZN-W zX}Wn@n>Qd=AO00E$KN@l15%`WYP$Z-FBU#OYNy}ceO+Ox@wa(n$7X8zrVMMh7PEcl zeMrWhfhPQb)Oe#;)fJ*MYA;Qq3q$&SfDx4!s|-7*_C$YFIb##$ZGDg7o|c zw`JY5F~4aU4jIKIziru}*!F+dP+1?OOFYclt;ON|#6Sprl!1~^HZ2z3W7?=7AY7|PCNvag&@WUKE67hufjNYRPNT@i04 z^1B2a@^eRXlNe`}l3%52k1tDS%gzYov?i|}*(Q4YdA1aWy;=IV|iU_loSOSm%ekl<;Fa zz8ym*0o&F8zf7czkMH#R1>A#aig|Kr3gxi>=ll1>@;ZHP%zgmMehmD+HaBH15`tJ? z2x6js{~nibNScUT86a5CeC375=iDifhAcx-@J z=!-g7A0QfSU0s*PC^3msJmIB9aB)bD09_Tw_$Nh%{IrC)p_D+U2oWRl599}5XUw>3 z-R9;q>t8tM#;MQuPj$aF>pLUsSm`HJY1X$OzUC4N3ne14$oxabKd=BIA(RIbnCyoF z1X9}6^ zn?V(cPt?u{)9oSBJbs&sS$w?tEGROwU_24Og5a=dBO{dUSe?U$}v zc>eZ~0@{9m$qpJTw3vW%sFUbxs;0!aLdovFN<>9?Kc326)m&W?_0ACjWl+UYl@F4X z4?$f%3>+xa7VE(I4ZE-a)M?AXLq2b7G&t;DaHl&E8C}$%u_wN^_s-vh6ma2_ zEt?g-^`#T3ukSG`&^1(o%>kp?3L)h2ke@~9e)3E5XeUMYnZVAgQ8^t(t~~h_8sgR| zW$31*3Zr(XQCD`E&e-v*e|NzRhGsrd&Gp3v!`z7mjP|99F-*(aL#CJONhlJQrGu*i zMKje_b)sk?H>(q#i7Klc%L&h`Gv<4WZUCI35!IP@Kb=tC1RO^(iKNJsYE`@%@tS$9 zCf<7IdW8giH!*!NvZx#t1wuPtPRUXObpLzf!%S_fSgV z_^_(Dk{eI1kt51cgr|;1T{f_zuCZwv>ej^Lo1jY2naR+kK^U+Ou*5X5`W%}ACZwW} z@^j476n`lw#RDOZ`yye2yPvMA41QS{M`f~~DnC_OlH?~7Q9Q!)kGk#Z_oY~`9_h+2 z7f4n{*S~>5X@IU7{isnSl*g+IKkeIgY#=ArLrZ&>~W>9U|QjW%7pk6mj!(dt~slo<> zfyTIL#7ts;k$zan!)LoPfDmHj+#U566$W@eiA}sboOD3S4}5_nmQV`s(8sKKrm+lw3Iu@gCRnxy*xu+1fFt)zyOV#r!^&pult-v#K%~n0az2=V7)9k zQ&^eFN;uF2O-X(j;}9%O_ygTlbGABxI)`*kV5T^B&jHk=6Q$-toy?+sROliVu~^brBP!X%FA`^Y2}-KG+JObh3%!*gD&my2jL#c>c%M}L z7~z8{$ft=i1B&_aO4cVQ(TomMM45O*f^x|)*bEgT%b)<~!7D!|wJWh)YPj*OH(VoV zh5lOk(`Ze6O_VovW$Esrkc{+_H}X`8FGbShk)8syhF3zQbQJNah)5VwhVXE)d2sFl zvm2trdwyx$7*$I`sMF}Lo|QUEx~?0#Wrf@KOC*;d!KuQ8g@=&%01!}b$W(c#NWdp9 z6;bkfNTf1FAEeFIep-^s3u{UOnMbHJTlv{4Ef`-!SiLd9!?`ZbjqaRT2b$TBX+^q$ zO>!b)9aI;Xz>$+0kSNVGh_AvltMwSBLV(uHcrB!sl+$9Oo=Eo`Aavw6(IAQf2oYuU z1BvNY8`h+Uu(5cXa2s-F33G;4Ea-Znq_aAECX1`BT*6SRv+{$_M3to?9WTBUUQ~18 z>Wt?Y{!tE^wQ9BGrRgZcAc6a)exO+}|6yeQ#Rkk|@#?uW6e^FO|0nbZpzI%|9PJWY zhZ-58O`w}OQud@$n>@mF<8#DZZIqnifb#tspJ8W-u3GA@S|k^RZl4Gpspj0UNv@oG zQd}a7HI;e4FxdkU>M%`&y{er{1H-JZE171FI?X$%r?8~y4Yr39QX-+?mylWSClGJF;TVEEIBjouO$S?FC6n94O(HRPYhzvXj)COkM#Z zQ-tTMiOG2gWXLF)dfBMbloX_s3~Hzq>*-Zx zE&SlB-ww+B*MX;Ao%a!>uoi@C#cKbJi0o8IXCkz};$3}(3ir^-&8jq1X`|ZROBW@A zYbzG&3#In*+&+N7!x(i8z~?KyjD%zE5elS_ zitwCYNR_dO{KC>?oS!<)kYA>7kE|5&8W7|*+n z&Vj53QCWiOpxl(Wzu52q;lvf`DF#W9RdhOCO&}rCQGjSd)cY)SgM{GATX+MDK|^Fw zXBv`}FZwbpe7<0nV3a2U3Yn{cAtxR$V6MKyq`x8!lH>}l4fR?nr+fF8uSP-9A$ZeF z7^qi~$m&c?tFj$p7>Mc(l=+EjOD;Rg730h!Mo_Cg;r4O~cR%W9#!2v0`3gCOz~=Q>9%S&OR( z77~sH(-yqLrr$*6%cQbG8m$z+{EAt6SZ5js$Lsatwg$pt@0}FK}G_02k zHU$U`Kp5Px&mF2~7$8C5&W+Ue8}iW^(o2h*dW!UTq}vB5v?2vq3}JyHZV0J{B8nJQ z3NIoZOln6|3iSSy+#ud9B#pYF(J-jchQ+!SaO?7cz6K?Wpsy_~x*s-5t4ehsXY(=_C!M!S*a7lBVW(ewXQ`}f&C zoEmh9fG1NqO)op{f4MwSgCRlt+b<1+AQ=YUH@x!W*6$jqVX2TS(VvFSS~V{#w674E zTNfbgQp2D7#baJSXJAky1z_MHCR}Ios8Zp>p2Xx~D@Tu*z#$SNIu3w(5_QtN5R#Vz zMdc#MhHAIe5;0&dWA#L9 zkBlJP438g8;G_)SPng+N?NxKPM-6x!=_6SW-UJ8ESG?69gp-3Sob zH^^OW)LrNb47Y3%=xlSYw!-V4G4LQ#T?_23s0gd9u$CI-4gg8!XTd}yIe}mRmUq^lUx~*!spbU6*2nw@SWd?JqND&?a z1mLPn^vJ_6hr2W`yq{4?&=MJPk%V#z)xz%(W0jl6?@A>dTiY57rlBvZD) zaOSK_)acz3zc0|q#yfYyI(>twG%e^n(olB6M~%ftN)f4ViJxe|qXK0X3MPi(M~Q`1 z9dU0OrY@hSKGS+rVK}d;!((VVQF&MfWUge?4P4WT^^Nr%>-sgAG*D6(Iv@dR1;-~U zZ+sw=l&FmmRC^tY@gR^tK)Bhggk%PnoxJ;KGa0XrtV1F^qqV)>EVPrki>%R2$IBH_ zBsAwg!TJ`65J6U~03fJA``jNX&I&q9e!*xg#vi(k>{LjF00WavLzG*js$x+6ieUh; zJ5sBkaW8(gVRZrOp|5|8CA36tyaaM!iL0j8_J+pxg0bEr!cCfT#k!pC_h<1W#ZP?Z z#*DcM)&fZ>)E=KkpgPgsg_*Bj-riL05CeQUIkHo#Jcw>irpYYgGuqm6)=I-1Ps;7L^(_t2-^%YFqpRp4#|b87xVlF6L2v^w?V9vU9{8 z5zJO~fap9_;ggmFA-tb4jj7{q_LZu-E~`VjN&|EKH+1A0+KV0Q`!^NW4rprRgZkW} zR%dpY@PQIx0|8%rIbp)n89D+XaSxV6=Bst42V^D!Yk^Z>jGP)NpxZ8zNK)!MU;rF zl6>?il^t8$25h48*<{teO;%5}j-60?m^eI!xbw=e&NLc^tXdBP*0#2-8MFyoM*}5> zCaOR8_C=~Q=QoU`TwMteoFMI|7{5FZAlQ`3=L|weRlV@^Uwa`}Si7OoY%l0_PsRolwnStyeG3h0I90K$!q#_jkbyQ>FJ08lc6J!Qur(7$J;L8dO2Oa`mgHg>di)YZ{>J@4<88<@8`#=Ay< zkhQ(;DikLy`8D(-I;#;%6vAAYKy=EBl00#ukbBC~m)f>_^ zi5|hXrl%qUk)@%gwAvN8C1P;_An^8y3*JYN`Y5mpkyB&3oH2-m74VMFIC7*n6$PkP zX^B*w;xyDP;D?dnssBtLxUQAe6-v0Se`9IwfX1A`H0DqBa3eA$@ySHSt3i?We6mog zLkKFvau|s?+)-XWU6WF6ZP#(-+9sp5P-mICx|@SIzyY3VDsTaEY7iw==akuxrn028CB6X~3m+|rUH%q`0O5!;wJWJeg<5nUC^<~k zP#y;MPgUGh6;&rYVB&PNruG6fwG}iPEGeuU*iT#EzcCjmD+^b8q8fBoSty0L&uBpf zDUv9FIzOH;TRU>br|TNc^=QrjUT+C%yUoOr>zuM#x4D>aZaWl@gugmtX@{`(ZVZ4O-LI z(7&}%Tr;p=`-(xE)R%I)#w$0mx86+Zf)Sxgz%T(p@)8P9Coh*WC5V*7><_&sRlOa-&ktM>aHhO+XXa-#dPj)JT ztY~9}goII5V9a@ENiIqZc6!dCeV`XgbwfX0TQ_*+`i>Pt`@^b1{p*W${&v}MJH+^X zYi@YpC{H9s*$+S@J*!)G^@fJR(p61ndm+~d9D&*2MiwV^2qVkr%R?`ZNJ4YTlf_P% z@yU~WDRW8|I3g7IJ!SM3LhFuV_PhdAU1c}4gie{;X#pb~FiH5Zs2Cq7A>oCE*9@~^ z^H0~6n%Yan<--O*Yh!(V_zm>cAfFVk6kQLo?@S~`KMt9@hK3)mYAUSU(8$Q#EsyR7 z6`2!PQiDvPz`Ow-ZuN#rLHcR|eh z@xhd85~`0%Okl~cnyM~&coEFR+`u)hFmP?Fv3l?(t;>fDXl!k&_eR0w1#0NJBLFaA zy9$r$_^B>lcqfGA+ELVTIhng3ukFXE&(HrvD1%T%W)q>hPfjco`1vCQKM3!H@l+m2 zyFQ~|4v@;C>Kk;^>@EeE1Q_AR5{Bz+`pE)R2i-dnnn!ovZS16i)&gS{oWcGEM#N3RDv) zr^;N~1DODH3W>~Re#(-Z_dq=}|AAX91S2vcH4;`qlA3*(dI{#f!n+fE> z5Vrv3{y6eq(@|%BxTc@Ed_$97GPMS^0(0U^vj8I1U`XGfoeoHfGT1lhr7x2wXBP8m z#H&GWLTI&sRSHv$I8{uJYODZNKq>^NF>IkGwL9J9|FgbR3%wa(O0`r zSYIraYnp-I$7i3TwP^t?Ti>tn=MRS&|NLyQ)?U)<>=1S@p_iW<3&mS!=gGX(z3T%p zj+h23$Kh{(Af6W|q#RNl@Zvb-0I{Bh@?$!yECC=>O}&d)L503c*Ni=fu5G&os({q` z0Edm4_7S#>x_Z@yZ5}gn>{4n1htTV=AM^%bC;d8|AOFOJg^6=Vr8_1~3nM&3@>ZM4 zEYf_=6^z`r?|*6z?bl>1-Fk3wP5-7QbnIA*CRTUUmEK)B06$#YPeZ2VJeEY>jC42d zLtllt*Q+#5ojy75+`lCClogWb z7@a$1aS$}?+azE7Pa9j`zp3q`t%l}4s2c$9tsY>!yJizIk6E2V zDb6Y%@cYjYq%W*tpl_`lOgTt`{yBh1p3(q`tYiZ#etd+@!o6 zy+B^R&H}e6qLO0{8DYdA15Z9~s^F0ratf2bTyJoKp_G0fbFc zk-bArQ)!SyMTCh4NkD$rNfW4{2EuA;1`o9vc=ep-=Jz3G^oRl*bn>*7g^q!<3=NK_ z)7fUCNK*a+Rkx^L0A0+r=-atcG8UV@jE|Z<}XCI?YXx6dm zx})O`-b=!(FR;nSO^d%>d=>fUcG=x?@Y3MkCtRGW43bFYu+wnsF};b<-PDx31ge)c z^xAs~jN;LC8`{q94)U|mV-umb9-nWepI2~U{`D0fu6c~!rsq*D>`jfbbCaRE>yDVSL z<#b)0GUGZ4iTGDnEl68U2GH5uDk*6KRcj^n7FF7HWU@aztNEDq(2eNvwZLp--nvgu zufFesKNqm$aB4D>sX6XMji?be7ATn`!YPz!s?%2&6(>5qE|4txD$g5T0GBje+6!)i z?@|%pkLQw4`4BN;SsVoW2Awd0kzzhx$Vjme4=d{%EFY#d52nhfgg7zU^JA)r8M%7= z)wCZse*`^%%xs1*_}FV#(a+pvcc1zj290AFYL`;wq&`~Q<0yrDRYElJariTqD302X zRTy4&SCgb`{tC(uE;c} z%@tI6r?wl6!Y!q&DnUD4@I7?hbKV@f>0cL(99e=MLgsdZ8Giij%jxI(kLONq(KR-i z?$&5(Y(o=8=I?gWyIjfZtTW-`V9kOF>4~k5=~}tjD!O-dKqO)QjtT63FUBP|k8D6q zj%9ZS;`e`7 zmrZXT^;gIMGCK`r%dyj!uu|Qn)C?z6OZjgg04o0C{Nv*EAd~|G9C`46ejHE^N{9m! z!G|lDR#@Ii^Oxg<=O30k@?#VANXh5K{huP@Rn*TnZhCWbCdki1rnki3?4;}0 z(a$~0TP8e;ZFR>o(9h7)T3_thJiMDSAXGo=O3lh>RTbvfU8*iVJ%v87`oA;~20F@p zZM-^j z#DR#xnrcCH8`8)pBKxHX=6xL{HnY1%b}K=z*r;Ih=2`1Ee{aYg2I7$>;8d#CHDUP%DVE%D2mh*NZ`X)m@rf=UfC(}}B^G6UcWL_vjBI%Ou9 zhEHljlaZ#(@J&oEi!f!Tn-KMMsKRwB59=94c$Bot5uX_BqAZf1g=Pbtzs6nTgVj2LI?^NUEZS`sPydH_THA(vbO}diT7#P1;x32Zsd1J@6 zLx$1oz6xhy=$Pq$dT;KS*ZRSrxnw3yp>{KpD!p^lW`tG_-H!5ZSlp;?Gy$;?cSz{o zd6M(}x`I4VeCBX z&GPKB+s^r$-dLJIck?tl-#l>w7;+pJhe6d5uI#$1>g+T+uj=ghm4z4ct~8E7JQ%Vh z4w#@yH0jabtFYR(Mn8KL> zQwFXG?NrylA~AC7te+k659mec-J6vXhMzWd`LO@}^-3(UgQ%hY3hh0^Aoec|or%*G zlype1udO@!`>K<-)raTyK=F99L#ny(JGPg4F9;hlGo?{9R_4&Hq2`pGko=w0Mzq1P%v9xT6zEXhTG z!F>MY<=d~>k8a8&ay=wAA|?nRhr#NtpjxVmmd? zU6?m$yV+rU1CP1pDhruFE%h(D?v+iTM)6uC(I@r|vdGO9ss+oW<`qt4@?rOfs}C_e z{);Z+S`Fc;Tbh5i0(vR>1Od9BffB1r?HTKD`MfF3baT$4`?edJiY1Y5OHK0X<-=6F zks7Lo-#Nk({gU=8s$4r~Hv4{^Fx?RXQ(1T_v-!&*M~(>nkB#$vgDw&Bgy*_4e?Y}G zi-CCrB@&pEkIF0tNVNSuA4fcQr|J0AVy3(yY81!ubr%uI8i-ti8r(qb_JKLgqt-w# zN1q}<9-EJu*0O5ul^K8XT`99IdQ8{9}9Cu}exEPRxEXYvoa zEAn?tQ*rR3?BTl!Yyu#DPgvYH&?mg08sy91rQ|T0WBod66nr8?w_nkZ9Z-#)8gz0- zuI~~e)F6PTAghf~Vw1w~zcQFTR%dNe@CY5>H0!6m&(sY=pCv#GL&i>DLO(YwyK~Z0 z8nENYTsn!)hm}3!?s_+)Qo`vKs*cM$D!lCpzRl>$E018%F&ja+U;ID^@1>kR!$24$ z0f8F98({ISlQ&_RR89tx+LVHn)vRxjM@^u1vWl*oE<&XIiqUQ|_UoK!-udRRVSnt& zb-QVxPZOYv;V0kn=JJ^nu4E1MFPmVV#X#GgT7@`&5P|DQ;v6Mlwcpg#oKUZZs`BG! zM%5)uryLu>U(&`TMdz@Hd+wzN0KsW5swp#a7(WGc!ilK@sHV(>?(E_cD+5K}pr{7J zh>&%bo+?0u!czn;PiuKwGtFCzjg9kX9D3-d&4f2lO6dbqAz$-pGK~+Cr)RY-nQHp7HTA_6r@@=AWSbcjl zQP=OFk=-SbF^pPyYs8L@Lu@bij$9Hf-|vr*qFf;JvwHGPSSY*5l{2 z4*TG5H*30f0G(bzo#_Ad%rEQD|XPb&%v(;SBoO&$)BgSBXk8} zSJU$_*VMFq{`HT4Tz>mcezF8Ignje*+-VO#yyIrM+&!jg-VRkjDhkj8BUH}wsd-w1C3by;wVISjP#y%STvc^N ziFH*4M(3ZbT+FLmUn|*Wp|6Y-qr$ExM8%XDXRZnh!~{-gmgQM+0=1{wTm|Rk<0QzB z6nkd2!YmflAq3T+lf74_v_6X&b_=Ag&4pl^*W->m{%%eRUtjAg#w}RTudY-&15NW} zD(4rd;+8-akX|34-5@rjH_92B&PFf4>&)9tvu@7tQ>MNL8G*CD*pku5ESq)4EugVW zh`0}guzD%C=IR?NGD%coI!49m3}IC>|8RE}G`k%2B@hM#SAF=d5^1@;evBh6v`Nc1 zp%ui6DD=UhoR5>9YZe1Uj1)W9;Sry!@|Z}1Zr>mPN@SV_B$^Y?toHvZ_4D2G@69%A z$>IRVl$MsEt-5}cUMQSF<^2*=8R@J9k+=3n7)*EktejT5efgb}4uT9~_=H4aO1kmrYhbtz`KNaX`x7 z`J?(S|GAMF=f^xZ$vt5H2F+qQtmuwjpI!M%(Ji=7T4DJJW%Ql=>v!1?KroBlV(|6k z*9}Czkh%n+{R(ZOgYLy0CaJ31nw#&>BKeJb_~9?LGd7h7`WlP;RF7jiM5BZ0yaiLWZ#Eq+36vpZo_mO}V9^-pJFldJHv{O}zlTJgE{& z)a-I05};yL711iXL)Df2gn-fM_&7S#lJIj2-F%pn4|qz_83u7P6_gymiUbscB%&Gwab0nhA>R)wS3Bgihf5`P>s`%1 zc?B|td_J#zGGfH`XwTgpO_h^uH~3B>9RlQAF5jB`!{fkUd#<>1@)LANZd>^D(zl!E z&rf+Cd~$4i*0hy0T6{sS*zW<8nU~N*upd|-Y2p<^6_IQrGz)QuSa;tqNj_2T63Jn* zw36iQE`bxxUooD#ZxDc=K5bj6@@_I=L>N9%T9`89nYDh2|4+6ozhHL^Pdp#R63)~qo$k?QR$&<%SPq^|%`>1SQo=jrcE zy7`ChbHLWKR_;IUj-lh{WM*lNHCjwRFVQIW&-$(Je}pxOnl5Fpv_9NbO;zXn^{}c_ zx`#!Q`traf3STz)eQM5b(OfCf3CB;FQKturDKk!70QHm^=9kYdDwEPfj|81d;fOa{ z4SHq6uvbLa;N<)!mEk@p7VeyL%rTjp&zE1gFt_}(&qmR+HIYvDM8s6;LWOh)(AnNx zvSB=+=&%C?xysP`{b=c&NjI-7mYyA9&)LfaoNc%6eQ(<2CpOVaCs1o%1=U3Pqez_{ zMP(6wN!`OqEPs%zOZj?URQs|C$rA{pm8rT)RINvB&Vi?@0JxD@U-`-Aub}8$dSbx!v!O@WVtT#_YYRbi z(%}@Qs&A0FZJY&{-br;J>@edw2GwA-AMmxB_UekwhWObEK~u80$D%$?@Z8P^ry2Y-C%U!{4FNk`VM3S&a|1TZ}A-@!0IV0 z3>+j$tE)uEAU+Q%2HGAp-@cGTn1;`jCw6yd$89NqD^K|M~vZl54=yKfjrop)FA~E^-f7BR;n#itVb=pJA zXPr3;^ZWMcHOs-NCJ;K+M4o2iuP{)ruyCiD1k+Nl&Tti4bl!^m6)Qaa>x<93eBVt! zus7Aj1b;P%u%ZK{DJ$T_LkMn^>Za|un_?K?;sWmuAeKeQ2NY!l#nc=Ckm}DavVG4y zKj`~7t)*ojQ`hIBrp=(!5$NpB#8q#%BVA(Y%oX`hjz!Mjq`#I=Hv7t=Wi!4y9R}7v zH~jdi8=x=20OcO5mG;%et1TAd9u-H-ztT8id8@*^D<|ZE4p%`jCy;B3dRnd=Pd#OZ z*M;Szkgr2&q}a>H*L(hI4q2Iks4uy=s*f@;ZX160+P!$-Z^PdwL8H5;vid#ft#guz zcnp*`Aqj6tyia#jNw>`d4EkZ>cr+}&57ow3VMF0JOK(5@mMxdP`B!^6TknT;5llf8 z7&vfFLy4|3vsvv|x#`;3`~&W;0*f+Z5x9Nxf@CJvU&KI1tXYiQv3kl3aBhOD*S{yv zIrPf{%zp&RMCp>I(HX^%O;`gQJMFT|R-om^BO1q36>MXk~(?#}1W-~WKg3E+{1-zLy=^UX{QrU9ZE%D8Z`D@Fi9Tu8HGbYY1))k*{=Ir%aU`WgF4pkTBSFLF-iSkCD zU=Spg=BcWn0<-^D@8=g#bizPKrD{+;@ZlXfWdy}Eny3lcuKC;-K*U#PZaVz`m}yQy zFpr>i-9L)Y_{$bWAQOIqp{s|U?*mLod|r#PU!eV|g7-tv_sVtXPc5H5Y3gQw`uHW5 zq17abQPN3=n}RBmQJG2FIWyK(gq4M_Ebk~kXGp;79}`x6IQO0Jd*kgOVZyW99~V09 zMVdg((V*w9iVIR-p6lk8z;)v%RRdo>=V~~@<2PF9?KrLFv7Jj$8mF11an|$cc?4Ka z4O9gY>V_#ocOBi|2N>%v+6Sl#<2QV3PTpZAgT0sSIegA1yN`chi?e5Ud6UHMhH8TX z(O-7yc~w_gocR2`(N%wRz)?rR0SKi6b5#{LWdf6WF94HFgLjoUeL6w`X_hhq?;^o5hy=XZX{5IlPJSW!uhC$5RB&7* z>8T==+tW_e{BG_Cr3*iqe)_qr&U|e13@xiup-tcLVtt|C<(kG$rqgZHHeJ1aZm?I>-F_UJMWsI*c1PWyVv3&gQ8AJZbsl=)3#% z>3tIfBBsnBtf5Dy1yEZA8OOdvd^>#d=|LYZUpWPIwqMy1DLK=k8+=q^rR z=F$T$J(JsWkSlL+1lh?4_%dRkj8=N&wuBDOrEZ)H=Z($Q7W6W#%}GE1@yfGw&~Bsh z@5lSekFDUS^o$7-6297~rkeEd$&5+!s9~JoIiUL{^-h8J6OL83uc|Vncv!}nyr-lpneO=s?S;U?Qdt7d>*VH@ zkYSvB@2|Hpb^IY&DHqa(?GOkM!XlC662m+!-ebv}Q9s)Ox`=cXV0i)?_x5+4!FgC@ z$`_8E6Yj0*r|bW5FIp#xaN-4`e}kySU2GIfzdm)76{j!1e!_6bFurm1)eq^0c??7I zY&w0LF2I!4m8`1Ne-Qa+p)2u|ElY#apk<7cqH_2EuG(CGV`cy-~ap6ER)}fk3BZvqz8U|2O8uRW1zfMP_(Lx@~f7ri;7eB^ZtwQ zSA_Zf080VpxN!ce36~nZXmM&#a_8N6^@g%46XH4fhN(eCdZIhy%4+?v5)Bh90K>R> z_Nhm{02#;04=&ig`T1wW%x?#qtOonXRG5UwQ`!7wbbqtbiHoaU}8z*GqEV8}c7?`_!yAvapn;8ePv{&eNuTPd9E{2LuhC@hgv5@uR*M->P# z{aseNi})&tOLaShZrbsh3HvoP^`HIG)N!-7K4(rQzkI(#K5vop^9v{BU+K3=$7ojG zHJ5$a^7F4zY%N()bxOihhO-@+Qx1RniWAr!k(IW(x5G-)UYrEHQC_$37GI%Hg#O4f zS5zkr*UDgAQ3J=SU8F(W41utM4(33sdE4!0HGc#d#<%UD zwFUnA1)vxvlDiZEFf2_7%dmP#PXU6f0Fx75*(r+jV$ukWt5ArXk}#>&|DD?N&#|NN z4_oJN%p?)Ic>VPAw(4l8KSx76jJl+DRE6nrRi_LWoyQ*sZVT-+2;$!tNy$lWt~&IR z;gq9N4Mr$BwOPz0GZ(_mVo7z{46Gd$21(<2!G(a%i|aRi6T4~4*-OYbYg1d=)nBSv`r?h?Adg^VHk9i}@#RRLO%SsFo{Lg9r$k^B_#gtrc#h6%w$QOZwF!*u=7 z{&NyV|BY^aruXnVdMln%w>ZHeGdc>zZay2=Z9?FpTmGNW=cAuweodTLCW z^sLP{J|M3vOcRd0^{gZAfegc1w|n9}kNynn;9061YffK(@17wFnEy&Vz)8`1F0??dB2djC^=y;jOv3;=zqw8PsdBiddO+~dC=Bn1?U^L;Hk90 z?XAK{vFqo#D@Tu=0|tT7UW&hl{=bh-XWxA8F`4>+my9uU=Qf(!fW0(LKZlz1{#1ND zG%%}%+EX4%z=YvK)2)gEOpO2;aMNJqrzwoW<%cLhiXl%ADhN-JuJTKDyc1*UJdv#+ zVYSdO^qX?)>)+UR+O#&vD4smyjE2E%;5SRi&Zm3u0|e15c7ZVtaU>`D2T3mM7Kep- z)g?g2k(wKniRVsqi3lYEtCR>O6FAf?W~@YV@eM=QuQk_cPtD3VXLhYQb>C?3?6}M4 zG^U?OBjCrA({{kU=Usje1&bfRh$WCtkf9qEBjS_^@Tja$gHg!{j0@*DVTgZc$j>%c zAQpjq+{AG+B9rEvZjLMsZa<$K=0Zks@U6FY(9er4qw=G++{!$ROuO?)!R|^8MpNC6 zkkgnj$y8k>VO;YSoo7Lq^5Wb-#`V>@2mFpN&P5O3j`p?zx6H{On)yw5-`!!v*EG~y=$bwcz;%+wsXP~GzX(`}AFybW;={Rz zpbXFa8xLaGw2|U&FcD8!9O0=PrTDR==Nu@B6ct(6PfsupG0tW=hC4woK=b^(waR7w za}%$Az8=~pqJ}@C$Nfum9pZP5D3{QZ$d3#R_{{%TC=WXuCZ8ydIH0&Sd z#rO7S@#eKLj*wlw$)u9_WuZ>h_n8Kd8hY{8zqc;=U)DY_9tO>1ThR4?!E^Ad%|GW} zOiaaO=qqTZ@biA66d`}VSr`$rpkQKws8vVzDM0x_!?-x8Od}cbfp6|A((ryHLJXR} zinvLh@C;%9nHPOVMgGMLr(bdpn(R!*%9~USw)`-vNhzwoGhxE!B+ALSgAD!_Rh;?@ zOn{a*CiRKX<2^y5Ab=vio4zeTd?Iw!BDt1K29N2W-TeMv9(`$kFWhn5sZMTEI4FtG z3kMNI7^NI5CBsWnZ(=#7*{Ti$UH|ezHdT< z_(eJH;d1v4bcvACESU(;k@L;dEC~3aLTk4f8Sbq>2%Q=sPHV9V#2-np|NLn+!FuPLhwJY)es9VP_|z#( zX8~@y3;1rp#RqB141hm9#tWm0U(N$plG{uZOQ%h{bad|~KNnp6GpSt%o|UlY4}$Ko zBoy*kE5m`3Hl%P2xMe_9LF#LPm1d>PjFNwVlmhX^43yzfon2@i@(mS==)NlZ21eeP zx0d_ev2b#JzF9QJ&_gkaNPl~-bFGXhRTp`WWUnM)K(x%tThRlP2082#cb8>vTYCRL z@b8pk7W4gu;I9$((sQCxAKxb?u!l9sO}#FE^b+V3Ad4OKfK4l?!SaFY!JTue%g8m;9V4gbSAVu#p9NaoPiWM07G2*;<%DI`UVrkf#NZz&Znr92`2lk$AOngz5>eKb zHVLAn2Hi9OIW-B&3DnZ$=~nuA7R-yuH$-Ed7>?&0G8_(|bqp!$!=ekw>= zgoS~)Fj83QuPKdWhrrTAIQc+&F@RSy%2 zX@x#i7?BPJgL`fv#D`(z=$vD3?*t6NNPB9>^9#r1Uo7R=fg~T!r|aF7np=Y^d_2kV zU;#%tiod+g8HII2FwfPAB=*$HBgKARetb7af65HLMN0N&EN*zPv2ppjd@q^S(pmUh zg9U4yKMV|%@Ie&k<@*vrgu?Ao_|~^AvqBi)tb@0*oA7Krvw8 zL8y}Aiz45oZz%Fah;Rk;|^YqyrZG}g^IeT^+W7*T1V{IaQ@aYq- z_&e5_qo_{CQ7N~KCpi{Ngx)k5iO53DTG=diZji~?3d-$|nr>eH;V1C#IdjHmc1PxM z`33zN2CV%m>o6~-7wZpngz->iFy}?jHRTwUhiWy5+@UI+FkwhH=oZ zF8jx;+rSk@$vA)r>o%&Tz?M+Lyg@}8V4mA?7#MAdIWz<&%=-CI_gtfXN2ghvJeP_g3)1Egdhn$k9&sP zwgBE&0XF&ebRRu4DF5w zwivu5i`()$W%|dHW3Rg0WW^V#Ue2e|e+jw$2bK4cgX|@co*)bCkp7xoQ4Jz9KSI>* zpss{D`Rm4i3>k&BKVNIpwwrWdT{D$?GL?T9u(}Z}lRoJXZ6zq#g4!MM;78Lz9^8W)e3Eui+~bH@z$S4k;d+~}N{WAX`gSsD3AJ)ZG_sfKp zAQD_>ex-=(z^~D@f8}$KmCPDyz_)9t?|bPrCtq>N)tM&0-1^2H4=F*zqZ-rhq?BG(>gYEwESh_l;*|b#tnmv z!Xm=gwuk9P3BPBRnachlA|g+C?g^qugtoGC20~C;&W5UQf#7-#@m>a{?`x)h-bL4* z{B{=mOf8Jb&uu*W+If4gYuNFAy3SvLiQl)}ec}_3s|v$;iMaJA=cjt!oMR>l7~uhv zo;4N-ACb1~A9dYaTS*Hkjso*+BzsDS81%D#guc~~FoEA8MSzCM1+4ZF^swiq%9$1JvXm^th5lk$(TBD;Vt;fG#;5Hrud zV+i74q<tN@hsg0s?Z&SV^#~igkpzciD zVKynHVFkN&iB9IsB^2h5o(qo*cO0BI=q3md7$gA*Zn7YyCx`cfU=_^bP9nWgV1d0j zcm5E=qnCd};-kvVb7bnc0FixtQE!WXR(AN}Q_sAWMmuMH z`?l%tLPl}eUHKPUMveMYL&J!JObss4fbEL>`eH>r3VXSrb8a(+)tmJWoz86AWZ4}= zw3%MFdv<>IuzFTE0o&P0M0DGs#~I=dG&YCW{eRYN){W}!w`x7y?kBp1ZaM}&>7hT@ zQbmF;0`mcZV=V;{Vho`P;T3LS@w}Hvm5_=Fj2>ls4x)Ni5sBlbRD9t3p(@Q7Qd0Nl zB{Po&@`JR->B33d_V9l#5~0v%>L%X%>iEe=w2aEvLq=guq(1E4%YRc>!edRq>!|Q+ z18u?ib4@aNzdx#!A~n)qfzHMbTElM7I{96A>94-q1ohLX^cRBl5h8RyvuWQv-=s(B zvzw3#_;iI&g$jNVCNYX>1x(|Bs^P+dl$MMTw?xk~R0rL*78n5{D?v$o7<7^y;!NJq zzP=ED--CrK(G-9RGWSe#_uO~4?%Q|CVg3$7RxkeZDQ8~tS);kg`5;o}@T2?lmQua! z;j#I7T9KVc{dGrD*`00qUHDTq?6*9&lgl%R`qgJ&Kkk*R_VKy6^ny9x!g~EQWX4#h z>jFHL#5GY)cnM}Gq-FwhqrYB}(0j3a%8y}>7n^8T|&D*2;!Q+*hUY{JERyVvQqol zbEl5~b5_aEs_Vy0hn&;=ONz+e0cH(t^z_yN` zkZF55UD&srsUROy1y47DJ#fxVr)RSKE-t_P-hr&6Z4~6#=^EhI-Bl^}H$_}sWuNmh z$lKh@kx`86oJ&Ihy6Jl5hyp@og^2H{ccxAnYfBe(fDPvz4H+f6QC=UPS z`Rm@;*}T{2&<;WC+ra{n5h@pf|Ih6-@ySu?j~p#2C9?JP2PKSwIN&VJzS2_!P@q4z)I$jvd0y*4dw z^It~QUr{BnK8nP+xqkk(VnGtL+n(6Y-8qWhd_lpJJ4eUay&mKOM483t=c5dxh@&{| zG*Vv*C#Y8b1cQVVMSdzXG&S-Anfw%vRfJFu!OgcQ0Cb3`^BcDddrV7$?9Na8HdU!FIMxqTC6!E%>)Ce$?_?+`F zKVHS~Zh`a_#3uLQsnro5Ki=#WmZw3w^8mwuA-_q(Q~DY`o?l?hoT-_)SAReH?4K^A zzAUIA6xW|I^9P%(-t6HV;G=YRzDEy#Jx_Y&U-TO?GG94)bN#$NK=g>gTjob@noEX| z9)!7myt`8dH;gc%3vz!T7cmJ5f})?#%P*V=6ZH*7xpxBHycA>3iAbeSnmL{?GMk4K6l#c_9ZVh&!1m2 ziwUDfjna4De4o#=9F8S3cbsXmA(lkoM^WAV^}sPBt;%(0+POY9;=gWU{c4;MUG-@& zCE)u0z#%Wcjo8Ka&U_QrX;}6MwYyZ$xhgLmJFxKh@z03krr5?2fVY=jH_0px^bJbs zRtqVu1cBH$M5ofl^vEv|E+kDzc_<-3U?`O#wA_LByAxD&cL;GP{dX9>{hrvge#hAh zk3RcLDNV!eHMr{J>05kv^Y5KcePO?+QRxfFX{bgc7v89?^8%3Mx#B35Aad%@YiN>L%#~S8heHy#3eQ99q{?-b-bxVet-#g20Q8u$GIQ5< zW07HGwHf;1BUF)HxI#>WC1i3#Y03)->M*GOKn|vI1o6?diIDZDSK!g6miyXs$6R>( z(@j$zKIpD#D`6voHLYbxzaihHdOe%!WPkc=koUTiM{ONva7Q}PJ#+UEna7S4I zd_N}xZ-BL|B&+{+b-$wLDnW2mpZh^6z8qyW>nO9p011GQj^pCggJOWhNtbsE4tThg z$s)rGarkgmKq>^NY34ID`g8~tbXYj~xx`m}@(YBIpsirk9uh+CipxsHY-pE>e^>sFhMi~9O#v9*e0@F#;uqjFEPyH?6%+U_*y=%KIMTEZ0X_v&q^LO4)jbcou|xwM z!9k2*cvZM06QNVFfK}ud_cVBMyi>3ruwWYYL+Gp8U|!|poQbd>YV6U$^&R&-b@YYb z&GJSIUBS&`ZvNu1r30twCN3ljvc7w44+uFGDwwqBt2@zDlm!44@9s?xy?%!J|2car3o-o7W#N{EAUAP~Es_w&JLiT@?YU!{2~pLdb`ASRDUQsCZx=}uO#5F~4n^u*W{sK0_)>vqxnhT8|=ntE={@*}k1xdG?q#B&-- zVD22sanL^p=N!c}8TTeCb6^_%D;WG`!VQMd5n|sD#c&9~?y{wP0gVzGmL8<}Q_<0wM&-4^dEToM_?pHRMQ-k1J=- zSAZ~e$Ue5dPjY-t%YEbVBQJaSk%p^h{`BsPK7$P5S7h#XFnv!0v^)dz%V=%G?~o42 z=4*feoTt=PG#o)9r*eSn_!9fgd@@B0o`Y-(12_K5SSoe~|6z1~-LikqJod9W5*-p` z(In_qh7;FeJ=fh2v}wnZ|Te+vMSSCmym4x&b{xfEKpS&#^kzpImX> ziGNtXs^M7B*krm_JM&@URGjaYOwHK@5)!s2$qxkn3vrOj=l%+13!6$2ATlA1N?|hi z3iX|QnHAcbA8WpJ#;Sh$ys`6ocB}gQzWLmCJ2dQFGWGLy2K&;(S}ziw1n0p95cteF z7wN(e>z@0><|gL#c}c3$_C}6S91>BfqAJ7gXt#-raVt8+UycL;f~!U(g@)XV#C?bO z5bKNMN6$~LYbV5~h}vvm9kcH``RH!l3a!U?58mwjU#|OA;}&xYCLT=naxD?hhXC@# z88sP3eaBahWAF0Jr1;#i=K&(=V0am-1@&MMuk!e^@-0U;efeXiBuwvE3d^U7fwJ(w zUb!^-@5}UH-#VlXo_x4DzyFgzynG<^0Dg7+)Ng!l`=(#fAlrO8wYpX6T}5L*$ToO` z-EKMl4$ZEA7$5m9%>e@NpX?Oexv-3DWQ_MiH-CRRO&U8w+hy>tm3d|ISD?uI{t118 zt~=+)Z~EX(sX^|VJX6JS^TMEiKkVr1==?5V+Wzl-_(p#2iAQ()K9D`80C_mmW~}c< zT=>p~6aRoFoJ6(sQ`bMLZ!F9oLm%*HA`4qF;+sI2+LREvpD*AZh`|4-)gMppvRaHR z3-G3!Dy&C@Inod#b%wjN4q*4RjLP5GJU`zp<_qQ3f5Rq?N1LW`7QHfe_Uy}$(qfWC zd3E9lIbo_wz?2rlf@@ZyFM}ADEN=>@tpKf2WlKr;-}!K5Ur-5pDi-|9r>i^q*yG-ycuqf9d= zP-T4!xN=rLIFc;9{Gf*^Kf{Dn`n*)-2$VJCSBPK!k0(R5V&v1{2{Mi(Fc85x}o>c>%d9u?DOTvE0DDqV?3_9`sd*!5DHL7eC3{JQQu z5%S>x<46$6yv2t!hTkLNoAArij(QU^giI5li*2Xf{!w9*6&ItX9fKx5LQZY2Ux3UI zAauPjMyo{R*e{AO(}1ds!oUZH5wjN!!oFpU7($R?WdVK@1wSrN6@sbG`=z9klYmLT z^1~_Af*`HIcjF#@rcihy8TbSz6RWFyn4t3fGWcYPAtYNJh@>Z$#~Xz4++}r&!p&vg zu^-R594`&;6^qbD@n5CGl#xiXU`fir{>?83eDx zdVHh!-BniTt-W>m!Z`sh0XH$1ZMnX(s>8|OD?it7CyvlSpklmwaNLA?;ja<=%K{DG zr;Mi77vaHMCpE8t45L>lKpxaTSp2Zx<_{H68*c(!NjLKYt0y*6`GHCig{dW(D8)3> zn5m##$Lk3crJ)v3d~wRlZNwP;OH%v z54$bvyi``Rbq5DERYR`9E0rVr4>{5u7aKtrh&Mp zpR44Y`tVgDa68>_dmuXH6efBDm!6|uDVt{uV6*0&-dvS^`nn6fP65i;@#fp!_{^+7 z%>;Hd-G}GMsSv8@B2;2fG1~7<*Dr0T$X2!FO*jYs+<9R;2fSjGG)qwZVaOapWg05} zOI`CtBed{}k}4D-A19#B_`r-mMG*SFTy@8p6^y$Xe7~R<4&8n@NU4z-LYeq}KKI=I zb<62DFk!MZuLMQ)O&PGim|&h*EW$B!P9OFEpqHUnDnJ=~Oq*s6iahq0$zv8Zz$V8s zO`AY>YM0#?kqyk+$l{EbZm)n4K8nbM_a$*o#&7)VldLe~M$5CHB1kl^*Zr0ANIP9&TB(A)dZ zZ&O|be*!Y&j;joh#JrNp#OzPV_O6>VdF4eUxl_Z2UOPm>Het4aI?^*MyB2M&^B*uaI_{0-wvAw30= zqVhPI+U^cSmBii*AV_Rsg9WlVs4}C4TIS4S-V|01h@=7p&&2l3Zo%|*{SPr>Y_x1gldwq%l6ge!f zCIzkMJ4@j~EDsk!PoXYFQv900E?3V4MQ*6Qco(bUa@JcFWD@9Q|kL!`LVkAP-W5@2}0}tO1fk z=)ONdO+z_ZQ=Sr&)z0M@V@rRL7)s?qVG_1et^yrD!%+K)uGgJB{hXs-fj*9n zLIKKfrp>(g=7b4v7%cZQrolPXH~3{p%6h${T!$D!f7p)Vxv=lJVwl#wf<`}Z~0XT%>$_^+&~TTZOdKk1C-3;RKAQ3-V^4l zIR0E(0m3OfnG8dBh6%|}9X8q1hzb=d`lkpfaj##C_l&B95I<$#9M?bQMv_${6Z$87 zeeEeiuWyZ0iKr@2HBplK_{0ql?EK9&RNlLE&HTZKtqs3$$!}x9MooY&cAYU}>DPu0 zy-)`{ntFc8EG{ol^P4Y1y3=4PFdgORHu6(CC=wI`^GQ=>{vsdN4-*ttA2l$K{jmL=2~*EK{>}OM zbicrsMQoHNunH`nx3t}2`a9h25<$aP^S&6$si^aShIGeLvf)7vX6?0l*{#XtwCt@!2o z1DH7L#*2@C5H@nu6rcjT-g@glnNfeT$;=a|ZN35N8NMD+acn=RK)Oty5lN>@#+pm>FiF4QN`u=(F@t%yZW%p zU{c=i(9fk<$o=$&i$*^LHPjSf7`}GZQv4^GzwzANbkQ> ziiUZ?^$z*f;G?Dh6X0w2Otm(8e0kxRF@N1`L%*ulSsm&FZGooP>rXhZMExZl#dUsB zJns~;AO(3i3d`?{>+EzGPNI2JNqjezdgCWX%lQS=qU2UhXzSq5P5s&q%;zWe*k>oR zjv4`0fRXd&RedRt_0G3scyI-Zdd;tWD5^aOA!?VU;3-Pql3KL$L3U2jjv@x*OzEJ{`Z0k2`n6xWuYjB3DDVqDFuj zf~Tx7%rD&BRGY`a(O;0lrHk%Xfbvx(BNaE4IJG5W5JW+uiTO(rE+aa5qeP7WGYD~% zkp=qj1aF7{1_e(@cOk?i6IDW~j64BnL)8c)uAoq57z}G8Sb-{SENqaV8sX*QyXgj0 zU`+t_2x8KpD;R&%mHH^A}$z{b*iE~D8f}_jmvr!Y6O@C1is8B zsyz_=095k^JOA886I)pNvNG)};0H78U&X*kL|pHK=`n*Ls_%2u(EX?pU=|?@k&uyJ z)nJHZU3Knz!U_C)u47*`VUr>>yh;Y6e0_>MB?1%k!bD{VnCeFAn-0|=p+F_nQw%v;ToMmuTNbuoKFnAJ6jLG^5v4?EFYUCO<9i|!xQ-R{t7o_(Wdynq> zMMbml7}U_MsI3L=VT@dqFVWBZ-<@#o>ve$5CWCXB2?ObgvG0vcQ~|*fTr(`9f>k97 zaHPoE*|ZC8I`wZ*L${-* z05gK`|LTT!_Wsq>YtYcYV=}yvoLZ9;7mrFte_32onMKeXw>|vqsPmuAH5jKL(fn(GN9X zSI}eit~F2+uKGAq3mN37CW02BIA)qTZgdAB6mJR^2;-hdS7bb=BK7l`cbcWr4>l~_ z{QMgEWeYV0m~k}EpKtA%`c})RQCDo*w8L-EV5c*NqXPjW*oHSxQoSZ9bo``ewQ{bR9JU>?LrB z@D=(y{<-5WxSyV|v*;lkX^j@E6&DkZP&$#r2I6{=m@>^WBB$*1jvem!5n4nQSF}u=@VbPqU%yrTfK#;I^e(O>u+}t&U`=kB{SIENw-aU8EVKpY6RFzalrl8 zzDqxsJ%02>Gn<%s361z3Ll5UrK1?_fCg`~eb>-qF8!}A+DUU=m??2ulDtsGN#BZrf z{kk)2#Mi4(8wBa)IP8I|KdGy4JQsEISR%lu=|SvJO@=N**`FUZH!wI-ESz)sWMxfo zSEg(S=KXo@+|?r&jzI^hz`wH+J5gtKqid?K_o1c$`v6AHD|fIzz4)8se)s8@hKvGJ z8&41C-q2aZ4yahj2H|xUu4T)0>VfJb=H7?gxS26dw0F_O+YM8@d-9!UegZZ0O4Jl! zAHr_0%_$yq-*xw!dfkudF+HCi)Hg|)#jdc&ME=ohgXQxcv5a}3yvA3lVI?<^+)zvq z%ar*k{dX1Wc;Kg7t-W#bos(k+7-&!DCN`#27~XX*y}X=xdif38U@9zz0W z5}kih9hxcT2y%WQuH8?N3VFsksmdg{Ibq8ao4F-#ig0Tw#4M&8cb+=uyz&YTGI^nf zzJnS8ZX{@)pI=EoGZv1@&s(1>T}J(4)@qXBm85|Q-7;jndKg}uDCZtUaJyx2ibfh7#%w@YwmmGrhbf&6rs@=y6%aRnXCGE8mk zM?19MTO+@X3pE9}kt3haTk`}zq`#?;9(l>5z_c@o6pkXg*eoutKVZ-^Q)Id_07G#* zi1dF$BslBjU!C_ms9~c-O##;6;U^DW`OaVePn*n2`u=qK2+_oJTLi93!br#AtlZ3M&C8mo|{ zUGNY;Ao9CZ)7p+W>F#r%8$T!CN_~I5bDCofRYA=Ju0e@IpUAh;&l3yA<)1IE!*O7+ zF~oCU21T36I)l(#{yzq=1?`4;^@RH`Tm?1M;Gm`eYly_5q>_ey%w}jg7=tD}3YpP# ziD=g(>H4P<=#%@m4V{LyzIas2B~uN?_9gK(m&Q{+R diff --git a/packages/grid/frontend/static/assets/small-logo.png b/packages/grid/frontend/static/assets/small-logo.png index 6732c49351eff345865006cee5a9bba48857c4ce..c0bb753561d038bf271fb01ac0b4c3642ef0d6a3 100644 GIT binary patch literal 24772 zcmZ^J1AHdWwqR`A&cwFuOl;e>Cbl`TZQIFYV%xUuWRw5BZ{OXwyZ!yX?&_}NI_K2s z>I##S5rc)of&u^lfRzvzRsaA1jQwioL4bXoZ9URAzAk`{3Sxo)RTDVJUpGa@Y7!UuHQ|9@6&%><;>lTt*rH(Y#j*X9Bc`gXjy34zWRZ40RNk34$yzm0F2E6{;xJb z-WMEzXy&Wz*9Fo}T-^}>fLiMN4_L_ayY!2Oow<^lliE*dPD5L3T74s117lh@YrAhO z0B$$Vuco!JlRkl)wUvz{ryCE^KM?eE8QL@z-OT@+la1rQ z)%sG9?z@MMftH@`|AqFY?EjYU|G;w7xBLGhIhmXMe|UZO{0r?LWBf}-?r#Y={~1tq zVRLI^8^FNIy^FMn21M^EUP9X>5ZwFGcwYB2? zfB6$P-T#F89|V4W4Y-lMlfJONlQAzNJtH#>JsS-JqY?uvClfm-Jqr~BJ?FPD-(>y| z*#DsOZ4yp31!G5BE9dWltJsD<&ghK%kXb@|M~3S@Z5CYKKUO$`mX@^=jm4j@IrkV=D(te z7wQ))sx$xqKY)a=fRY>Fxi+{L%D`jxa%VhLF7ZtIOTWK=$(xltHGu)Bj}HonJOTnV zkqb`}oWFl=sS|Z?Gzw}VgufFs<%}mZ>HW#YTQ_pNUF+J#`G)q(SjfK1VW;`#`dGUA z?Ex$)kuWS^lZm+X{HTt8B+1A_imKV`c1Ygu)**2M0t5tzLTAzBp( z>=2UXRB@HWq<#{YL;W9W290k7W3BLdE-a0_c4(2Z)h)P?3e( zo1eC_aFVETK!AR}{5g@t1R&y}=zqMu4!o3qX9d9=#|+%0Ae{XemhSZ!vI?8gzYDha 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 M07*qoM6N<$g5k{71poj5 literal 26289 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 diff --git a/packages/grid/frontend/static/assets/small-syft-symbol-logo.png b/packages/grid/frontend/static/assets/small-syft-symbol-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..08086eac8e0d614aa0e098c9b317551584d780c3 GIT binary patch literal 33965 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

8cJLDH)k-ztTuExUk}G!t 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 #eEAVkE#75OY6MfXw)J;9y`PNty@DU*Jwq<_T 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 diff --git a/packages/syft/src/syft/assets/img/small-syft-symbol-logo.png b/packages/syft/src/syft/assets/img/small-syft-symbol-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..08086eac8e0d614aa0e098c9b317551584d780c3 GIT binary patch literal 33965 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

8cJLDH)k-ztTuExUk}G!t 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 #eEAVkE#75OY6MfXw)J;9y`PNty@DU*Jwq<_T zu4Q`K#0xf#mQuXBL4Kfj8tSFf#py?x+UZAAfjB$Y=(5(Jc26^kOZ<6V_EPnDJmXfAKX*i~h3u*RVf6uL-fsM9Qu?pL}0trhXH1 zqc@cfLO(CPTxD=au#{)5A3nG^xZK9(ic0~=A>-u-?=kXeknZV0T8uVDt3Mes+=4ZLpVbb}JGJ)QTP+*TDK*J7n+6D}ldDQ8g-~Vpep#^hSa!t{+Y5el#(wtrEas_wO zi>iU}Bj;@rn}P;w_VO;<8d2*bzWn-hLhvbrBx~63H0KJ(N(TT zckY50ZBnhAw#sZn;yJqux)D{J4gSVy1XLqa)ca=+&N-kFJ%ZSRNs>eU2ZrTX*`#rz zWZW-)n8$^b<|(VBGz0I=rZ5Pr*dcMix}QJ1CycU&6p336uqApBfNEmn4S5jxKfpab zSCiagbBN1Z)*p-KPr9D0#?aSA6W#YPV!NHGYyw_{u_?C7JukSHU1gRw&E8RP2UTr< zhwyt;E1odyfAL*!qNe@C;bgaBBpB+dlc1UekNl%SWehP>)}B2{uz_&XNEnH_DHT5o zqo83$I*bO`649dE{4oqc0ifAvF;r?vo}X_@Ota@?E{wm`74uz7?hr-sPPL|f!}JBy zqvqP+!tUXYook=M5DR{wq*H4TA*^eZ?0ojYY;O0{Eb;w=Q^j6o(57|q7@#)c#;M=W zIj$MQAe2*Bm>_pb-vSq^0b$Xl^qu12gG_BU>97KjKTy6GaDC#5IZ%VKv@U{~!YlL+ z_$B@(siDstGc1|A0*f(w*|l};RStVoaM^n_ZiG*v;?2)JIO>#^beA3|yi1nZTUyc# zpv5o&qWNepyJY(VDpPmj0}~c)O2o`{84r~N@M*fkuo`B%R)onA7fg9YGoC?|7ks7I zdT4{1`cYy2^!bLQyPf)U|g&!Jr&Ux|dtJ*YBKPnws0A7NX2Vuo(j?oZUgK_N;elV$M zlQ5$?ttdNxOqt8o_Ua35s*7tXbG8@bKlmKD2OdB z+mtM*WQf*uo9XEg21_6c|8R%o@Z8J~KcMu$iU^`)e~p%oCzb#V0C&vV8Lu(wfmT7s z;Ib#+RwRcK97$H5I+-{!5+WVFtZR31ieMM^;>DT;EP`Ew8VYQ?)6aTbm?XnIkG4q` z>t{l^>NRPkRyW$qwB&en$&N=6ZY?68LbP{}mOSZ2t3%rW+XA&PXJK!mdZxo=AsYfQ zxvjiG-m9+dlJNBDzFqd&1X?|J@|emX%XRo{b9b$K6xw+{BvYC`V6bxv_22#6gO6%z z_v5_2^kzXf%%bwRjau@qx_zRry58olciW$<_tqDz$<5W|gPpy(^xsrQxa&_uF)sxs zT)#GR;O86zGbc*`w)1pWWxdc(5|p**#J52^h-et=NtFC2zts(WgNm>@B8(S3j0G!S zg6=1H!9PYFUoutxP#_|<4)n`@XD5$D>-_$jPV&MhGd$3KG}lhrX?|31&)vB`l~QFD za2cu_Bb0dHLUZ4Yfg}H_M;$M|v3d~PbGR)m;&%-=C_Y8>pR05T^&Xp_QDMT$tf8=7 zYm>Mmd1G4lU7&VfBor~?c@sfA*im8gqMa+ zcKP(pT~$@2R~*LSp)^9$c~MU-ULH4w6a4F5ix;30QBC+)^&_g13PBK#yS>sU3#Vm< z68|p}_6;jLclX+RVTpYiVuP>b(XF3?@T?gRWk0W1!?5h_ebBxwQu;OZQbT2(UGn%v zJ67jZsFVy{m6fqSQo4cVN0*e&!nrH(S~$nR6tlmBO+EX2sa?8ttVdb?{51(P({wXZnufp>ElMtGxF?_FuCw>JJ zg&L}m237EvCy}Ij*Q88cLnZ~!_cwF$)e=5Gc?^R7*RaOvxnhT})7s}H?t!j>6Lg7G z^3oe??uRWcY+IPD2)=r^$jWOSHlJVM{e|=VG5l9Ytjx{ilXaSZKIf)`*Z&hnXCE3>)#AD)r`%m9wg2_o0cXgQ33y2I`RW9JWv#uX9j?Y9t2Zsq%PiM~$*+jy zl$9kY<+Yz;=-M+c-T=$vd3@QwfUvB^Hl3eB zL|%}Hy=v~{NBCymnk4Sqhk9Rx@av@s!M2I`m`H}qd?0&w+u6duyP#}&S4oig^0c5` zNxVLx8pGVgI=5t(m9M{=_$uv|Wi_WzW8ueJh@r0we`fLHNE7&cW_`xs`H|8ws{Gec zHmcS*s)uha*{QB!D*XMPK(l&;+O!KjJNqlHNtQw_XO{e2I6|0z0l{^U+ol9YKUWBQ zhf35>W#*QNR4)>b-=j#4=@*YRLNk&BdFSpe4po^6;ip-=y+Hb{9P{`#GiN@SJ+GB} znq6A-X2Boup?I=Ag3$IbXP=S23};otSGpO6&e}amL{LTh?Rd^N8F!%-k>|dBaRCBgN!P)cK3ToVnX@J`-R6 z;9LnH4SF7}>~i*|G|><*bD#y$$A6+k zYGCTe#%qj;B259TB6k=PZKM(MK^1HSlb<9B$N!oTXr>zM0XvGQHut*vkJ4O|`Wgq4 zeINn|v?}}*g*Mi@C8@GblDs~#HI45QDIbt{ZpE14FI>8y^l)L?IOefNeGYo)suPhcz}wRHE#o zRQ<;blXA}))%3!$!h~AN{tiBF_4sUJRlVI^Rc~u+nA?)I&s2quSd}~M?=5d=b>;biH)e-5vPb=yk6iAaJf25=W%QvJYNs9t6#LBUy z0UG?IcEfGvLT%#|d^6!TbLHLY+{t$T=QpR@pb>WXXM`c`5eyAK#zgT)5OyCxdpSy- zDM#mz9b9MdN=Z%!JSj*_{Lf^*<|qUrxc;5np_x0u3+xYg6+C zXqW5;4avd)!QNUoeDK||xK_Qxzg${&givTL&zRRaA(5=Y3(Z%Pv}*Hnr#O74AOuzH zXdVjf*v-qhKx@E&wgJLqCsUPusz-Qz!Sw6~v$ctD6WOIf?1x$Fd2oZeH%$Jx2h|Qo zH)rPJ0ouE{1oHG_41KRFuPKF)8W4D0i(?3p7qRxYU7trS>e8BqH3Zfg(IDwfD49`% zko=FhohR>91-20LmjAD1QD?2!-s5Do=S<&JJ`|3}j}@je*z53n*$)TmzsbyZf!G}t z3&xMA0ZLM66iA(YLQpE)DflP8WplD3~W4QJtyf$v+=YjXDyCpV!(K|H(9XL$? zw?Jx9Ip)!7&OoG{Rt1FqQpq7qR=hiJ(&&Fig_|%c%`4b)1E!_!!|?k#6u&ME5`jhP zKxc7}UR`Io`uG3Z%9y}RS{-L^-FmYsi*KU;T&)$&%XH|8;*3FkFQ3QOk);8e;CVIq ztrd}F&GcaWFKuAIE{5vp(_%t-8;TR$|X?bL_FYv`CSy|LXRt?h)2Jc!DisjNZzw(p#-vf3 zOZi?m5K>eRw<YgN^}vO!#jst|(hDCHrJ-BYm0sthH;Cun^}asw#7!?S&oc z>@vl#9i0-0{Lm}ej~xEmRUJ>Vw(ji56dA%vuSqm|)@D=str;?;TE}MSO4=F%>k4o9 z#J?IU?n3Or{eG!_FlE9re94opJziypHt4HMb%t$x51uRfAvB=BK=5t%6Lv!NdFoWb zUA=hfR379YZW4E8>Cz|+gFDA8Xf!vXVOnE*906$`cqR7{9v;iEq^b)4c|v86m>HV(?ESV*{OrY|sQ;M+cb?AWL~6dUyzxM^Y1%Oy#2C*fD96GEcxkW~@!MagR`vW9E!ch??IBe!h1 zUSPI^_^73~mpAPDj2$k{d^qC0PQtEVqk?fE0P`m@J4R%3Ch_92b1egtM#4|5lpVYF zkNrd<{RW!RkHE8D`}8)!0W-xPB!@cd-k(@qFK0Z_@HTe z)?ox~Erw7=@Y!Y^co;uWyz<`s$x9EYglv;U@>fA{9G|xE(Ti;sjM1B83!dQ`+XmPN zcV2U&q${h%fFcsP# zpHug)_)=x+lPj|`HhndNZ(!AgjM%WFt7uaXU_y%vd%e>}guWlCcO^#9j|&0F zftojY=^xOTpcZ7~3wa((u@J3UF0k1WtFAkfQj=Md$v2;|QVb&CVoW%*aeFsW@#SES zW1jI%U{#_Z3|KZ=zc_yFwJEEl6uT3W|7;)dz3Jbob%AnVxN2#hb>d<(Wy`V};v`@yNM6C14} z!N`ZALI*9&8+M}A`vzPbxuvwfppf0bK$E3haWM(Pk*@bk z<%tgEC=Ag3LO>pK2DBHx0==+G^(U%Loj-r_61a!Z*I+w(M|8UnOxo(i z(xYMdla~B{%z*CIgEoLVi`VS~ESq?nDQx?*FHee@P)>T_VIaqk>q!+}T0w|AP8N2q$sdiWn_h>n z@3UB&yU!=f?>Z~G{d3-=C6n@>&ez=s%b4~>ua=30o4S9|r{5Zc)jEh5{6%nL2H^)* zgz*<03SUAO)x?80B+!InBZVIttSXFbifY4ks61{aL7K6lSl`OXB%C+J(QCf0+X3Ym z@<_W^;|qBQZS1rdf^a{M@gr}_DmyrH>Eue?s*e}K@L!p*e)GLd5k|?BaV^8njj-_N zGeHX(Vnfip6f7(hHt&iR6Z~4zk7Zg@cJFpHme+qrq{0@oBhpaw+C#xeIb?AE zl{v#d)Sh_g6i08_at%?Xqxdo;g5{$f4oH_W;2q>7cXxs@vj`F<8OSWR=#}E@D z4j)5o=}3h)px5khr(bxhquLGgR+o0NN%C0Wk&WkcD}K5!RSUg8(Bmp&LsyL%{(k6X z^(ir`q_hMtEf3*kXi`=7;D(<+yxY)94X7+G1>g&lUb#o5%HIsYFVZT$zz}bpO2t1B z8#(dpi;sU6DM7QBf2?p@Z&g$t1fP5&!F(FuWdQ%-m(_uVd70&xFGcrg^rq55@I>I6 zvcaY+cA+@qVI4M9iY}hK_P7*)Jm%Z{$uFNk>v~5Y;-ENCV9;(v#OJf%eHlxZie}_b zs0pfMjARPSHdB;tHs=g2W3~_i4Y&Y!L zJ2Cq^Fz{Nu92@*4F$Oj~FgAb6(gU#F^fso(h-(p{33kG;_!bDlMYKVl4|kq-alBuk zSm17V@14G2ddx-M;43z$qw76bsy3DpFE>e;T<{@w5FxL47@f7&M8c2vE`g~Fq9Ocv z-6|t-5&DX^rDcjs0mvH(Ve%UO@Y%#zOnhnA-4Kd*tBg)3onG_E2A^duysgFVUJSGT)oqV(61Y#pD_H->@thb8|-+#hM>;Hh4WE_Hz z#^lEos~di@dQ8TVp0OOZLk0=d}8@EKG~1X zP2+M3zfBw{#fC`i1GF8RAt}35Mcn`FvWZn~mI?Ca_@XWSVU^Fru<>W0-!;f$X3KVj zDe9<|xtWK|#u(>k%(iWP6}d_HL}%#BnLz)sHFW;&n%w@TwKsD%BS~>B09~#!TVlmW zf58yv`;mYY4`pH1#~vwcABN1U1VK7%v!#A9ZDH_HJ@~|inyB1KnLGoXWVQ|qWb$nkOqZGh9Z(0i?ZUJWy@c3rzuu5B_;=CcK>wQKFBn1qW-eEMSz+p$ zfJ+_r5JD>v+S)^y;e3@b`Jmrlet7n_~fsFhav%mMp+%pc5;kXxo91l1ZZ@?cOI^9Y^ARya?Q)j=GcC}&?9qeCY zgc$E93~_9Q*(5Lp82vfdgQE z9mkdc3;?99Lz_>%{`x}|#GfF_K8KBYI@^`HZV5g`6jItMXVQCopX4X19Lj2w^4H9k zo!Vc3CJqPk=qFXR{Wbbr=+8li5P*V0|EY>*=vMkaP%UeaJcdLp8>pPjy_`i(+{OayqO7gK0E($k3S|-$(v+XDz8mC?@N}h!fmtl zr5Y-dyH;flKSpvwX=rrvGF4s*O*J}|x2%=Y{F02|Jp@`7kEL^yAg(`Tb0;p%funGt z{xx;H8Wc$&-ejrXlO!cJcCov?iITCwI$J_c$x&4hN30q(sDv}j4!#2`xMu1Fo936Z+W+MIIj-8W*uvTfaq6AVwE>J?M%IJ-QkN# zeGXnA7&2GeJ+e=bRRv#JxRe=`82K3PK0k^D;l~lFJMsDV@CVBX&64Q5J&*jo!@MUQ zMgxR1G|iv<@}JP)pO~eq#XTPYTaiS+-yw+gX$juit_dm=1^u)`h6q5CFMGwvkuebj zBWvr{tC(VY4+e$qX6XxfWWQgRG5D8e;YV*iI*bO$BdNd_aKGMwTJ!@DfMHPdDN;h6 zU+8+O&UwSZ@}z5zT$DSXb2m6^{j#7icR=n)4*e+nD)FczVnz7z#xhlW(M-aR^CU2F zBmdh`QilO{k%4*$Hy0K7%Dq^d|XBB4f452_=TKZ+vCLH zVJjwN#!M9Lky}cCh@h1wvHN|6K4a&LG9NO%-87QE(z0xa5`YK>z#s0RmLOQ?(L=yl z>mxlstnA+VoeKoQ(3^gyUUf9e+y=#?Gq;y`o@vxw`MBPZZ`xxdl>0eN;qBS>P|6sR zm(pd1)MKJb%;vhFJ2Z$=TmY%Rh}#5pugt0-Xaq!=5eP#E7l>WHXy~HY1X6dEv$~;+ zBT2T46suEO_SG6_P`_9)W_VH1m6#wS-_%?t?6;Vx>1+aanpwch;KjQ6oy`|I$U)0a z75B}yQQ>ukDSUs86Lwq;g}qlHA$zhB@Y;O!lJR*oy9i_(&e`X%}wz`trG*uipDx=hy#oW&W^r)deO- z$+&BAPM7?4c%Eu?+o)uFad(E>x93q4%x1MYOtn9x-|_x^(yArDT int: def get_client_type(self) -> type[SyftClient] | SyftError: # TODO: Rasswanth, should remove passing in credentials - # when metadata are proxy forwarded in the grid routes + # when metadata are proxy forwarded in the server routes # in the gateway fixes PR # relative from .datasite_client import DatasiteClient diff --git a/packages/syft/src/syft/client/enclave_client.py b/packages/syft/src/syft/client/enclave_client.py index 92ccd076804..fc0544e03ad 100644 --- a/packages/syft/src/syft/client/enclave_client.py +++ b/packages/syft/src/syft/client/enclave_client.py @@ -117,7 +117,7 @@ def _repr_html_(self) -> str: """ - small_grid_symbol_logo = load_png_base64("small-grid-symbol-logo.png") + small_server_symbol_logo = load_png_base64("small-syft-symbol-logo.png") url = getattr(self.connection, "url", None) server_details = f"URL: {url}
" if url else "" @@ -160,7 +160,7 @@ def _repr_html_(self) -> str: }}

- Logo

Welcome to {self.name}

diff --git a/packages/syft/src/syft/client/gateway_client.py b/packages/syft/src/syft/client/gateway_client.py index 003c7aa958b..c8e4929f99e 100644 --- a/packages/syft/src/syft/client/gateway_client.py +++ b/packages/syft/src/syft/client/gateway_client.py @@ -93,7 +93,7 @@ def _repr_html_(self) -> str: """ - small_grid_symbol_logo = load_png_base64("small-grid-symbol-logo.png") + small_server_symbol_logo = load_png_base64("small-syft-symbol-logo.png") url = getattr(self.connection, "url", None) server_details = f"URL: {url}
" if url else "" @@ -136,7 +136,7 @@ def _repr_html_(self) -> str: }}
- Logo

Welcome to {self.name}

diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index a79ae863d68..6602155d200 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -267,6 +267,11 @@ } }, "ServerSettings": { + "3": { + "version": 3, + "hash": "6b2240b92099684b0e431d27c0be2a22daad234b890c95eb607f0cc9e73c9f0d", + "action": "add" + }, "5": { "version": 5, "hash": "522690efe97c50dff81936640e95207861406e480d7e1d87587e558dbd7a506c", @@ -281,7 +286,7 @@ "HTTPConnection": { "3": { "version": 3, - "hash": "b58f9e16879e87169ccfac55504c8ae65dbc7a8345f6e361af4133e5572e2b13", + "hash": "2e567111a679e9f01b84eafc96d5e14e52b12fea991957e547f2edcbc0ede34c", "action": "add" } }, @@ -422,12 +427,12 @@ "BlobRetrievalByURL": { "4": { "version": 4, - "hash": "4ed706c90c5835959993bf9ebd61577829cdf8d2e51d4fd9606c68928f7be658", + "hash": "6a77259a8c83f85e83e89cee4c7ea7b1d57ccac4f70ecfb86b6c5db21c62ee79", "action": "add" }, "5": { "version": 5, - "hash": "2c6528e3efa7473a73951c4dec5e58547afdec8d0ba58807a0556733fd6217a5", + "hash": "e9c5e16f14e5bd45209f44ebf6c758a8c4a315b2d335a33bc529606506037890", "action": "add" } }, @@ -554,6 +559,11 @@ } }, "SyftLog": { + "3": { + "version": 3, + "hash": "c2ee3f4c34dc7af3af533865dc07384403fb757e7959272c9d6d08110623a216", + "action": "add" + }, "4": { "version": 4, "hash": "3b90dcb66359a1d03345291b47dcb8b5c166b1e0344dbe84d9c1f3a8e57f99eb", @@ -561,6 +571,11 @@ } }, "JobItem": { + "4": { + "version": 4, + "hash": "3e2eaae1b2c367b5bc52cbc4eb3390b1f5a6a6f8cae69523bbfc8e071c314bf8", + "action": "add" + }, "6": { "version": 6, "hash": "b633f770c9c47a849b75fe6b93c573c94eadab23c689aa812a8671cec9543650", @@ -568,6 +583,11 @@ } }, "ExecutionOutput": { + "1": { + "version": 1, + "hash": "c6cb71d6ae689e71c31685c29a7ecd44d1c0c5b31fd19991b535cb597db7b44a", + "action": "add" + }, "2": { "version": 2, "hash": "1b045334d8049f3970e655da11f3f62bc8a9f78e562fd75ed517c97fc95bb1c3", @@ -781,7 +801,7 @@ "SeaweedFSBlobDeposit": { "4": { "version": 4, - "hash": "84cdecd1a4ae0713a1e2992ba00ef74363996855c0b864b6fcd0e2fef2e3b44c", + "hash": "d5c268e0ccbb00149319679b95eb43134ae80ae43814d7f991732530c79399a1", "action": "add" } }, @@ -1156,6 +1176,20 @@ "hash": "eec308b8fd9437fc74a65f0cf70dff586130b35866d1e1512de49d45e7896981", "action": "add" } + }, + "StoreMetadata": { + "1": { + "version": 1, + "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", + "action": "add" + } + }, + "MigrationData": { + "1": { + "version": 1, + "hash": "ae07a6345762b8ebe9d2a100776e2405fd17516c9d224913a3358c96480ba889", + "action": "add" + } } } } diff --git a/packages/syft/src/syft/server/uvicorn.py b/packages/syft/src/syft/server/uvicorn.py index ad1a5eee238..3626db6aa13 100644 --- a/packages/syft/src/syft/server/uvicorn.py +++ b/packages/syft/src/syft/server/uvicorn.py @@ -162,7 +162,7 @@ def run_uvicorn( # Finally, run the uvicorn server. uvicorn.run( - "syft.server.server:app_factory", + "syft.server.uvicorn:app_factory", host=host, port=port, factory=True, diff --git a/packages/syft/src/syft/service/settings/settings_service.py b/packages/syft/src/syft/service/settings/settings_service.py index 5df9d9755e7..a59773a0280 100644 --- a/packages/syft/src/syft/service/settings/settings_service.py +++ b/packages/syft/src/syft/service/settings/settings_service.py @@ -351,7 +351,7 @@ def welcome_show( """ result = str_tmp.safe_substitute( FONT_CSS=FONT_CSS, - grid_symbol=load_png_base64("small-grid-symbol-logo.png"), + server_symbol=load_png_base64("small-syft-symbol-logo.png"), datasite_name=context.server.name, description=context.server.metadata.description, # server_url='http://testing:8080', diff --git a/packages/syft/src/syft/service/worker/utils.py b/packages/syft/src/syft/service/worker/utils.py index bc84a138b31..55d608c2964 100644 --- a/packages/syft/src/syft/service/worker/utils.py +++ b/packages/syft/src/syft/service/worker/utils.py @@ -567,7 +567,7 @@ def create_default_image( in_kubernetes: bool = False, ) -> SyftError | SyftWorkerImage: if not in_kubernetes: - tag = f"openmined/grid-backend:{tag}" + tag = f"openmined/syft-backend:{tag}" worker_config = PrebuiltWorkerConfig( tag=tag, diff --git a/packages/syft/src/syft/util/schema.py b/packages/syft/src/syft/util/schema.py index 56e443b1b7d..fd284fa6e87 100644 --- a/packages/syft/src/syft/util/schema.py +++ b/packages/syft/src/syft/util/schema.py @@ -57,7 +57,7 @@ }
- Logo

Welcome to $datasite_name

diff --git a/packages/syft/tests/syft/assets_test.py b/packages/syft/tests/syft/assets_test.py index 498094b9300..acc2297f1df 100644 --- a/packages/syft/tests/syft/assets_test.py +++ b/packages/syft/tests/syft/assets_test.py @@ -9,7 +9,7 @@ def test_load_assets(): - png = load_png_base64("logo.png") + png = load_png_base64("small-syft-symbol-logo.png") assert isinstance(png, str) with pytest.raises(FileNotFoundError): diff --git a/packages/syft/tests/syft/custom_worker/config_test.py b/packages/syft/tests/syft/custom_worker/config_test.py index 76a353e2d3b..3777be6e222 100644 --- a/packages/syft/tests/syft/custom_worker/config_test.py +++ b/packages/syft/tests/syft/custom_worker/config_test.py @@ -166,7 +166,7 @@ def test_load_custom_worker_config( DOCKER_METHODS = ["from_str", "from_path"] DOCKER_CONFIG_OPENDP = f""" - FROM openmined/grid-backend:{sy.__version__} + FROM openmined/syft-backend:{sy.__version__} RUN pip install opendp """ diff --git a/packages/syft/tests/syft/worker_pool/worker_pool_service_test.py b/packages/syft/tests/syft/worker_pool/worker_pool_service_test.py index 70219984d58..b5c5ea2f3a3 100644 --- a/packages/syft/tests/syft/worker_pool/worker_pool_service_test.py +++ b/packages/syft/tests/syft/worker_pool/worker_pool_service_test.py @@ -16,7 +16,7 @@ # relative from ..request.request_code_accept_deny_test import get_ds_client -PREBUILT_IMAGE_TAG = f"docker.io/openmined/grid-backend:{sy.__version__}" +PREBUILT_IMAGE_TAG = f"docker.io/openmined/syft-backend:{sy.__version__}" CUSTOM_DOCKERFILE = f""" FROM {PREBUILT_IMAGE_TAG} diff --git a/packages/syft/tests/syft/worker_pool/worker_test.py b/packages/syft/tests/syft/worker_pool/worker_test.py index e65a3334273..4da24cb315b 100644 --- a/packages/syft/tests/syft/worker_pool/worker_test.py +++ b/packages/syft/tests/syft/worker_pool/worker_test.py @@ -10,7 +10,7 @@ def get_docker_config(): # the DS makes a request to create an image and a pool based on the image custom_dockerfile = f""" - FROM openmined/grid-backend:{sy.__version__} + FROM openmined/syft-backend:{sy.__version__} RUN pip install recordlinkage """ return DockerWorkerConfig(dockerfile=custom_dockerfile) diff --git a/packages/syftcli/manifest.yml b/packages/syftcli/manifest.yml index 966706f9b11..809fb7cfb9d 100644 --- a/packages/syftcli/manifest.yml +++ b/packages/syftcli/manifest.yml @@ -4,8 +4,8 @@ syftVersion: 0.8.7-beta.13 dockerTag: 0.8.7-beta.13 images: - - docker.io/openmined/grid-frontend:0.8.7-beta.13 - - docker.io/openmined/grid-backend:0.8.7-beta.13 + - docker.io/openmined/syft-frontend:0.8.7-beta.13 + - docker.io/openmined/syft-backend:0.8.7-beta.13 - docker.io/library/mongo:7.0.4 - docker.io/traefik:v2.11.0 diff --git a/scripts/build_images.sh b/scripts/build_images.sh index 3426b5049de..bf7ad7e1823 100644 --- a/scripts/build_images.sh +++ b/scripts/build_images.sh @@ -3,6 +3,6 @@ REGISTRY=${1:-"k3d-registry.localhost:5800"} TAG=${2:-"latest"} -docker image build -f ./packages/grid/backend/backend.dockerfile --target backend -t $REGISTRY/openmined/grid-backend:$TAG ./packages -docker image build -f ./packages/grid/frontend/frontend.dockerfile --target grid-ui-development -t $REGISTRY/openmined/grid-frontend:$TAG ./packages/grid/frontend -docker image build -f ./packages/grid/seaweedfs/seaweedfs.dockerfile -t $REGISTRY/openmined/grid-seaweedfs:$TAG ./packages/grid/seaweedfs +docker image build -f ./packages/grid/backend/backend.dockerfile --target backend -t $REGISTRY/openmined/syft-backend:$TAG ./packages +docker image build -f ./packages/grid/frontend/frontend.dockerfile --target syft-ui-development -t $REGISTRY/openmined/syft-frontend:$TAG ./packages/grid/frontend +docker image build -f ./packages/grid/seaweedfs/seaweedfs.dockerfile -t $REGISTRY/openmined/syft-seaweedfs:$TAG ./packages/grid/seaweedfs diff --git a/scripts/flush_queue.sh b/scripts/flush_queue.sh deleted file mode 100755 index fbb2914bc33..00000000000 --- a/scripts/flush_queue.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -docker ps --format '{{.Names}}' | grep "celeryworker" | xargs -I '{}' docker exec -i {} python -c "from grid.core.celery_app import celery_app; celery_app.control.purge();print('Tasks Cleared')" diff --git a/tests/integration/container_workload/pool_image_test.py b/tests/integration/container_workload/pool_image_test.py index 6024a4b7b3a..10eab93ad31 100644 --- a/tests/integration/container_workload/pool_image_test.py +++ b/tests/integration/container_workload/pool_image_test.py @@ -21,7 +21,7 @@ from syft.util.util import get_latest_tag registry = os.getenv("SYFT_BASE_IMAGE_REGISTRY", "docker.io") -repo = "openmined/grid-backend" +repo = "openmined/syft-backend" if "k3d" in registry: tag = get_latest_tag(registry, repo) diff --git a/tox.ini b/tox.ini index ac6ba7f7b3f..9b67b7cfb06 100644 --- a/tox.ini +++ b/tox.ini @@ -178,7 +178,7 @@ commands = pnpm install; \ pnpm run test:unit; \ else \ - docker build --target grid-ui-tests -t ui-test -f frontend.dockerfile .; \ + docker build --target syft-ui-tests -t ui-test -f frontend.dockerfile .; \ docker run -t ui-test; \ fi' @@ -310,7 +310,7 @@ allowlist_externals = bash commands = bash -c 'tox -e single_container.destroy' - bash -c 'docker build -f grid/backend/backend.dockerfile . -t openmined/grid-backend:local-dev' + bash -c 'docker build -f grid/backend/backend.dockerfile . -t openmined/syft-backend:local-dev' bash -c 'docker run -d \ -e SERVER_NAME=${SERVER_NAME} \ -e SERVER_TYPE=${SERVER_TYPE} \ @@ -319,7 +319,7 @@ commands = -e CREATE_PRODUCER=true \ -e INMEMORY_WORKERS=true \ -p ${SERVER_PORT}:80 --add-host=host.docker.internal:host-gateway \ - --name ${SERVER_NAME} openmined/grid-backend:local-dev' + --name ${SERVER_NAME} openmined/syft-backend:local-dev' [testenv:single_container.destroy] description = Destroy the single backend container run using single_container.launch From 198cb53620cbfcc32dae7ac675976b091a45cf82 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Fri, 12 Jul 2024 09:47:30 +0200 Subject: [PATCH 045/117] disable migration tests --- .github/workflows/pr-tests-stack.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-tests-stack.yml b/.github/workflows/pr-tests-stack.yml index 26098bfa9fa..458092a16c5 100644 --- a/.github/workflows/pr-tests-stack.yml +++ b/.github/workflows/pr-tests-stack.yml @@ -417,6 +417,7 @@ jobs: k3d registry delete k3d-registry.localhost || true pr-tests-migrations: + if: false strategy: max-parallel: 99 matrix: From 5e0f2244f5dba93ba2250bb579ef180036c18e51 Mon Sep 17 00:00:00 2001 From: alfred-openmined-bot <145415986+alfred-openmined-bot@users.noreply.github.com> Date: Sun, 14 Jul 2024 12:50:03 +0000 Subject: [PATCH 046/117] [syft]bump version --- .bumpversion.cfg | 2 +- VERSION | 2 +- packages/grid/VERSION | 2 +- .../backend/grid/images/worker_cpu.dockerfile | 2 +- packages/grid/devspace.yaml | 2 +- packages/grid/frontend/package.json | 2 +- packages/grid/helm/repo/index.yaml | 189 +-- .../grid/helm/repo/syft-0.8.7-beta.14.tgz | Bin 0 -> 19241 bytes packages/grid/helm/syft/Chart.yaml | 4 +- packages/grid/helm/syft/templates/NOTES.txt | 1158 ++++++++++++++--- packages/grid/helm/syft/values.yaml | 2 +- packages/syft/setup.cfg | 2 +- packages/syft/src/syft/VERSION | 2 +- packages/syft/src/syft/__init__.py | 2 +- packages/syftcli/manifest.yml | 8 +- 15 files changed, 1120 insertions(+), 259 deletions(-) create mode 100644 packages/grid/helm/repo/syft-0.8.7-beta.14.tgz diff --git a/.bumpversion.cfg b/.bumpversion.cfg index cd48a82318d..e146a7c8c8b 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.7-beta.13 +current_version = 0.8.7-beta.14 tag = False tag_name = {new_version} commit = True diff --git a/VERSION b/VERSION index df1dec5602a..0c01f370f55 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.13" +__version__ = "0.8.7-beta.14" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/VERSION b/packages/grid/VERSION index df1dec5602a..0c01f370f55 100644 --- a/packages/grid/VERSION +++ b/packages/grid/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.13" +__version__ = "0.8.7-beta.14" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/backend/grid/images/worker_cpu.dockerfile b/packages/grid/backend/grid/images/worker_cpu.dockerfile index 3095c703e22..a873bbead6d 100644 --- a/packages/grid/backend/grid/images/worker_cpu.dockerfile +++ b/packages/grid/backend/grid/images/worker_cpu.dockerfile @@ -5,7 +5,7 @@ # NOTE: This dockerfile will be built inside a syft-backend container in PROD # Hence COPY will not work the same way in DEV vs. PROD -ARG SYFT_VERSION_TAG="0.8.7-beta.13" +ARG SYFT_VERSION_TAG="0.8.7-beta.14" FROM openmined/syft-backend:${SYFT_VERSION_TAG} # should match base image python version diff --git a/packages/grid/devspace.yaml b/packages/grid/devspace.yaml index 0a00e7767f7..7920791b541 100644 --- a/packages/grid/devspace.yaml +++ b/packages/grid/devspace.yaml @@ -28,7 +28,7 @@ vars: DOCKER_IMAGE_RATHOLE: openmined/syft-rathole DOCKER_IMAGE_ENCLAVE_ATTESTATION: openmined/syft-enclave-attestation CONTAINER_REGISTRY: "docker.io" - VERSION: "0.8.7-beta.13" + VERSION: "0.8.7-beta.14" PLATFORM: $(uname -m | grep -q 'arm64' && echo "arm64" || echo "amd64") # This is a list of `images` that DevSpace can build for this project diff --git a/packages/grid/frontend/package.json b/packages/grid/frontend/package.json index b2969306994..180462c5d6f 100644 --- a/packages/grid/frontend/package.json +++ b/packages/grid/frontend/package.json @@ -1,6 +1,6 @@ { "name": "syft-ui", - "version": "0.8.7-beta.13", + "version": "0.8.7-beta.14", "private": true, "scripts": { "dev": "pnpm i && vite dev --host --port 80", diff --git a/packages/grid/helm/repo/index.yaml b/packages/grid/helm/repo/index.yaml index 56fdc4275cb..088ca146c2c 100644 --- a/packages/grid/helm/repo/index.yaml +++ b/packages/grid/helm/repo/index.yaml @@ -1,9 +1,22 @@ apiVersion: v1 entries: syft: + - apiVersion: v2 + appVersion: 0.8.7-beta.14 + created: "2024-07-14T12:48:16.383106715Z" + description: Perform numpy-like analysis on data that remains in someone elses + server + digest: 6e7cbca1d603ba11e09ae2a3089cfdafaa08cfa07c553c4f0fb8b42f8d3028f7 + home: https://github.com/OpenMined/PySyft/ + icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png + name: syft + type: application + urls: + - https://openmined.github.io/PySyft/helm/syft-0.8.7-beta.14.tgz + version: 0.8.7-beta.14 - apiVersion: v2 appVersion: 0.8.7-beta.13 - created: "2024-06-25T14:52:54.915182775Z" + created: "2024-07-14T12:48:16.381397481Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1dbe3ecdfec57bf25020cbcff783fab908f0eb0640ad684470b2fd1da1928005 @@ -16,7 +29,7 @@ entries: version: 0.8.7-beta.13 - apiVersion: v2 appVersion: 0.8.7-beta.12 - created: "2024-06-25T14:52:54.914499475Z" + created: "2024-07-14T12:48:16.380688282Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e92b2f3a522dabb3a79ff762a7042ae16d2bf3a53eebbb2885a69b9f834d109c @@ -29,7 +42,7 @@ entries: version: 0.8.7-beta.12 - apiVersion: v2 appVersion: 0.8.7-beta.11 - created: "2024-06-25T14:52:54.913815474Z" + created: "2024-07-14T12:48:16.379990154Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 099f6cbd44b699ee2410a4be012ed1a8a65bcacb06a43057b2779d7fe34fc0ad @@ -42,7 +55,7 @@ entries: version: 0.8.7-beta.11 - apiVersion: v2 appVersion: 0.8.7-beta.10 - created: "2024-06-25T14:52:54.913093962Z" + created: "2024-07-14T12:48:16.379291705Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 00773cb241522e281c1915339fc362e047650e08958a736e93d6539f44cb5e25 @@ -55,7 +68,7 @@ entries: version: 0.8.7-beta.10 - apiVersion: v2 appVersion: 0.8.7-beta.9 - created: "2024-06-25T14:52:54.921044649Z" + created: "2024-07-14T12:48:16.388267418Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a3f8e85d9ddef7a644b959fcc2fcb0fc08f7b6abae1045e893d0d62fa4ae132e @@ -68,7 +81,7 @@ entries: version: 0.8.7-beta.9 - apiVersion: v2 appVersion: 0.8.7-beta.8 - created: "2024-06-25T14:52:54.920407065Z" + created: "2024-07-14T12:48:16.387623261Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a422ac88d8fd1fb80d5004d5eb6e95fa9efc7f6a87da12e5ac04829da7f04c4d @@ -81,7 +94,7 @@ entries: version: 0.8.7-beta.8 - apiVersion: v2 appVersion: 0.8.7-beta.7 - created: "2024-06-25T14:52:54.919767347Z" + created: "2024-07-14T12:48:16.386972992Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0dc313a1092e6256a7c8aad002c8ec380b3add2c289d680db1e238a336399b7a @@ -94,7 +107,7 @@ entries: version: 0.8.7-beta.7 - apiVersion: v2 appVersion: 0.8.7-beta.6 - created: "2024-06-25T14:52:54.91914935Z" + created: "2024-07-14T12:48:16.386341078Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 052a2ec1102d2a4c9915f95647abd4a6012f56fa05a106f4952ee9b55bf7bae8 @@ -107,7 +120,7 @@ entries: version: 0.8.7-beta.6 - apiVersion: v2 appVersion: 0.8.7-beta.5 - created: "2024-06-25T14:52:54.918496807Z" + created: "2024-07-14T12:48:16.385692963Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1728af756907c3fcbe87c2fd2de014a2d963c22a4c2eb6af6596b525a9b9a18a @@ -120,7 +133,7 @@ entries: version: 0.8.7-beta.5 - apiVersion: v2 appVersion: 0.8.7-beta.4 - created: "2024-06-25T14:52:54.917833966Z" + created: "2024-07-14T12:48:16.385048795Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 387a57a3904a05ed61e92ee48605ef6fd5044ff7e822e0924e0d4c485e2c88d2 @@ -133,7 +146,7 @@ entries: version: 0.8.7-beta.4 - apiVersion: v2 appVersion: 0.8.7-beta.3 - created: "2024-06-25T14:52:54.916857511Z" + created: "2024-07-14T12:48:16.384413735Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 3668002b7a4118516b2ecd61d6275f60d83fc12841587ab8f62e1c1200731c67 @@ -146,7 +159,7 @@ entries: version: 0.8.7-beta.3 - apiVersion: v2 appVersion: 0.8.7-beta.2 - created: "2024-06-25T14:52:54.915789101Z" + created: "2024-07-14T12:48:16.383772393Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e62217ffcadee2b8896ab0543f9ccc42f2df898fd979438ac9376d780b802af7 @@ -159,7 +172,7 @@ entries: version: 0.8.7-beta.2 - apiVersion: v2 appVersion: 0.8.7-beta.1 - created: "2024-06-25T14:52:54.912442092Z" + created: "2024-07-14T12:48:16.378617882Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 553981fe1d5c980e6903b3ff2f1b9b97431f6dd8aee91e3976bcc5594285235e @@ -172,7 +185,7 @@ entries: version: 0.8.7-beta.1 - apiVersion: v2 appVersion: 0.8.6 - created: "2024-06-25T14:52:54.911941434Z" + created: "2024-07-14T12:48:16.378070285Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ddbbe6fea1702e57404875eb3019a3b1a341017bdbb5fbc6ce418507e5c15756 @@ -185,7 +198,7 @@ entries: version: 0.8.6 - apiVersion: v2 appVersion: 0.8.6-beta.1 - created: "2024-06-25T14:52:54.911419657Z" + created: "2024-07-14T12:48:16.377535653Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: cc2c81ef6796ac853dce256e6bf8a6af966c21803e6534ea21920af681c62e61 @@ -198,7 +211,7 @@ entries: version: 0.8.6-beta.1 - apiVersion: v2 appVersion: 0.8.5 - created: "2024-06-25T14:52:54.910887971Z" + created: "2024-07-14T12:48:16.376992826Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: db5d90d44006209fd5ecdebd88f5fd56c70f7c76898343719a0ff8da46da948a @@ -211,7 +224,7 @@ entries: version: 0.8.5 - apiVersion: v2 appVersion: 0.8.5-post.2 - created: "2024-06-25T14:52:54.910132145Z" + created: "2024-07-14T12:48:16.376231799Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ea3f7269b55f773fa165d7008c054b7cf3ec4c62eb40a96f08cd3a9b77fd2165 @@ -224,7 +237,7 @@ entries: version: 0.8.5-post.2 - apiVersion: v2 appVersion: 0.8.5-post.1 - created: "2024-06-25T14:52:54.909328308Z" + created: "2024-07-14T12:48:16.37568788Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9deb844d3dc2d8480c60f8c631dcc7794adfb39cec3aa3b1ce22ea26fdf87d02 @@ -237,7 +250,7 @@ entries: version: 0.8.5-post.1 - apiVersion: v2 appVersion: 0.8.5-beta.10 - created: "2024-06-25T14:52:54.901637641Z" + created: "2024-07-14T12:48:16.368097513Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9cfe01e8f57eca462261a24a805b41509be2de9a0fee76e331d124ed98c4bc49 @@ -250,7 +263,7 @@ entries: version: 0.8.5-beta.10 - apiVersion: v2 appVersion: 0.8.5-beta.9 - created: "2024-06-25T14:52:54.908047519Z" + created: "2024-07-14T12:48:16.374916865Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 057f1733f2bc966e15618f62629315c8207773ef6211c79c4feb557dae15c32b @@ -263,7 +276,7 @@ entries: version: 0.8.5-beta.9 - apiVersion: v2 appVersion: 0.8.5-beta.8 - created: "2024-06-25T14:52:54.907301222Z" + created: "2024-07-14T12:48:16.373739578Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 921cbce836c3032ef62b48cc82b5b4fcbe44fb81d473cf4d69a4bf0f806eb298 @@ -276,7 +289,7 @@ entries: version: 0.8.5-beta.8 - apiVersion: v2 appVersion: 0.8.5-beta.7 - created: "2024-06-25T14:52:54.906546207Z" + created: "2024-07-14T12:48:16.372756916Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 75482e955b2b9853a80bd653afb1d56535f78f3bfb7726798522307eb3effbbd @@ -289,7 +302,7 @@ entries: version: 0.8.5-beta.7 - apiVersion: v2 appVersion: 0.8.5-beta.6 - created: "2024-06-25T14:52:54.905804338Z" + created: "2024-07-14T12:48:16.371971694Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6a2dfaf65ca855e1b3d7b966d4ff291e6fcbe761e2fc2a78033211ccd3a75de0 @@ -302,7 +315,7 @@ entries: version: 0.8.5-beta.6 - apiVersion: v2 appVersion: 0.8.5-beta.5 - created: "2024-06-25T14:52:54.905005392Z" + created: "2024-07-14T12:48:16.371178147Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fead03823bef04d66901d563aa755c68ab277f72b126aaa6f0dce76a6f3bdb6d @@ -315,7 +328,7 @@ entries: version: 0.8.5-beta.5 - apiVersion: v2 appVersion: 0.8.5-beta.4 - created: "2024-06-25T14:52:54.904263382Z" + created: "2024-07-14T12:48:16.370401542Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 93e4539d5726a7fd0d6a3e93d1c17c6a358a923ddc01d102eab22f37377502ab @@ -328,7 +341,7 @@ entries: version: 0.8.5-beta.4 - apiVersion: v2 appVersion: 0.8.5-beta.3 - created: "2024-06-25T14:52:54.90351485Z" + created: "2024-07-14T12:48:16.369609467Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: f91e9390edf3441469048f5da646099af98f8b6d199409d0e2c1e6da3a51f054 @@ -341,7 +354,7 @@ entries: version: 0.8.5-beta.3 - apiVersion: v2 appVersion: 0.8.5-beta.2 - created: "2024-06-25T14:52:54.902672242Z" + created: "2024-07-14T12:48:16.368859942Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 59159c3aa4888038edc3c0135c83402363d7a0639fe62966a1e9d4928a364fa8 @@ -354,7 +367,7 @@ entries: version: 0.8.5-beta.2 - apiVersion: v2 appVersion: 0.8.5-beta.1 - created: "2024-06-25T14:52:54.900351402Z" + created: "2024-07-14T12:48:16.36732211Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 65aeb74c52ed8ba5474af500b4c1188a570ee4cb1f2a2da356b3488d28356ed9 @@ -366,7 +379,7 @@ entries: version: 0.8.5-beta.1 - apiVersion: v2 appVersion: 0.8.4 - created: "2024-06-25T14:52:54.899982841Z" + created: "2024-07-14T12:48:16.366927711Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 08afea8e3a9eef225b7e611f0bc1216c140053ef8e51439b02337faeac621fd0 @@ -378,7 +391,7 @@ entries: version: 0.8.4 - apiVersion: v2 appVersion: 0.8.4-beta.31 - created: "2024-06-25T14:52:54.897562879Z" + created: "2024-07-14T12:48:16.363695182Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fabf3e2f37e53fa623f5d3d99b00feae06e278e5cd63bce419089946312ab1fc @@ -390,7 +403,7 @@ entries: version: 0.8.4-beta.31 - apiVersion: v2 appVersion: 0.8.4-beta.30 - created: "2024-06-25T14:52:54.897124859Z" + created: "2024-07-14T12:48:16.363285764Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e8f792709f73ec14eab48a268bdf50a4505b340bd142cddd7c7bfffd94009ad @@ -402,7 +415,7 @@ entries: version: 0.8.4-beta.30 - apiVersion: v2 appVersion: 0.8.4-beta.29 - created: "2024-06-25T14:52:54.896384402Z" + created: "2024-07-14T12:48:16.362505462Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 4c985d6a9b3456769c4013f9e85e7374c0f963d2d27627e61f914f5537de1971 @@ -414,7 +427,7 @@ entries: version: 0.8.4-beta.29 - apiVersion: v2 appVersion: 0.8.4-beta.28 - created: "2024-06-25T14:52:54.895981798Z" + created: "2024-07-14T12:48:16.361966622Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: bd2aa3c92c768c47c502e31a326f341addcb34e64d22cdcbf5cc3f19689d859c @@ -426,7 +439,7 @@ entries: version: 0.8.4-beta.28 - apiVersion: v2 appVersion: 0.8.4-beta.27 - created: "2024-06-25T14:52:54.895572461Z" + created: "2024-07-14T12:48:16.361557665Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e8ad0869993af39d7adda8cb868dc0b24cfb63b4bb9820dc579939c1007a60ba @@ -438,7 +451,7 @@ entries: version: 0.8.4-beta.27 - apiVersion: v2 appVersion: 0.8.4-beta.26 - created: "2024-06-25T14:52:54.895153567Z" + created: "2024-07-14T12:48:16.361149991Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 30dccf630aa25a86a03c67572fe5411687d8ce6d58def448ea10efdba2b85e3a @@ -450,7 +463,7 @@ entries: version: 0.8.4-beta.26 - apiVersion: v2 appVersion: 0.8.4-beta.25 - created: "2024-06-25T14:52:54.894459409Z" + created: "2024-07-14T12:48:16.360740353Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b6e2043bcf5a0335967d770c7939f5a7832955359a7d871c90b265660ff26e5f @@ -462,7 +475,7 @@ entries: version: 0.8.4-beta.25 - apiVersion: v2 appVersion: 0.8.4-beta.24 - created: "2024-06-25T14:52:54.893613495Z" + created: "2024-07-14T12:48:16.360330315Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b19efa95394d50bb8d76da6ec306de5d3bb9ea55371fafea95a1282a697fa33e @@ -474,7 +487,7 @@ entries: version: 0.8.4-beta.24 - apiVersion: v2 appVersion: 0.8.4-beta.23 - created: "2024-06-25T14:52:54.893200211Z" + created: "2024-07-14T12:48:16.359913894Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 5c5d05c15bff548574896118ce92335ae10c5b78f5307fe9b2618e5a5aa71a5c @@ -486,7 +499,7 @@ entries: version: 0.8.4-beta.23 - apiVersion: v2 appVersion: 0.8.4-beta.22 - created: "2024-06-25T14:52:54.892776578Z" + created: "2024-07-14T12:48:16.359493016Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0160dbce938198132ca9cd2a5cb362816344687291f5b6d7cf6de8f2855e9414 @@ -498,7 +511,7 @@ entries: version: 0.8.4-beta.22 - apiVersion: v2 appVersion: 0.8.4-beta.21 - created: "2024-06-25T14:52:54.892368944Z" + created: "2024-07-14T12:48:16.35904211Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7dce153d2fcae7513e9c132e139b2721fd975ea3cc43a370e34dbeb2a1b7f683 @@ -510,7 +523,7 @@ entries: version: 0.8.4-beta.21 - apiVersion: v2 appVersion: 0.8.4-beta.20 - created: "2024-06-25T14:52:54.891969626Z" + created: "2024-07-14T12:48:16.35791944Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c51189a187bbf24135382e25cb00964e0330dfcd3b2f0c884581a6686f05dd28 @@ -522,7 +535,7 @@ entries: version: 0.8.4-beta.20 - apiVersion: v2 appVersion: 0.8.4-beta.19 - created: "2024-06-25T14:52:54.891018374Z" + created: "2024-07-14T12:48:16.356942108Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 8219575dedb42fa2ddbf2768a4e9afbfacbc2dff7e953d77c7b10a41b78dc687 @@ -534,7 +547,7 @@ entries: version: 0.8.4-beta.19 - apiVersion: v2 appVersion: 0.8.4-beta.18 - created: "2024-06-25T14:52:54.890618786Z" + created: "2024-07-14T12:48:16.35653782Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6418cde559cf12f1f7fea5a2b123bba950e50eeb3be002441827d2ab7f9e4ef7 @@ -546,7 +559,7 @@ entries: version: 0.8.4-beta.18 - apiVersion: v2 appVersion: 0.8.4-beta.16 - created: "2024-06-25T14:52:54.890227603Z" + created: "2024-07-14T12:48:16.356130817Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9c9840a7c9476dbb08e0ac83926330718fe50c89879752dd8f92712b036109c0 @@ -558,7 +571,7 @@ entries: version: 0.8.4-beta.16 - apiVersion: v2 appVersion: 0.8.4-beta.15 - created: "2024-06-25T14:52:54.889830279Z" + created: "2024-07-14T12:48:16.355727852Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0955fd22da028315e30c68132cbfa4bdc82bae622039bcfce0de339707bb82eb @@ -570,7 +583,7 @@ entries: version: 0.8.4-beta.15 - apiVersion: v2 appVersion: 0.8.4-beta.14 - created: "2024-06-25T14:52:54.88942517Z" + created: "2024-07-14T12:48:16.355327231Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 56208571956abe20ed7a5cc1867cab2667ed792c63e53d0e8bb70a9b438b7bf6 @@ -582,7 +595,7 @@ entries: version: 0.8.4-beta.14 - apiVersion: v2 appVersion: 0.8.4-beta.13 - created: "2024-06-25T14:52:54.889036452Z" + created: "2024-07-14T12:48:16.354975542Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: d7222c72412b6ee5833fbb07d2549be179cdfc7ccd89e0ad947d112fce799b83 @@ -594,7 +607,7 @@ entries: version: 0.8.4-beta.13 - apiVersion: v2 appVersion: 0.8.4-beta.12 - created: "2024-06-25T14:52:54.888678191Z" + created: "2024-07-14T12:48:16.354626367Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: af08c723756e397962b2d5190dedfd50797b771c5caf58b93a6f65d8fa24785c @@ -606,7 +619,7 @@ entries: version: 0.8.4-beta.12 - apiVersion: v2 appVersion: 0.8.4-beta.11 - created: "2024-06-25T14:52:54.888112171Z" + created: "2024-07-14T12:48:16.354267935Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a0235835ba57d185a83dd8a26281fa37b2077c3a37fe3a1c50585005695927e3 @@ -618,7 +631,7 @@ entries: version: 0.8.4-beta.11 - apiVersion: v2 appVersion: 0.8.4-beta.10 - created: "2024-06-25T14:52:54.88720381Z" + created: "2024-07-14T12:48:16.353886641Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 910ddfeba0c5e66651500dd11404afff092adc0f768ed68e0d93b04b83aa4388 @@ -630,7 +643,7 @@ entries: version: 0.8.4-beta.10 - apiVersion: v2 appVersion: 0.8.4-beta.9 - created: "2024-06-25T14:52:54.899577432Z" + created: "2024-07-14T12:48:16.366311125Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c25ca8a9f072d6a5d02232448deaef5668aca05f24dfffbba3ebe30a4f75bb26 @@ -642,7 +655,7 @@ entries: version: 0.8.4-beta.9 - apiVersion: v2 appVersion: 0.8.4-beta.8 - created: "2024-06-25T14:52:54.89925044Z" + created: "2024-07-14T12:48:16.365397803Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7249a39d4137e457b369384ba0a365c271c780d93a8327ce25083df763c39999 @@ -654,7 +667,7 @@ entries: version: 0.8.4-beta.8 - apiVersion: v2 appVersion: 0.8.4-beta.7 - created: "2024-06-25T14:52:54.898923167Z" + created: "2024-07-14T12:48:16.36505446Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ee750c7c8d6ea05bd447375e624fdd7f66dd87680ab81f7b7e73df7379a9024a @@ -666,7 +679,7 @@ entries: version: 0.8.4-beta.7 - apiVersion: v2 appVersion: 0.8.4-beta.6 - created: "2024-06-25T14:52:54.898597537Z" + created: "2024-07-14T12:48:16.364708601Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0e046be9f73df7444a995608c59af16fab9030b139b2acb4d6db6185b8eb5337 @@ -678,7 +691,7 @@ entries: version: 0.8.4-beta.6 - apiVersion: v2 appVersion: 0.8.4-beta.5 - created: "2024-06-25T14:52:54.898264563Z" + created: "2024-07-14T12:48:16.364373513Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b56e9a23d46810eccdb4cf5272cc05126da3f6db314e541959c3efb5f260620b @@ -690,7 +703,7 @@ entries: version: 0.8.4-beta.5 - apiVersion: v2 appVersion: 0.8.4-beta.4 - created: "2024-06-25T14:52:54.897896133Z" + created: "2024-07-14T12:48:16.364035099Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1d5808ecaf55391f3b27ae6236400066508acbd242e33db24a1ab4bffa77409e @@ -702,7 +715,7 @@ entries: version: 0.8.4-beta.4 - apiVersion: v2 appVersion: 0.8.4-beta.3 - created: "2024-06-25T14:52:54.896727544Z" + created: "2024-07-14T12:48:16.362874744Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b64efa8529d82be56c6ab60487ed24420a5614d96d2509c1f93c1003eda71a54 @@ -714,7 +727,7 @@ entries: version: 0.8.4-beta.3 - apiVersion: v2 appVersion: 0.8.4-beta.2 - created: "2024-06-25T14:52:54.891563686Z" + created: "2024-07-14T12:48:16.357497218Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -730,7 +743,7 @@ entries: version: 0.8.4-beta.2 - apiVersion: v2 appVersion: 0.8.4-beta.1 - created: "2024-06-25T14:52:54.886840739Z" + created: "2024-07-14T12:48:16.353530804Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -746,7 +759,7 @@ entries: version: 0.8.4-beta.1 - apiVersion: v2 appVersion: 0.8.3 - created: "2024-06-25T14:52:54.886301389Z" + created: "2024-07-14T12:48:16.352961928Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -762,7 +775,7 @@ entries: version: 0.8.3 - apiVersion: v2 appVersion: 0.8.3-beta.6 - created: "2024-06-25T14:52:54.88564517Z" + created: "2024-07-14T12:48:16.351935353Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -778,7 +791,7 @@ entries: version: 0.8.3-beta.6 - apiVersion: v2 appVersion: 0.8.3-beta.5 - created: "2024-06-25T14:52:54.885028145Z" + created: "2024-07-14T12:48:16.35102644Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -794,7 +807,7 @@ entries: version: 0.8.3-beta.5 - apiVersion: v2 appVersion: 0.8.3-beta.4 - created: "2024-06-25T14:52:54.884468206Z" + created: "2024-07-14T12:48:16.350416717Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -810,7 +823,7 @@ entries: version: 0.8.3-beta.4 - apiVersion: v2 appVersion: 0.8.3-beta.2 - created: "2024-06-25T14:52:54.883815253Z" + created: "2024-07-14T12:48:16.34971405Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -826,7 +839,7 @@ entries: version: 0.8.3-beta.2 - apiVersion: v2 appVersion: 0.8.3-beta.1 - created: "2024-06-25T14:52:54.883268449Z" + created: "2024-07-14T12:48:16.349167956Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -842,7 +855,7 @@ entries: version: 0.8.3-beta.1 - apiVersion: v2 appVersion: 0.8.2 - created: "2024-06-25T14:52:54.882705244Z" + created: "2024-07-14T12:48:16.348621793Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -858,7 +871,7 @@ entries: version: 0.8.2 - apiVersion: v2 appVersion: 0.8.2-beta.60 - created: "2024-06-25T14:52:54.881823299Z" + created: "2024-07-14T12:48:16.347982144Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -874,7 +887,7 @@ entries: version: 0.8.2-beta.60 - apiVersion: v2 appVersion: 0.8.2-beta.59 - created: "2024-06-25T14:52:54.880463332Z" + created: "2024-07-14T12:48:16.347337786Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -890,7 +903,7 @@ entries: version: 0.8.2-beta.59 - apiVersion: v2 appVersion: 0.8.2-beta.58 - created: "2024-06-25T14:52:54.879820297Z" + created: "2024-07-14T12:48:16.346676957Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -906,7 +919,7 @@ entries: version: 0.8.2-beta.58 - apiVersion: v2 appVersion: 0.8.2-beta.57 - created: "2024-06-25T14:52:54.87918108Z" + created: "2024-07-14T12:48:16.345610839Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -922,7 +935,7 @@ entries: version: 0.8.2-beta.57 - apiVersion: v2 appVersion: 0.8.2-beta.56 - created: "2024-06-25T14:52:54.878467744Z" + created: "2024-07-14T12:48:16.344597911Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -938,7 +951,7 @@ entries: version: 0.8.2-beta.56 - apiVersion: v2 appVersion: 0.8.2-beta.52 - created: "2024-06-25T14:52:54.877795425Z" + created: "2024-07-14T12:48:16.343958252Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -954,7 +967,7 @@ entries: version: 0.8.2-beta.52 - apiVersion: v2 appVersion: 0.8.2-beta.51 - created: "2024-06-25T14:52:54.877128356Z" + created: "2024-07-14T12:48:16.343310728Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -970,7 +983,7 @@ entries: version: 0.8.2-beta.51 - apiVersion: v2 appVersion: 0.8.2-beta.50 - created: "2024-06-25T14:52:54.876499117Z" + created: "2024-07-14T12:48:16.342658525Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -986,7 +999,7 @@ entries: version: 0.8.2-beta.50 - apiVersion: v2 appVersion: 0.8.2-beta.49 - created: "2024-06-25T14:52:54.87585986Z" + created: "2024-07-14T12:48:16.341907308Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1002,7 +1015,7 @@ entries: version: 0.8.2-beta.49 - apiVersion: v2 appVersion: 0.8.2-beta.48 - created: "2024-06-25T14:52:54.874640847Z" + created: "2024-07-14T12:48:16.341261868Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1018,7 +1031,7 @@ entries: version: 0.8.2-beta.48 - apiVersion: v2 appVersion: 0.8.2-beta.47 - created: "2024-06-25T14:52:54.873983756Z" + created: "2024-07-14T12:48:16.340597603Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1034,7 +1047,7 @@ entries: version: 0.8.2-beta.47 - apiVersion: v2 appVersion: 0.8.2-beta.46 - created: "2024-06-25T14:52:54.873429929Z" + created: "2024-07-14T12:48:16.340010513Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1050,7 +1063,7 @@ entries: version: 0.8.2-beta.46 - apiVersion: v2 appVersion: 0.8.2-beta.45 - created: "2024-06-25T14:52:54.87285366Z" + created: "2024-07-14T12:48:16.338776556Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1066,7 +1079,7 @@ entries: version: 0.8.2-beta.45 - apiVersion: v2 appVersion: 0.8.2-beta.44 - created: "2024-06-25T14:52:54.872314971Z" + created: "2024-07-14T12:48:16.338177133Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1082,7 +1095,7 @@ entries: version: 0.8.2-beta.44 - apiVersion: v2 appVersion: 0.8.2-beta.43 - created: "2024-06-25T14:52:54.871773206Z" + created: "2024-07-14T12:48:16.337596755Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1098,7 +1111,7 @@ entries: version: 0.8.2-beta.43 - apiVersion: v2 appVersion: 0.8.2-beta.41 - created: "2024-06-25T14:52:54.871123439Z" + created: "2024-07-14T12:48:16.336953048Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1114,7 +1127,7 @@ entries: version: 0.8.2-beta.41 - apiVersion: v2 appVersion: 0.8.2-beta.40 - created: "2024-06-25T14:52:54.870471407Z" + created: "2024-07-14T12:48:16.336306917Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1130,7 +1143,7 @@ entries: version: 0.8.2-beta.40 - apiVersion: v2 appVersion: 0.8.2-beta.39 - created: "2024-06-25T14:52:54.869913914Z" + created: "2024-07-14T12:48:16.335749462Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1146,7 +1159,7 @@ entries: version: 0.8.2-beta.39 - apiVersion: v2 appVersion: 0.8.2-beta.38 - created: "2024-06-25T14:52:54.869352352Z" + created: "2024-07-14T12:48:16.33517182Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1162,7 +1175,7 @@ entries: version: 0.8.2-beta.38 - apiVersion: v2 appVersion: 0.8.2-beta.37 - created: "2024-06-25T14:52:54.868708877Z" + created: "2024-07-14T12:48:16.334618462Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1178,7 +1191,7 @@ entries: version: 0.8.2-beta.37 - apiVersion: v2 appVersion: 0.8.1 - created: "2024-06-25T14:52:54.86743294Z" + created: "2024-07-14T12:48:16.333962593Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1192,4 +1205,4 @@ entries: urls: - https://openmined.github.io/PySyft/helm/syft-0.8.1.tgz version: 0.8.1 -generated: "2024-06-25T14:52:54.866566006Z" +generated: "2024-07-14T12:48:16.332623073Z" diff --git a/packages/grid/helm/repo/syft-0.8.7-beta.14.tgz b/packages/grid/helm/repo/syft-0.8.7-beta.14.tgz new file mode 100644 index 0000000000000000000000000000000000000000..da49fb5c01e49bcc14af09796b4f5850b32b3d8e GIT binary patch literal 19241 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 Q0RRC1|J_j*djPxv04ir6ivR!s literal 0 HcmV?d00001 diff --git a/packages/grid/helm/syft/Chart.yaml b/packages/grid/helm/syft/Chart.yaml index 6965335a744..7ebe62c3364 100644 --- a/packages/grid/helm/syft/Chart.yaml +++ b/packages/grid/helm/syft/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: syft description: Perform numpy-like analysis on data that remains in someone elses server type: application -version: "0.8.7-beta.13" -appVersion: "0.8.7-beta.13" +version: "0.8.7-beta.14" +appVersion: "0.8.7-beta.14" home: https://github.com/OpenMined/PySyft/ icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png diff --git a/packages/grid/helm/syft/templates/NOTES.txt b/packages/grid/helm/syft/templates/NOTES.txt index 2fc86bf30c6..f625e4e727a 100644 --- a/packages/grid/helm/syft/templates/NOTES.txt +++ b/packages/grid/helm/syft/templates/NOTES.txt @@ -10,345 +10,1193 @@ Following class versions are either added/removed. { + "PartialSyftObject": { + "2": { + "version": 2, + "hash": "a32dc097345cffb073caa322281fd8de5f89f0072e9244d093a8bf32ce260642", + "action": "add" + } + }, "ServerMetadata": { + "4": { + "version": 4, + "hash": "e5e0c2d926bf1fea0696126c9cd2ea5308c198f9412de1732a509082cb738e35", + "action": "add" + }, + "5": { + "version": 5, + "hash": "13bfe668b20779b2ab04227dc6b92d545b9ea83baaf0002cad5bcc450f34d246", + "action": "add" + } + }, + "StoreConfig": { + "2": { + "version": 2, + "hash": "af833ac27e16cd3dd93061e4870847df37e480893d867966a0ae8dcca57b9abb", + "action": "add" + } + }, + "MongoDict": { + "2": { + "version": 2, + "hash": "2ab3c12b81326108badd66307d4c4fefb1d60e76d5be2c67e70bb607b4992e93", + "action": "add" + } + }, + "MongoStoreConfig": { + "2": { + "version": 2, + "hash": "89f75ccf2d640d2dc47aa68bdbd766e4b83433a98653ade174724a631f47fd4d", + "action": "add" + } + }, + "LinkedObject": { + "2": { + "version": 2, + "hash": "d9c00f99c5385cbcdd11173dfd30b532ddcbc4e8c37f6121a01061cf71b91b5e", + "action": "add" + } + }, + "BaseConfig": { + "2": { + "version": 2, + "hash": "09bb3e3ba91f6c2604d4a057a7be48afa8fb4720b683ac4019569323900acdc9", + "action": "add" + } + }, + "ServiceConfig": { + "2": { + "version": 2, + "hash": "df15d8e09dedcbee2e07292ad71a8fd42cf0d52ac4ffdaaa27ef87b7f2629a8a", + "action": "add" + } + }, + "LibConfig": { + "2": { + "version": 2, + "hash": "6453cb794e0a89c8a0f4529d2f81e4f04b141a0d313760c38f41f2dd42258941", + "action": "add" + } + }, + "APIEndpoint": { + "2": { + "version": 2, + "hash": "695974643dbc32a1a653218a9b2fedfdd341bdd687584cf80035bb51e7ed9be1", + "action": "add" + } + }, + "LibEndpoint": { + "2": { + "version": 2, + "hash": "acc9924f09471081899ed21d2d4da3e4ed307edd5e703ee0041a41827e26ccde", + "action": "add" + } + }, + "SignedSyftAPICall": { + "2": { + "version": 2, + "hash": "4dfc0709ab211d55250d2be8f6ec60be1f9517d98a73c98d2a360d92e49822ff", + "action": "add" + } + }, + "SyftAPICall": { + "2": { + "version": 2, + "hash": "b457a48a7f0ddc67525d91faf660667adcb80f7a478999a35396a2e4bc22c562", + "action": "add" + } + }, + "SyftAPIData": { + "2": { + "version": 2, + "hash": "46b073b98cfb3a4a0f5dc6c55885278f263bc208d3704821849568e246101aa8", + "action": "add" + } + }, + "SyftAPI": { + "2": { + "version": 2, + "hash": "03ec5999de8f43ce83da079d836aec737d1142ec11265c0f3ca89da3139fad36", + "action": "add" + }, + "3": { + "version": 3, + "hash": "b82f04c734e7cc3a14bf5cf88173e2ed41a09ddd332b0b4a79747c333ca8db1e", + "action": "add" + } + }, + "User": { + "3": { + "version": 3, + "hash": "cdd25c47e32ac79e177bd26b8d3231847f4722247543954fc967686159ac17a2", + "action": "add" + } + }, + "UserUpdate": { + "3": { + "version": 3, + "hash": "01c3a470b326229bc892bea96b425c059edfde3bca57b0af83491a4fecbd0402", + "action": "add" + } + }, + "UserCreate": { + "3": { + "version": 3, + "hash": "cb2d9872cba80c960c748b232547556fa69901c108d84ab46f177cb47f0dd3fc", + "action": "add" + } + }, + "UserSearch": { + "2": { + "version": 2, + "hash": "c2676b012142f68ae64a11f3807e35430a046f51b7cac6682aa453c0345a9a32", + "action": "add" + } + }, + "UserView": { + "3": { + "version": 3, + "hash": "a07bebf2362391b915fb2554e61c98e35cb4f945ba8c3c3299dd059dc6f0e137", + "action": "add" + } + }, + "UserViewPage": { + "2": { + "version": 2, + "hash": "9ccdbff62daac91fc9951a62c7d54d35418035a0ad4fd979bd1f7262c2cdabc9", + "action": "add" + } + }, + "UserPrivateKey": { + "2": { + "version": 2, + "hash": "3e7a37177e86a5a0c54a6e6cc87eb2c3a266e5e65cb8dd33f6b0c3fccc7b584d", + "action": "add" + } + }, + "DateTime": { + "2": { + "version": 2, + "hash": "298922f94fc06eb8ce080cd19bc124929943729ea83bf15b463b37fe959141cb", + "action": "add" + } + }, + "ReplyNotification": { + "2": { + "version": 2, + "hash": "0420ed6a014e3a16bcf063208cfdc393a02f4ec0ddbd0635dc15308b5deafc92", + "action": "add" + } + }, + "Notification": { + "2": { + "version": 2, + "hash": "38defc169bf225474e0b8037aedf66dee78f5e0aef3af75ab24d1e8f5d55f23a", + "action": "add" + } + }, + "CreateNotification": { + "2": { + "version": 2, + "hash": "079523cd89527b90003bef1ab4f985e374550bfb1f7921f8906702a9f6938205", + "action": "add" + } + }, + "NotificationPreferences": { + "1": { + "version": 1, + "hash": "499e02b45defab561decaef6bdcf0ec1a6bbda834bd7d25a465982159b8c2909", + "action": "add" + } + }, + "NotifierSettings": { + "1": { + "version": 1, + "hash": "8edcbf73f2098f6a20d393f09c5805493da5346e8f7070f841c36ac7b777edb1", + "action": "add" + } + }, + "SyftImageRegistry": { + "2": { + "version": 2, + "hash": "2495c6836c6f0ba991637766657ccd04e992d367102d336a04c608d95cbf9895", + "action": "add" + } + }, + "SyftWorkerImage": { + "2": { + "version": 2, + "hash": "dcd40e107f930c0efcd525694e89eedea1546fdc31d44373fce7e9d4ac2bbc2e", + "action": "add" + } + }, + "SyftWorker": { + "2": { + "version": 2, + "hash": "6dbf5487cfb6fceea8a57d1cbb1320107f4a4116fb0269f151082e15f9d150b5", + "action": "add" + }, + "3": { + "version": 3, + "hash": "905b97e80b2a9d509a5d37ae248ed6ddc1e028e851330c836ee5ce26444fac88", + "action": "add" + } + }, + "WorkerPool": { + "2": { + "version": 2, + "hash": "d2205590c821af416ba8f13f3e2b834fa3bb561f08dca060eb2bd86f7eca89e2", + "action": "add" + } + }, + "MarkdownDescription": { + "2": { + "version": 2, + "hash": "d8f5ec42e69d55eabe044a417bfbf6d57b867eadcc975377e1fc8a499a9f90f3", + "action": "add" + } + }, + "HTMLObject": { + "1": { + "version": 1, + "hash": "4127056b8f9f904f2dcb225de2952ad7b57c4b2874ac76800afa234c826d6702", + "action": "add" + } + }, + "ServerSettingsUpdate": { + "4": { + "version": 4, + "hash": "09b96c7c25e9261144ffe3409ac47e943abe5cf433759f68c03a321d21d69c1b", + "action": "add" + }, + "5": { + "version": 5, + "hash": "81a9e2930fe91f7744a5a495f73eb9f7c04145ebe1848257ea52b537fed4b3d7", + "action": "add" + } + }, + "ServerSettings": { + "3": { + "version": 3, + "hash": "6b2240b92099684b0e431d27c0be2a22daad234b890c95eb607f0cc9e73c9f0d", + "action": "add" + }, "5": { "version": 5, - "hash": "70197b4725dbdea0560ed8388e4d20b76808bee988f3630c5f916ee8f48761f8", + "hash": "522690efe97c50dff81936640e95207861406e480d7e1d87587e558dbd7a506c", + "action": "add" + }, + "6": { + "version": 6, + "hash": "be6d6402a5ccf0b93847ebcde75f4ea357f3b45003a1a7c01426e9e34ea3b5e1", + "action": "add" + } + }, + "HTTPConnection": { + "3": { + "version": 3, + "hash": "2e567111a679e9f01b84eafc96d5e14e52b12fea991957e547f2edcbc0ede34c", + "action": "add" + } + }, + "PythonConnection": { + "3": { + "version": 3, + "hash": "854a2ffc94e21fdcc4878ddc16f60bef8e7bf8ddc72dec63c9cb182ad7e4bbb7", + "action": "add" + } + }, + "ActionDataEmpty": { + "2": { + "version": 2, + "hash": "76445c74c9636f33524ed1ec60796caabfda2dcf85a950387ee9526b2659efe4", + "action": "add" + } + }, + "ObjectNotReady": { + "2": { + "version": 2, + "hash": "09e8e20e1f96189b96ddda19d1cffafed98dfa8fd80b286ea91b814c7aa0aa5b", + "action": "add" + } + }, + "ActionDataLink": { + "2": { + "version": 2, + "hash": "45f82b2a0124f7adadc515c40f71551a37ea4b04fdc2caa220e39988e8d83675", + "action": "add" + } + }, + "Action": { + "3": { + "version": 3, + "hash": "9baeef92e1199d9686ad27bcaf55ad0621233560dd70377fc964ccc4ab21bcb4", + "action": "add" + } + }, + "ActionObject": { + "3": { + "version": 3, + "hash": "e13cca90723c27b17529295e1050ba4736aa42e548511f922ab4d10a78e9c558", + "action": "add" + }, + "4": { + "version": 4, + "hash": "da069dc83b2c583d5624f86541ed95d9c8a85774a1fb64e37fdd87e490e06300", + "action": "add" + } + }, + "AnyActionObject": { + "3": { + "version": 3, + "hash": "8b6a450bbc40f381cb3404ea6ff86024651debcdebe785db0819ab1ffd6535b0", + "action": "add" + }, + "4": { + "version": 4, + "hash": "a944e6db84aa6cda0d4cb278cc836df1ce64882896a9d3da798148e1e9bb5c42", + "action": "add" + } + }, + "BlobFile": { + "4": { + "version": 4, + "hash": "6d59e20f3a9bf16cf199deddb0d246b100d5ab616a4811e96b682df58546b869", + "action": "add" + } + }, + "BlobFileOBject": { + "2": { + "version": 2, + "hash": "af3c2e435c20258b94377716fb6babb0bfb8ea684c88a93aff968f95fb1497f6", + "action": "add" + }, + "3": { + "version": 3, + "hash": "417f4eb6f978a273c3b7cad93fc80caab122bebdf21923520dbfcadcc5160baf", + "action": "add" + } + }, + "SecureFilePathLocation": { + "2": { + "version": 2, + "hash": "1680c4c2f81f3e93fe126c5888288577b32e76546f16be3ffe5c3fdcce1aac3f", + "action": "add" + } + }, + "SeaweedSecureFilePathLocation": { + "3": { + "version": 3, + "hash": "0d34e64267f3c870a5ce5307802a23fcfbb796cf48b979c2d1d4c0ef772f8131", + "action": "add" + } + }, + "AzureSecureFilePathLocation": { + "2": { + "version": 2, + "hash": "a97c52808be5afceaea7f9b3ac6c00d4256d7f9a8c7f2200acf8f82451018319", + "action": "add" + } + }, + "BlobStorageEntry": { + "3": { + "version": 3, + "hash": "6ff74feabd8a58ae0e1881c03f3ffbb70c95944bef507f8c5b1493bfb6594ea5", + "action": "add" + } + }, + "BlobStorageMetadata": { + "3": { + "version": 3, + "hash": "738daa84b6824841254ba7a651a433dd0ff1c44961ed142920786cbc60329ffa", + "action": "add" + } + }, + "CreateBlobStorageEntry": { + "2": { + "version": 2, + "hash": "9c0069727e5b845a004717dc28abcf1486f5581cba4ec0526fdb3553d40ecd7a", + "action": "add" + } + }, + "BlobRetrieval": { + "3": { + "version": 3, + "hash": "3b7be2fa9b5821c03808ae2dd244feb04817f5b1f1f821cd861f111fdc8692f9", + "action": "add" + } + }, + "SyftObjectRetrieval": { + "4": { + "version": 4, + "hash": "4d6a3175fd8753919ceed4d7b19a6a25baa47013da8f9d2e4eae3afd2c72f246", + "action": "add" + } + }, + "BlobRetrievalByURL": { + "4": { + "version": 4, + "hash": "6a77259a8c83f85e83e89cee4c7ea7b1d57ccac4f70ecfb86b6c5db21c62ee79", + "action": "add" + }, + "5": { + "version": 5, + "hash": "e9c5e16f14e5bd45209f44ebf6c758a8c4a315b2d335a33bc529606506037890", + "action": "add" + } + }, + "BlobDeposit": { + "2": { + "version": 2, + "hash": "cf27595f05e3f60c825ef3b547ab72f04cc983688b12ef9233785b05b5a24551", + "action": "add" + } + }, + "WorkerSettings": { + "3": { + "version": 3, + "hash": "982d68aca23fdecd9d8986f6ac95a2812ddac784c5a30655367df5356c9778f1", + "action": "add" + } + }, + "HTTPServerRoute": { + "3": { + "version": 3, + "hash": "530fec14b476cf67afeef8667fd5397a2bca51744869e41828f4328bed647f72", + "action": "add" + } + }, + "PythonServerRoute": { + "3": { + "version": 3, + "hash": "f9f52b5764f2a5c3bd2b628f793e2ab9d0e5163f0bf4a469d4b3ee804ee27eeb", + "action": "add" + } + }, + "VeilidServerRoute": { + "1": { + "version": 1, + "hash": "0924cb1d76957bdc7f39ccb54e2944ce07bc83c0bf37ccf5f89d7328c0088eeb", + "action": "add" + } + }, + "EnclaveMetadata": { + "3": { + "version": 3, + "hash": "94998d8fad3c2ca1f371a08641873e24504065bfe785548aba72dfaf9687c409", + "action": "add" + } + }, + "CustomEndpointActionObject": { + "1": { + "version": 1, + "hash": "aba8c35a83b81f602ae19393e9bd1813ca1d191d055272499c63543961089b86", + "action": "add" + } + }, + "DataSubject": { + "2": { + "version": 2, + "hash": "24329941dbb93f9382527b9b2e70da58369aefa65ae6934a4f55725487259515", + "action": "add" + } + }, + "DataSubjectCreate": { + "2": { + "version": 2, + "hash": "1584dc6cbd2df80118d46aa9cf4788c96be420ce3a1d3ff041664fb265626871", + "action": "add" + } + }, + "DataSubjectMemberRelationship": { + "2": { + "version": 2, + "hash": "26876c004bb080c06af331965466e66d454ccb6b6a03d12aec0d44032302412b", + "action": "add" + } + }, + "Contributor": { + "2": { + "version": 2, + "hash": "281a88bcfd8840b3f92780d31075bfa369b2ff0e5d4044ebbc269bebca451b47", + "action": "add" + } + }, + "Asset": { + "2": { + "version": 2, + "hash": "84f33e07c0a4a627808ada7ae092b9e11305a2a6a9d4f264f62ed906a834663d", + "action": "add" + } + }, + "CreateAsset": { + "2": { + "version": 2, + "hash": "0fbe735bdf6acd91f5589369188c02d25d014b7112afbcde8b04d52aca2abb65", + "action": "add" + } + }, + "Dataset": { + "2": { + "version": 2, + "hash": "e9df341cf5128d9ce09fb137e6413745842818675c9dfbbf824e521cb0196dd0", + "action": "add" + }, + "3": { + "version": 3, + "hash": "acc25456a60ccef861de65eea1feef612ef9fa1ed6e986b466450c4adf73906b", + "action": "add" + } + }, + "DatasetPageView": { + "2": { + "version": 2, + "hash": "0e336a3afd446aa58fc6ec6950691baa36b76a0649b9da31bbecb4db1b0587cf", + "action": "add" + } + }, + "CreateDataset": { + "2": { + "version": 2, + "hash": "3e4983b35c6513a64198cf5346aec23017192045aad562e85deb7e212be78784", + "action": "add" + }, + "3": { + "version": 3, + "hash": "7ecb8d62a8c12e385ff45ed700106bb1463926237fbdde3e84a83f38419d54de", + "action": "add" + } + }, + "SyftLog": { + "3": { + "version": 3, + "hash": "c2ee3f4c34dc7af3af533865dc07384403fb757e7959272c9d6d08110623a216", + "action": "add" + }, + "4": { + "version": 4, + "hash": "3b90dcb66359a1d03345291b47dcb8b5c166b1e0344dbe84d9c1f3a8e57f99eb", + "action": "add" + } + }, + "JobItem": { + "4": { + "version": 4, + "hash": "3e2eaae1b2c367b5bc52cbc4eb3390b1f5a6a6f8cae69523bbfc8e071c314bf8", + "action": "add" + }, + "6": { + "version": 6, + "hash": "b633f770c9c47a849b75fe6b93c573c94eadab23c689aa812a8671cec9543650", + "action": "add" + } + }, + "ExecutionOutput": { + "1": { + "version": 1, + "hash": "c6cb71d6ae689e71c31685c29a7ecd44d1c0c5b31fd19991b535cb597db7b44a", + "action": "add" + }, + "2": { + "version": 2, + "hash": "1b045334d8049f3970e655da11f3f62bc8a9f78e562fd75ed517c97fc95bb1c3", + "action": "add" + } + }, + "TwinObject": { + "2": { + "version": 2, + "hash": "c1f81d875b96cec303af7d869e5a70f7b619f0f4849ad6a8987e75cf6e2f4538", + "action": "add" + } + }, + "PolicyRule": { + "1": { + "version": 1, + "hash": "b92557f8bd715caadb4eba68793f167493d36f29972006c2bd59b0ec8e829ba7", + "action": "add" + } + }, + "CreatePolicyRule": { + "1": { + "version": 1, + "hash": "2962b14b70451ea8e13746ebadff62d927f62111d3d5610787ecb3b9cefcc897", + "action": "add" + } + }, + "CreatePolicyRuleConstant": { + "1": { + "version": 1, + "hash": "3807c5bf87bd1a58ecae8a97083e636f0471d4604121fb1f61182bd7dbbc1c47", + "action": "add" + } + }, + "Matches": { + "1": { + "version": 1, + "hash": "20dd67c0d60cd0047267dc83a767568d90fc418e84a05186eaba6f6a0279c50b", + "action": "add" + } + }, + "PreFill": { + "1": { + "version": 1, + "hash": "557185e0437884ea9da718b449d0c6b38bc6c107e29d5f36ab6e34b8509a884d", + "action": "add" + } + }, + "UserOwned": { + "1": { + "version": 1, + "hash": "50de8777b4027f394d910f5304d3d27c48cc58abdd9882c0e1cddc10b69f85c5", + "action": "add" + } + }, + "MixedInputPolicy": { + "1": { + "version": 1, + "hash": "b4d6b42c04a8b64a1ec065e700af67347c44a180cdfdb8f4e9b3bc030cf3bfe4", + "action": "add" + } + }, + "ExactMatch": { + "2": { + "version": 2, + "hash": "7fcc80c7ec005a0e1484b9d44fe9892ad886fda82044a9a96b0c33fbffc63d4f", + "action": "add" + } + }, + "OutputHistory": { + "2": { + "version": 2, + "hash": "e9844cc602cb57168e3062263961ad5d22a1e93a5bb3765ee364637813c9daca", + "action": "add" + } + }, + "OutputPolicyExecuteCount": { + "2": { + "version": 2, + "hash": "82a309e0616864a3505600a88fcfb772c2d5f781e286a285953e495f93a2b3e2", + "action": "add" + } + }, + "OutputPolicyExecuteOnce": { + "2": { + "version": 2, + "hash": "0b0baa12dd349997fb67887005c5c76f559d02d1a5570700af31d17a39016e72", + "action": "add" + } + }, + "EmptyInputPolicy": { + "2": { + "version": 2, + "hash": "f1724dfc2f8f1f33db2a9c9f0a18bed8c763539592e8cbadd586df7af90b66fe", + "action": "add" + } + }, + "UserPolicy": { + "2": { + "version": 2, + "hash": "4b2396d083ad1200f66f83610a16c98fcf2fe9cbe918dfe1f2a893d3b700b6eb", + "action": "add" + } + }, + "SubmitUserPolicy": { + "2": { + "version": 2, + "hash": "91594efc92f7d6115c148930f02f90a06728fb8e1ed567c2c03cdae1967b62e3", + "action": "add" + } + }, + "UserCodeStatusCollection": { + "1": { + "version": 1, + "hash": "96bea86ece8bd4cb2948deba4fbdc1aa95a54b6f5ef03dbf8c805f1b3cc36db1", + "action": "add" + } + }, + "UserCode": { + "4": { + "version": 4, + "hash": "60ee9415e8692ad6c0fe9e5e65961d3b7e4247fbc765abcd871f612f546155f9", + "action": "add" + }, + "5": { + "version": 5, + "hash": "c3845ff8d7e006525f208dc19f93e0f0757a15b63b3e3664fabfa789dbe5fd2e", + "action": "add" + } + }, + "SubmitUserCode": { + "4": { + "version": 4, + "hash": "330b62d200c304e12b47e5b288fe7f419dcdb22f0aad2e31aa978a0a5993dbcb", + "action": "add" + }, + "5": { + "version": 5, + "hash": "ca0d501801f3aac1ad53f1e7844520dc7733c64f3fa012abb9fd95940c170d6e", + "action": "add" + } + }, + "UserCodeExecutionResult": { + "2": { + "version": 2, + "hash": "72aed37d1b165f36aeeba41e13c9ac570b17b35ced11a53b70d289e95d5d0c5e", "action": "add" } }, - "SyftAPI": { + "UserCodeExecutionOutput": { + "1": { + "version": 1, + "hash": "d180eb86a0baa95c0df100beda459586793af07259e21c1a559bcf961661cffd", + "action": "add" + } + }, + "CodeHistory": { + "2": { + "version": 2, + "hash": "7740375395772ee76a693b592f8ca72b954b75478d9b77eb38a2efbd0e3f53cb", + "action": "add" + }, "3": { "version": 3, - "hash": "b1b9d131a4f204ef2d56dc91bab3b945d5581080565232ede864f32015c0882a", + "hash": "7bede78c55f99d0e0294b0555ab2bace37f78fc5f58f423bba485b88ae190dc3", "action": "add" } }, - "HTMLObject": { - "1": { - "version": 1, - "hash": "010d9aaca95f3fdfc8d1f97d01c1bd66483da774a59275b310c08d6912f7f863", + "CodeHistoryView": { + "2": { + "version": 2, + "hash": "c289d9a50f718966d7edb647025c1bcfb71b38e11f4d0d2a18d24c6a7b6d9bbf", "action": "add" } }, - "ServerSettingsUpdate": { + "CodeHistoriesDict": { + "2": { + "version": 2, + "hash": "25f10dd11e5d360760b253ca76a38a1399cbbb6a209dad884bebff563acf0d58", + "action": "add" + } + }, + "UsersCodeHistoriesDict": { + "2": { + "version": 2, + "hash": "5c5840b39300d5540c8dbeab673dc925e8187d8589f36a84063af822437ebe88", + "action": "add" + } + }, + "OnDiskBlobDeposit": { + "2": { + "version": 2, + "hash": "83d6ec5c1c0c67627ad117b287201a75d9d91eb043921992bc761cf08b9526f0", + "action": "add" + } + }, + "RemoteConfig": { + "2": { + "version": 2, + "hash": "9ec87d036c109dd408ed2ab8042a735f0150358799c4acc8af582148605373fc", + "action": "add" + } + }, + "AzureRemoteConfig": { + "2": { + "version": 2, + "hash": "4f5f6f4d0b52788c2ae484c5da6346f1c8b25ae064d865da69e6dffb32275852", + "action": "add" + } + }, + "SeaweedFSBlobDeposit": { + "4": { + "version": 4, + "hash": "d5c268e0ccbb00149319679b95eb43134ae80ae43814d7f991732530c79399a1", + "action": "add" + } + }, + "DictStoreConfig": { "2": { "version": 2, - "hash": "e1dc9d2f30c4aae1f7359eb3fd44de5537788cd3c69be5f30c36fb019f07c261", - "action": "remove" + "hash": "4f7084ac3353fb7c16b010b654150096c08de108fbdaf6e8837654aa38a32466", + "action": "add" + } + }, + "NumpyArrayObject": { + "3": { + "version": 3, + "hash": "9e43f7bea261b729e7f6fa523ed050ba148fc1caf973ac996f9501af61b6ae8a", + "action": "add" }, "4": { "version": 4, - "hash": "ec783a7cd097e2bc4273a519d11023c796aebb9e3710c1d8332c0e46966d4ae0", + "hash": "939a577d5929ac8a9c421b1d07acba1c33db63143e6614d533624e4548bf614b", + "action": "add" + } + }, + "NumpyScalarObject": { + "3": { + "version": 3, + "hash": "5f6698e55cfb7105e279e9c28a3c30e759db143d2aa673abef448b78a2a39f69", "action": "add" }, - "5": { - "version": 5, - "hash": "fd89638bb3d6dda9095905aab7ed2883f0b3dd5245900e8e141eec87921c2c9e", + "4": { + "version": 4, + "hash": "5a4e86b712a242037958a3af68d2ab276dc7438db9b9551797323f051ca1a98a", "action": "add" } }, - "ServerSettings": { + "NumpyBoolObject": { "3": { "version": 3, - "hash": "2d5f6e79f074f75b5cfc2357eac7cf635b8f083421009a513240b4dbbd5a0fc1", - "action": "remove" + "hash": "3c8db86e9ea1b6c1ee457610b05831c242fb0d375fcc8176bb64f9ae08a5eb00", + "action": "add" }, - "5": { - "version": 5, - "hash": "cde18eb23fdffcfba47bc0e85efdbba1d59f1f5d6baa9c9690e1af14b35eb74e", + "4": { + "version": 4, + "hash": "b783d03c5d1fe9c4c8d346e2902c1e4ac7faac563c145ee4388c9c2c960963e2", + "action": "add" + } + }, + "PandasDataframeObject": { + "3": { + "version": 3, + "hash": "a130e7c5f88b4dbbef3030dd5b6b4bf7db3b4f60585f68b920bc250cee46022e", "action": "add" }, - "6": { - "version": 6, - "hash": "986d201418035e59b12787dfaf60aa2af17817c1894ce42ab4b982ed73127403", + "4": { + "version": 4, + "hash": "8b9a0b2c6652c60381c818d327d109404c735e62ad4e827fcd9042ec86325422", "action": "add" } }, - "BlobRetrievalByURL": { - "5": { - "version": 5, - "hash": "4934bf72bb10ac0a670c87ab735175088274e090819436563543473e64cf15e3", + "PandasSeriesObject": { + "3": { + "version": 3, + "hash": "c36e22ffea7633813ac0d53fd2075de0606abe240acd72d206830c424f62bbc8", + "action": "add" + }, + "4": { + "version": 4, + "hash": "3286a2085b84d6499c97df36a78eca1a0d701e265a43f733cdf5e20ac78ab32d", "action": "add" } }, - "EnclaveMetadata": { + "Change": { + "2": { + "version": 2, + "hash": "26073bb329dd19c65714ed0e2eb5a53aa4454adc02d7f1a22d6f4890149babcf", + "action": "add" + } + }, + "ChangeStatus": { + "2": { + "version": 2, + "hash": "260b340ed0b44c82a17e0d5662914a0cbf5ca02e62e36be2cc5e0dba0fc7ef01", + "action": "add" + } + }, + "ActionStoreChange": { + "2": { + "version": 2, + "hash": "98ae17d2677c72d5820ea6824a4f5fa1a5441fa4064d0fef9f6597056dfbcfcd", + "action": "add" + } + }, + "CreateCustomImageChange": { "2": { "version": 2, - "hash": "6dcc26695abc6a9ecd9d7d1e6507a9f1a92cc5ccd10987e92419bf984245f9a1", - "action": "remove" + "hash": "4b4c9312ab44c7b7c1c68ba9548da80e2454f6b8ea99f7652e546c635fd7f37b", + "action": "add" }, "3": { "version": 3, - "hash": "d2f23411927c68e2307a84d180ad053b3e4ba12d74aba64d34dac224c90e815d", + "hash": "c6c74ecacd2be69c6d494e25c6ccc5df92f28a26273316424aa9daf0936d00d6", "action": "add" } }, - "CustomEndpointActionObject": { - "1": { - "version": 1, - "hash": "642facc6cafbaad4de030a33cd619bd68ac31a32b0db07ddc1c1d5d7f914503e", + "CreateCustomWorkerPoolChange": { + "2": { + "version": 2, + "hash": "cafeea65a74c11caf6dae2ebe47175d6d0947e35ca7b832240513eaab3fd63d8", + "action": "add" + }, + "3": { + "version": 3, + "hash": "3a96efb85ffaba05479c16963de853e7d4a77bd36db5341dbcb9426fb28fee7e", "action": "add" } }, - "JobItem": { - "4": { - "version": 4, - "hash": "6a7cc7c2bb4dd234c1508b0af4d3b403cd3b7b427578a775bf80dc36891923ed", - "action": "remove" + "Request": { + "2": { + "version": 2, + "hash": "fad2e98b71d28b0039a631af4714858c495559ccbc93ccc2b1beed463f6d9452", + "action": "add" }, - "6": { - "version": 6, - "hash": "865a2ed791b8abd20d76e9a6bfae7ae7dad51b5ebfd8ff728aab25af93fa5570", + "3": { + "version": 3, + "hash": "25602e25c595d36f3755a8e8e16fc94ce9e832af36e8670f88406a0b180fcc51", "action": "add" } }, - "ExecutionOutput": { - "1": { - "version": 1, - "hash": "c2337099eba14767ead75fcc1b1fa265c1898461ede0b5e7758a0e8d11d1757d", - "action": "remove" - }, + "RequestInfo": { "2": { "version": 2, - "hash": "854fe9df5bcbb5c7e5b7c467bac423cd98c32f93d6876fea7b8eb6c08f6596da", + "hash": "65d41c5f3bc80202993c2167d42c030217956bd7932b92179f20016f47ab00b1", "action": "add" } }, - "CreateCustomImageChange": { + "RequestInfoFilter": { + "2": { + "version": 2, + "hash": "dea1b2af70f35864698027ca79eac4e1a23f03eb2faa26109259353a92afa960", + "action": "add" + } + }, + "SubmitRequest": { + "2": { + "version": 2, + "hash": "76819df6cbf6288428a1fe523e88f53fdd6e7399ba8196140b96bcd891e67517", + "action": "add" + } + }, + "ObjectMutation": { + "2": { + "version": 2, + "hash": "215cd56d33a58c8f5f725ad5ff32f62aa0b11330328ea952dc4df040983babbd", + "action": "add" + } + }, + "EnumMutation": { + "2": { + "version": 2, + "hash": "9c3b684b8a0c165eee84a58fb0955b85c3f8c34d7bd34a31dd07a7e24ef82be2", + "action": "add" + } + }, + "UserCodeStatusChange": { + "3": { + "version": 3, + "hash": "f9243a74da84b4e5a8ea63bc73a027e385e8e0e90658cac161d9c35bbfbb981d", + "action": "add" + } + }, + "SyncedUserCodeStatusChange": { "3": { "version": 3, - "hash": "e5f099940a7623f145f51f3e15b97a910a1d7fda1f67739420fed3035d1f2995", + "hash": "133db7a12c8b883d8c7ce73a7c5b79e93400c7baeacbe9a32bd42c8188ed5252", "action": "add" } }, "TwinAPIContextView": { "1": { "version": 1, - "hash": "7d368102d0b473009af3b8c46e0ea6d35893c5ebb172b373ad7d52553c12c9fa", + "hash": "1a2836ba7832013912a649c4d73ed85ef5e3323af8f75f7d1bc9e7db4c483a60", "action": "add" } }, "CustomAPIView": { "1": { "version": 1, - "hash": "0b9afdd554f0b353c07256e2522342be1302b395d649f1cbabc555e5baecb150", + "hash": "4defa7437482a8499ffeb84705f74dd24ca44e03379040d7324c8f2eaeb9fe82", "action": "add" } }, "CustomApiEndpoint": { "1": { "version": 1, - "hash": "13617f3dce60fa692421e0d9deda7ffd365ec02d4a062c18510b48457b6eba02", + "hash": "1651e640f1b9fb3e39d86336ce7bbcd6539fb44344382d02342474b2f01e2464", "action": "add" } }, "PrivateAPIEndpoint": { "1": { "version": 1, - "hash": "004ec19753263440e2896b4e35d7a6305322934512f473f37d54043af5726fe6", + "hash": "c703dfc895ad585d15b2b79b7641555dbacaad80016842dc1c10fa46297a2691", "action": "add" } }, "PublicAPIEndpoint": { "1": { "version": 1, - "hash": "5589b6bdd045ee9c45987dae78fd5a1124530a6c493e2328b304d9273b75177f", + "hash": "3586329beedf63913954d811d46bda3fcf8f1f25669f27b0c35e624a4cdf1370", "action": "add" } }, "UpdateTwinAPIEndpoint": { "1": { "version": 1, - "hash": "6d8effd404f15d4378b1ff3382e0622b9e5a637d9db342d43cfec00fe29c649a", + "hash": "92aeddf7a8cb90a542c600c0daeca0c236888cadcc5274ec81ea99516fe3199b", "action": "add" } }, "CreateTwinAPIEndpoint": { "1": { "version": 1, - "hash": "55e0a7b0ac428a6abb771ffcb925ee79cdd752a4b83058aa4b71fbef2a9fee63", + "hash": "5efa208b4003c5e6580a567dd1677bb298e9a08c3c5c8e4291e3c68b9a5865f2", "action": "add" } }, "TwinAPIEndpoint": { "1": { "version": 1, - "hash": "e538734d20be3b477e188eb91f66600c2e654bb32e34806ef24329e48238bf18", - "action": "add" - } - }, - "SyftLog": { - "3": { - "version": 3, - "hash": "8964d48238672e0e5d5db6b932cda4ee8eb77581949ab3f7a38a05b1efec13b7", - "action": "remove" - }, - "4": { - "version": 4, - "hash": "ad6ef18ccd87fced669f3824d27ab423aaf52574b0cd4f720687aeaba77524e5", + "hash": "ca4925c40e21464f49ecb0b9c2067328a7fa95242be91ca02f705b7b2230fa6e", "action": "add" } }, "SyncState": { - "1": { - "version": 1, - "hash": "a0616775ec8ef0629e2d91e0df9cc4237ea3674727eda1ce367f1897ee35767d", - "action": "remove" - }, "2": { "version": 2, - "hash": "925f1b8ccd4b9d542700a111f9c4bdd28bfa55978d805ddb2fb3c108cc940d19", + "hash": "22b70f9e51f667204ab4653cef18363831d50175e8962b62ac830b1f11ee1857", "action": "add" }, "3": { "version": 3, - "hash": "1b5fd28919cb496f8073a64a57736d477ace1ed969962b1b049cecf766f2661c", + "hash": "a06fb5e7826b4a33bc738280b661a2384fd4d4757551945b9302d01a1abaff85", "action": "add" } }, "ServerPeer": { + "2": { + "version": 2, + "hash": "daf8c5226dfa253ad13719aed78625c9d982b17a8927ffb818ab7cb56c255153", + "action": "add" + }, "3": { "version": 3, - "hash": "ec0e39fc77ddb542558519d6a1f7c55f41cc037b6312792333792a04feea57e6", + "hash": "eee060523d89db3abc29fd6e6997f9a8210d221923f768e4a672521e8fb1fb31", "action": "add" } }, - "AssociationRequestChange": { + "ServerPeerUpdate": { "1": { "version": 1, - "hash": "508550c43e9e3f30243813c23eb6eec20918923d7ba09498cddbcd7e8bfa4539", + "hash": "38a171ff362dd1da6d2eb34d51aea753496b2860d6b25adc595e6241ca5bf63c", "action": "add" } }, - "APIEndpointQueueItem": { + "AssociationRequestChange": { "1": { "version": 1, - "hash": "d31b2edfb767401c810584baccd27e4f566181c3ef7706618a82eb25ae20ff6d", + "hash": "2102685cc30aec0d5a2b1f62f38b475745dc129599fce6c57e2bb92d13f1179d", "action": "add" } }, - "ServerMetadataUpdate": { - "2": { - "version": 2, - "hash": "520ae8ffc0c057ffa827cb7b267a19fb6b92e3cf3c0a3666ac34e271b6dd0aed", - "action": "remove" + "QueueItem": { + "4": { + "version": 4, + "hash": "aa04c1a0807164b9307a18d250e09eaf27f74efef61bec9392cd386eb43aa5e6", + "action": "add" } }, - "SyncStateItem": { - "1": { - "version": 1, - "hash": "4dbfa0813f5a3f7be0b36249ff2d67e395ad7c9e138c5a122fc7342b8dcc4b92", - "action": "remove" + "ActionQueueItem": { + "3": { + "version": 3, + "hash": "df2399704de2c69a8a10524133bdb062bee6c48ad18b713d7d7f23fab1819bf7", + "action": "add" } }, - "VeilidConnection": { + "APIEndpointQueueItem": { "1": { "version": 1, - "hash": "c1796e7b01c9eae0dbf59cfd5c2c2f0e7eba593e0cea615717246572b27aae4b", - "action": "remove" + "hash": "d94c0bc1efc18f0217b7342ac49a3ddd4d26df9ffa678a706e84643f7cd3df00", + "action": "add" } }, - "CreateCustomWorkerPoolChange": { - "3": { - "version": 3, - "hash": "e982f2ebcdc6fe23a65a014109e33ba7c487bb7ca5623723cf5ec7642f86828c", + "SyftObjectMigrationState": { + "2": { + "version": 2, + "hash": "51f416fbce4ff408903b96aafa924fc3adde33b19172122b06acd04a1651c7ab", "action": "add" } }, - "ServerPeerUpdate": { - "1": { - "version": 1, - "hash": "9e7cd39f6a9f90e8c595452865525e0989df1688236acfd1a665ed047ba47de9", + "ProjectThreadMessage": { + "2": { + "version": 2, + "hash": "506b292e24486632a2e7d816c48a3051b23527c8a3a35f726ffd7249222b15bb", "action": "add" } }, - "JobInfo": { + "ProjectMessage": { "2": { "version": 2, - "hash": "89dbd4a810586b49498be1f5299b565a19871487e14a120433b0a4cf607b6dee", - "action": "remove" + "hash": "1fabc4acc439749ba2f62f1cf01b56c91a31d59d908bfe206822f88552d3ce71", + "action": "add" } }, - "HTTPConnection": { - "3": { - "version": 3, - "hash": "54b452bb4ab76691ac1e704b62e7bcec740850fea00805145259b37973ecd0f4", + "ProjectRequestResponse": { + "2": { + "version": 2, + "hash": "7b08ce278d58b8ee96d7bc594079c808ec06fd148f14aedc638aba4075d05a1e", "action": "add" } }, - "UserCode": { - "4": { - "version": 4, - "hash": "0a7181cd5f76800b6566175ffa7276d0cf38c4ddc5110114430147dfc8bfdb2a", - "action": "remove" - }, - "5": { - "version": 5, - "hash": "128705a5fdf308055ef857b25c80966c928938a05ec03459dae9b36bd6122aa2", + "ProjectRequest": { + "2": { + "version": 2, + "hash": "ceb9fc7a258dc1574ced311051466f2686f29b1bd65828810f2c87d2022c8533", "action": "add" } }, - "SyncedUserCodeStatusChange": { - "3": { - "version": 3, - "hash": "9b8ab2d513d84006bdd1329cd0bb636e7e62100a6227d8b772a5bf7c0c45b72f", + "AnswerProjectPoll": { + "2": { + "version": 2, + "hash": "b9bd5e61af04a96b93fd9f2e2d8548f8defc391258014c4fbbe4dc80f47c9705", "action": "add" } }, - "PolicyRule": { - "1": { - "version": 1, - "hash": "31a982b94654ce27ad27a6622c6fa26dfe3f759a7824ac21d104390f10a5aa82", + "ProjectPoll": { + "2": { + "version": 2, + "hash": "0dcad5d725714cd023f6d7d40139bb6657a9f39a027ee67442b970c43006623a", "action": "add" } }, - "CreatePolicyRule": { - "1": { - "version": 1, - "hash": "9b82e36c63e10c5b7b76b3b8ec1da1d2dfdce39f2cce98603a418ec221621874", + "Project": { + "2": { + "version": 2, + "hash": "2088e56054a45f13600d63cb44f00674dfa43e79e63639c912c0e58302526e3c", "action": "add" } }, - "CreatePolicyRuleConstant": { - "1": { - "version": 1, - "hash": "9e821ddd383b6472f95dad2b56ebaefad225ff49c96b89b4ce35dc99c422ba76", + "ProjectSubmit": { + "2": { + "version": 2, + "hash": "5341778735a00699b085a0d99afca630cbff8d25aa0f2205a09f74e93263c5e0", "action": "add" } }, - "Matches": { - "1": { - "version": 1, - "hash": "d1e875a6332a481458e83db364dfdf92bd34a87093d9762dfe8e136e5088bc4e", + "ZMQClientConfig": { + "4": { + "version": 4, + "hash": "f54c62694a0b058ebf41d48b783b70423894a0609f50bc3d347b7b135d142674", "action": "add" } }, - "PreFill": { - "1": { - "version": 1, - "hash": "22c38b8ad68409493810362e6c48822d3e2919760f26eba2d1de3f2ad394e314", + "SQLiteStoreConfig": { + "2": { + "version": 2, + "hash": "b6d391bd7884886daef88b08734cf41b4d278b474c22cfc3574b9e7ec140c9e3", "action": "add" } }, - "UserOwned": { - "1": { - "version": 1, - "hash": "b5cbb44d742fa51b9adf2a48bb56d9ff5ca82a25f8568a2505961bd906d9d084", + "Plan": { + "2": { + "version": 2, + "hash": "eec308b8fd9437fc74a65f0cf70dff586130b35866d1e1512de49d45e7896981", "action": "add" } }, - "MixedInputPolicy": { + "StoreMetadata": { "1": { "version": 1, - "hash": "0e84e4c91e378717e1a4703574b07e3b1e6a3e5707401b4e0cc8d30088a506b9", + "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", "action": "add" } }, - "Request": { - "3": { - "version": 3, - "hash": "ba9ebb04cc3e8b3ae3302fd42a67e47261a0a330bae5f189d8f4819cf2804711", + "MigrationData": { + "1": { + "version": 1, + "hash": "ae07a6345762b8ebe9d2a100776e2405fd17516c9d224913a3358c96480ba889", "action": "add" } } diff --git a/packages/grid/helm/syft/values.yaml b/packages/grid/helm/syft/values.yaml index 497dcd97b9b..48bb41fa11a 100644 --- a/packages/grid/helm/syft/values.yaml +++ b/packages/grid/helm/syft/values.yaml @@ -1,7 +1,7 @@ global: # Affects only backend, frontend, and seaweedfs containers registry: docker.io - version: 0.8.7-beta.13 + version: 0.8.7-beta.14 # Force default secret values for development. DO NOT SET THIS TO FALSE IN PRODUCTION randomizedSecrets: true diff --git a/packages/syft/setup.cfg b/packages/syft/setup.cfg index 14a3aaaeb67..9ee693855b2 100644 --- a/packages/syft/setup.cfg +++ b/packages/syft/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = syft -version = attr: "0.8.7-beta.13" +version = attr: "0.8.7-beta.14" description = Perform numpy-like analysis on data that remains in someone elses server author = OpenMined author_email = info@openmined.org diff --git a/packages/syft/src/syft/VERSION b/packages/syft/src/syft/VERSION index df1dec5602a..0c01f370f55 100644 --- a/packages/syft/src/syft/VERSION +++ b/packages/syft/src/syft/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.13" +__version__ = "0.8.7-beta.14" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index 373130e86b4..2cd91e5aefa 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.8.7-beta.13" +__version__ = "0.8.7-beta.14" # stdlib from collections.abc import Callable diff --git a/packages/syftcli/manifest.yml b/packages/syftcli/manifest.yml index 809fb7cfb9d..be37bbf6f71 100644 --- a/packages/syftcli/manifest.yml +++ b/packages/syftcli/manifest.yml @@ -1,11 +1,11 @@ manifestVersion: 1.0 -syftVersion: 0.8.7-beta.13 -dockerTag: 0.8.7-beta.13 +syftVersion: 0.8.7-beta.14 +dockerTag: 0.8.7-beta.14 images: - - docker.io/openmined/syft-frontend:0.8.7-beta.13 - - docker.io/openmined/syft-backend:0.8.7-beta.13 + - docker.io/openmined/syft-frontend:0.8.7-beta.14 + - docker.io/openmined/syft-backend:0.8.7-beta.14 - docker.io/library/mongo:7.0.4 - docker.io/traefik:v2.11.0 From 4d74bc68604b544f965146ee43f016e560ff144a Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Sun, 14 Jul 2024 21:39:15 +0530 Subject: [PATCH 047/117] fix save of flattened action object in user execute - rename preprocess action arg method to flatten action arg --- .../syft/src/syft/service/action/action_service.py | 13 ++++++------- packages/syft/src/syft/service/queue/zmq_queue.py | 4 ---- tests/integration/local/job_test.py | 3 ++- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index 56f74a329c2..3613a60da42 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -391,8 +391,8 @@ def _user_code_execute( output_policy = code_item.get_output_policy(context) # Unwrap nested ActionObjects - for _, arg in kwargs.items(): - self.preprocess_action_arg(context, arg) if isinstance(arg, UID) else None + for _k, arg in kwargs.items(): + self.flatten_action_arg(context, arg) if isinstance(arg, UID) else None if not override_execution_permission: if input_policy is None: @@ -807,9 +807,7 @@ def unwrap_collection(col: set | dict | list) -> [Any]: # type: ignore return True return False - def preprocess_action_arg( - self, context: AuthedServiceContext, arg: UID - ) -> UID | None: + def flatten_action_arg(self, context: AuthedServiceContext, arg: UID) -> UID | None: """ "If the argument is a collection (of collections) of ActionObjects, We want to flatten the collection and upload a new ActionObject that contains its values. E.g. [[ActionObject1, ActionObject2],[ActionObject3, ActionObject4]] @@ -833,8 +831,9 @@ def preprocess_action_arg( syft_node_location=action_object.syft_node_location, ) new_action_object._save_to_blob_storage() - res = self.action_service._set( - context=self.auth_context, action_object=new_action_object + res = self._set( + context=context, + action_object=new_action_object, ) return None diff --git a/packages/syft/src/syft/service/queue/zmq_queue.py b/packages/syft/src/syft/service/queue/zmq_queue.py index faf9434237b..7f2434048b8 100644 --- a/packages/syft/src/syft/service/queue/zmq_queue.py +++ b/packages/syft/src/syft/service/queue/zmq_queue.py @@ -293,10 +293,6 @@ def read_items(self) -> None: action.args ) or self.contains_unresolved_action_objects(action.kwargs): continue - # for arg in action.args: - # self.preprocess_action_arg(arg) - # for _, arg in action.kwargs.items(): - # self.preprocess_action_arg(arg) msg_bytes = serialize(item, to_bytes=True) worker_pool = item.worker_pool.resolve_with_context( diff --git a/tests/integration/local/job_test.py b/tests/integration/local/job_test.py index e713da731df..894cf74be5e 100644 --- a/tests/integration/local/job_test.py +++ b/tests/integration/local/job_test.py @@ -2,7 +2,6 @@ # stdlib from secrets import token_hex -import time # third party import pytest @@ -87,6 +86,7 @@ def job(node): @syft_function() def process_batch(): # stdlib + import time while time.sleep(1) is None: ... @@ -96,6 +96,7 @@ def process_batch(): @syft_function_single_use() def process_all(domain): # stdlib + import time _ = domain.launch_job(process_batch) _ = domain.launch_job(process_batch) From 3b5096864d8eebb4c1f3a3cd7f97b41a47bbe13e Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 15 Jul 2024 10:14:54 +0800 Subject: [PATCH 048/117] Rename deleted dataset --- packages/syft/src/syft/service/dataset/dataset.py | 1 + .../syft/src/syft/service/dataset/dataset_service.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index caf4518584c..026c49e9abd 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -977,4 +977,5 @@ class DatasetUpdate(PartialSyftObject): __canonical_name__ = "DatasetUpdate" __version__ = SYFT_OBJECT_VERSION_1 + name: str marked_as_deleted: bool diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index c7f48d74734..6c1929bd1d9 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -161,9 +161,7 @@ def search( ) @service_method(path="dataset.get_by_id", name="get_by_id") - def get_by_id( - self, context: AuthedServiceContext, uid: UID - ) -> SyftSuccess | SyftError: + def get_by_id(self, context: AuthedServiceContext, uid: UID) -> Dataset | SyftError: """Get a Dataset""" result = self.stash.get_by_uid(context.credentials, uid=uid) if result.is_err(): @@ -248,8 +246,10 @@ def delete( return_msg.append(f"Asset with id '{asset.id}' successfully deleted.") # soft delete the dataset object from the store # result = self.stash.delete_by_uid(credentials=context.credentials, uid=uid) - datset_update = DatasetUpdate(id=uid, marked_as_deleted=True) - result = self.stash.update(context.credentials, datset_update) + dataset_update = DatasetUpdate( + id=uid, name=f"{uid}-{dataset.name}", marked_as_deleted=True + ) + result = self.stash.update(context.credentials, dataset_update) if result.is_err(): return SyftError(message=result.err()) return_msg.append(f"Dataset with id '{uid}' successfully deleted.") From d96392d9792f64db5ed6c2aff35719fbee441fed Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 15 Jul 2024 10:16:24 +0800 Subject: [PATCH 049/117] Rename Dataset.marked_as_deleted to Dataset.to_be_deleted to be consistent with SyftWorker.to_be_deleted --- .../syft/src/syft/service/dataset/dataset.py | 20 +++++++++---------- .../syft/service/dataset/dataset_service.py | 12 +++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index 026c49e9abd..f7fdf0b3e5e 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -508,7 +508,7 @@ class Dataset(SyftObject): created_at: DateTime = DateTime.now() uploader: Contributor summary: str | None = None - marked_as_deleted: bool = False + to_be_deleted: bool = False __attr_searchable__ = [ "name", @@ -698,11 +698,11 @@ def __assets_must_contain_mock( _check_asset_must_contain_mock(asset_list) return asset_list - @field_validator("marked_as_deleted") + @field_validator("to_be_deleted") @classmethod - def __marked_as_deleted_must_be_false(cls, v: bool) -> bool: + def __to_be_deleted_must_be_false(cls, v: bool) -> bool: if v is True: - raise ValueError("marked_as_deleted must be False") + raise ValueError("to_be_deleted must be False") return v def set_description(self, description: str) -> None: @@ -931,7 +931,7 @@ def createdataset_to_dataset() -> list[Callable]: validate_url, convert_asset, add_current_date, - make_set_default("marked_as_deleted", False), # explicitly set it to False + make_set_default("to_be_deleted", False), # explicitly set it to False ] @@ -941,7 +941,7 @@ def migrate_dataset_v2_to_v3() -> list[Callable]: make_set_default("summary", None), drop("__repr_attrs__"), make_set_default("__repr_attrs__", ["name", "summary", "url", "created_at"]), - make_set_default("marked_as_deleted", False), + make_set_default("to_be_deleted", False), ] @@ -949,7 +949,7 @@ def migrate_dataset_v2_to_v3() -> list[Callable]: def migrate_dataset_v3_to_v2() -> list[Callable]: return [ drop("summary"), - drop(["__repr_attrs__", "marked_as_deleted"]), + drop(["__repr_attrs__", "to_be_deleted"]), make_set_default("__repr_attrs__", ["name", "url", "created_at"]), ] @@ -960,7 +960,7 @@ def migrate_create_dataset_v2_to_v3() -> list[Callable]: make_set_default("summary", None), drop("__repr_attrs__"), make_set_default("__repr_attrs__", ["name", "summary", "url"]), - make_set_default("marked_as_deleted", False), + make_set_default("to_be_deleted", False), ] @@ -968,7 +968,7 @@ def migrate_create_dataset_v2_to_v3() -> list[Callable]: def migrate_create_dataset_v3_to_v2() -> list[Callable]: return [ drop("summary"), - drop(["__repr_attrs__", "marked_as_deleted"]), + drop(["__repr_attrs__", "to_be_deleted"]), make_set_default("__repr_attrs__", ["name", "url"]), ] @@ -978,4 +978,4 @@ class DatasetUpdate(PartialSyftObject): __version__ = SYFT_OBJECT_VERSION_1 name: str - marked_as_deleted: bool + to_be_deleted: bool diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index 6c1929bd1d9..dff15361220 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -129,7 +129,7 @@ def get_all( for dataset in datasets: if context.server is not None: dataset.node_uid = context.server.id - if dataset.marked_as_deleted: + if dataset.to_be_deleted: datasets.remove(dataset) return _paginate_dataset_collection( @@ -153,7 +153,7 @@ def search( filtered_results = [ dataset for dataset_name, dataset in results.items() - if name in dataset_name and not dataset.marked_as_deleted + if name in dataset_name and not dataset.to_be_deleted ] return _paginate_dataset_collection( @@ -167,7 +167,7 @@ def get_by_id(self, context: AuthedServiceContext, uid: UID) -> Dataset | SyftEr if result.is_err(): return SyftError(message=result.err()) dataset = result.ok() - if dataset.marked_as_deleted: + if dataset.to_be_deleted: return SyftError(message="Dataset not found.") if context.server is not None: dataset.node_uid = context.server.id @@ -185,7 +185,7 @@ def get_by_action_id( for dataset in datasets: if context.server is not None: dataset.node_uid = context.server.id - if dataset.marked_as_deleted: + if dataset.to_be_deleted: datasets.remove(dataset) return datasets @@ -202,7 +202,7 @@ def get_assets_by_action_id( if isinstance(datasets, SyftError): return datasets for dataset in datasets: - if dataset.marked_as_deleted: + if dataset.to_be_deleted: datasets.remove(dataset) return [ asset @@ -247,7 +247,7 @@ def delete( # soft delete the dataset object from the store # result = self.stash.delete_by_uid(credentials=context.credentials, uid=uid) dataset_update = DatasetUpdate( - id=uid, name=f"{uid}-{dataset.name}", marked_as_deleted=True + id=uid, name=f"{uid}-{dataset.name}", to_be_deleted=True ) result = self.stash.update(context.credentials, dataset_update) if result.is_err(): From aa99cd6aba0379c1184a21d21481af11ebf81e05 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 15 Jul 2024 10:19:01 +0800 Subject: [PATCH 050/117] Rename node to server --- packages/syft/src/syft/service/action/action_service.py | 2 +- packages/syft/src/syft/service/dataset/dataset_service.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index fa9ab98c2da..dd471237035 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -890,7 +890,7 @@ def _delete_blob_storage_entry( ) -> SyftSuccess | SyftError: deleted_blob_ids = [] blob_store_service = cast( - BlobStorageService, context.node.get_service(BlobStorageService) + BlobStorageService, context.server.get_service(BlobStorageService) ) if isinstance(obj, ActionObject) and obj.syft_blob_storage_entry_id: diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index dff15361220..1cfd04303a6 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -235,7 +235,7 @@ def delete( return_msg = [] for asset in dataset.asset_list: action_service = cast( - ActionService, context.node.get_service(ActionService) + ActionService, context.server.get_service(ActionService) ) del_res: SyftSuccess | SyftError = action_service.delete( context=context, uid=asset.action_id From f7ca6211f671c9a1eb9c6aae2d00810cd053da38 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 15 Jul 2024 10:19:56 +0800 Subject: [PATCH 051/117] Rename root_domain_client to root_client domain has been renamed to datasite --- .../syft/service/action/action_object_test.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/syft/tests/syft/service/action/action_object_test.py b/packages/syft/tests/syft/service/action/action_object_test.py index c2c0d916236..da3ea135f5b 100644 --- a/packages/syft/tests/syft/service/action/action_object_test.py +++ b/packages/syft/tests/syft/service/action/action_object_test.py @@ -1032,29 +1032,29 @@ def test_actionobject_delete(worker): """ Test deleting action objects and their corresponding blob storage entries """ - root_domain_client = worker.root_client + root_client = worker.root_client # small object with no blob store entry data_small = np.random.randint(0, 100, size=3) action_obj = ActionObject.from_obj(data_small) - action_obj.send(root_domain_client) + action_obj.send(root_client) assert action_obj.syft_blob_storage_entry_id is None - del_res = root_domain_client.api.services.action.delete(uid=action_obj.id) + del_res = root_client.api.services.action.delete(uid=action_obj.id) assert isinstance(del_res, SyftSuccess) # big object with blob store entry num_elements = 25 * 1024 * 1024 data_big = np.random.randint(0, 100, size=num_elements) # 4 bytes per int32 action_obj_2 = ActionObject.from_obj(data_big) - action_obj_2.send(root_domain_client) + action_obj_2.send(root_client) assert isinstance(action_obj_2.syft_blob_storage_entry_id, UID) - read_res = root_domain_client.api.services.blob_storage.read( + read_res = root_client.api.services.blob_storage.read( action_obj_2.syft_blob_storage_entry_id ) assert isinstance(read_res, SyftObjectRetrieval) - del_res = root_domain_client.api.services.action.delete(uid=action_obj_2.id) + del_res = root_client.api.services.action.delete(uid=action_obj_2.id) assert isinstance(del_res, SyftSuccess) - read_res = root_domain_client.api.services.blob_storage.read( + read_res = root_client.api.services.blob_storage.read( action_obj_2.syft_blob_storage_entry_id ) assert isinstance(read_res, SyftError) From d9259426ad8c332211364db33dafdfd51511bbb5 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 15 Jul 2024 10:36:59 +0800 Subject: [PATCH 052/117] Create a None ActionObject to replace the one linked with the deleted Asset --- .../syft/service/dataset/dataset_service.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index 1cfd04303a6..d09c8c34465 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -10,6 +10,7 @@ from ...types.dicttuple import DictTuple from ...types.uid import UID from ...util.telemetry import instrument +from ..action.action_object import ActionObject from ..action.action_permissions import ActionObjectPermission from ..action.action_permissions import ActionPermission from ..action.action_service import ActionService @@ -234,15 +235,37 @@ def delete( # delete the dataset's assets return_msg = [] for asset in dataset.asset_list: + msg = ( + f"ActionObject {asset.action_id} " + f"linked with Assset {asset.id} " + f"in Dataset {uid}" + ) + action_service = cast( ActionService, context.server.get_service(ActionService) ) del_res: SyftSuccess | SyftError = action_service.delete( context=context, uid=asset.action_id ) + if isinstance(del_res, SyftError): + del_msg = f"Failed to delete {msg}: {del_res.message}" + logger.error(del_msg) return del_res - logger.info(del_res.message) + logger.info(f"Successfully deleted {msg}: {del_res.message}") + + res = action_service.set( + context=context, + action_object=ActionObject.from_obj( + syft_action_data=None, id=asset.action_id + ), + ) + + if isinstance(res, SyftError): + set_msg = f"Failed to create a None {msg}: {res.message}" + logger.error(set_msg) + logger.info(f"Successfully created a None {msg}: {res.message}") + return_msg.append(f"Asset with id '{asset.id}' successfully deleted.") # soft delete the dataset object from the store # result = self.stash.delete_by_uid(credentials=context.credentials, uid=uid) From dd3cba3dd781bb09247e3ef6b647dd8c925ea5ae Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 15 Jul 2024 10:47:46 +0800 Subject: [PATCH 053/117] Rename node_uid to server_uid --- packages/syft/src/syft/service/dataset/dataset_service.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index d09c8c34465..e9af0aad3bd 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -129,7 +129,7 @@ def get_all( for dataset in datasets: if context.server is not None: - dataset.node_uid = context.server.id + dataset.server_uid = context.server.id if dataset.to_be_deleted: datasets.remove(dataset) @@ -171,7 +171,7 @@ def get_by_id(self, context: AuthedServiceContext, uid: UID) -> Dataset | SyftEr if dataset.to_be_deleted: return SyftError(message="Dataset not found.") if context.server is not None: - dataset.node_uid = context.server.id + dataset.server_uid = context.server.id return dataset @service_method(path="dataset.get_by_action_id", name="get_by_action_id") @@ -185,7 +185,7 @@ def get_by_action_id( datasets = result.ok() for dataset in datasets: if context.server is not None: - dataset.node_uid = context.server.id + dataset.server_uid = context.server.id if dataset.to_be_deleted: datasets.remove(dataset) return datasets From a2de957c451817b275106585b45641cc112174d8 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 15 Jul 2024 11:02:45 +0800 Subject: [PATCH 054/117] Update protocol version --- packages/syft/src/syft/protocol/protocol_version.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index 6602155d200..9c2bf50adee 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -535,7 +535,7 @@ }, "3": { "version": 3, - "hash": "acc25456a60ccef861de65eea1feef612ef9fa1ed6e986b466450c4adf73906b", + "hash": "9a0c9a7dbd7180eafef272e5db1cec9a7933793d321b5b58a7fdb09e742dc173", "action": "add" } }, @@ -554,7 +554,7 @@ }, "3": { "version": 3, - "hash": "7ecb8d62a8c12e385ff45ed700106bb1463926237fbdde3e84a83f38419d54de", + "hash": "366135dd01adb59511e43278c8a6f8b8d746bd2edc80c71a114ddc1ef5bcf474", "action": "add" } }, From 24050bd06877f0810003b8c3c3a6e8b122cdd1ef Mon Sep 17 00:00:00 2001 From: dk Date: Mon, 15 Jul 2024 10:29:38 +0700 Subject: [PATCH 055/117] [syft/action_service] soft deleting an action ojbect / twin object from store --- .../src/syft/service/action/action_service.py | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index dd471237035..a39784ed960 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -861,7 +861,7 @@ def exists( @service_method(path="action.delete", name="delete", roles=ADMIN_ROLE_LEVEL) def delete( - self, context: AuthedServiceContext, uid: UID + self, context: AuthedServiceContext, uid: UID, soft_delete: bool = True ) -> SyftSuccess | SyftError: get_res = self.store.get(uid=uid, credentials=context.credentials) if get_res.is_err(): @@ -876,7 +876,9 @@ def delete( return_msg.append(blob_del_res.message) # delete the action object from the action store - store_del_res = self._delete_from_action_store(context=context, obj=obj) + store_del_res = self._delete_from_action_store( + context=context, uid=obj.id, soft_delete=soft_delete + ) if isinstance(store_del_res, SyftError): return SyftError(message=store_del_res.message) return_msg.append(store_del_res.message) @@ -923,14 +925,46 @@ def _delete_blob_storage_entry( def _delete_from_action_store( self, context: AuthedServiceContext, - obj: TwinObject | ActionObject, + uid: UID, + soft_delete: bool = True, ) -> SyftSuccess | SyftError: - uid = obj.id - res = self.store.delete(credentials=context.credentials, uid=uid) - if res.is_err(): - return SyftError(message=res.err()) + if soft_delete: + get_res = self.store.get(uid=uid, credentials=context.credentials) + if get_res.is_err(): + return SyftError(message=get_res.err()) + obj: ActionObject | TwinObject = get_res.ok() + if isinstance(obj, TwinObject): + res = self._soft_delete(context=context, action_obj=obj.private) + if res.is_err(): + return SyftError(message=res.err()) + res = self._soft_delete(context=context, action_obj=obj.mock) + if res.is_err(): + return SyftError(message=res.err()) + else: # ActionObject + res = self._soft_delete(context, obj) + if res.is_err(): + return SyftError(message=res.err()) + else: + res = self.store.delete(credentials=context.credentials, uid=uid) + if res.is_err(): + return SyftError(message=res.err()) + return SyftSuccess(message=f"Action object with uid '{uid}' deleted.") + def _soft_delete( + self, context: AuthedServiceContext, action_obj: ActionObject + ) -> Result[ActionObject, str]: + action_obj.syft_blob_storage_entry_id = None + action_obj.syft_action_data_type = None + action_obj.syft_action_data_repr_ = None + action_obj.syft_action_data_str_ = None + action_obj.syft_action_data_server_id = None + action_obj.syft_action_data_cache = None + res = self.set(context=context, action_object=action_obj) + if isinstance(res, SyftError): + return Err(res.message) + return Ok(action_obj) + def resolve_action_args( action: Action, context: AuthedServiceContext, service: ActionService From 7b8fc8036b06ab00c9e2f18b71216a6f51d09a5c Mon Sep 17 00:00:00 2001 From: dk Date: Mon, 15 Jul 2024 10:49:18 +0700 Subject: [PATCH 056/117] [syft/action_service] moving logic to soft delete a dataset's assets to action service Co-authored-by: Kien Dang --- .../src/syft/service/action/action_service.py | 31 ++++++++++--------- .../syft/service/dataset/dataset_service.py | 14 +-------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index a39784ed960..dc0be3500bd 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -934,14 +934,16 @@ def _delete_from_action_store( return SyftError(message=get_res.err()) obj: ActionObject | TwinObject = get_res.ok() if isinstance(obj, TwinObject): - res = self._soft_delete(context=context, action_obj=obj.private) + res = self._soft_delete_action_obj( + context=context, action_obj=obj.private + ) if res.is_err(): return SyftError(message=res.err()) - res = self._soft_delete(context=context, action_obj=obj.mock) + res = self._soft_delete_action_obj(context=context, action_obj=obj.mock) if res.is_err(): return SyftError(message=res.err()) else: # ActionObject - res = self._soft_delete(context, obj) + res = self._soft_delete_action_obj(context, obj) if res.is_err(): return SyftError(message=res.err()) else: @@ -951,19 +953,20 @@ def _delete_from_action_store( return SyftSuccess(message=f"Action object with uid '{uid}' deleted.") - def _soft_delete( + def _soft_delete_action_obj( self, context: AuthedServiceContext, action_obj: ActionObject ) -> Result[ActionObject, str]: - action_obj.syft_blob_storage_entry_id = None - action_obj.syft_action_data_type = None - action_obj.syft_action_data_repr_ = None - action_obj.syft_action_data_str_ = None - action_obj.syft_action_data_server_id = None - action_obj.syft_action_data_cache = None - res = self.set(context=context, action_object=action_obj) - if isinstance(res, SyftError): - return Err(res.message) - return Ok(action_obj) + uid: UID = action_obj.id + del_res = self.store.delete(credentials=context.credentials, uid=uid) + if del_res.is_err(): + return del_res + none_action_obj = ActionObject.from_obj(syft_action_data=None, id=uid) + set_result = self._set( + context=context, + action_object=none_action_obj, + ignore_detached_objs=True, + ) + return set_result def resolve_action_args( diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index e9af0aad3bd..7cf1e08d187 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -10,7 +10,6 @@ from ...types.dicttuple import DictTuple from ...types.uid import UID from ...util.telemetry import instrument -from ..action.action_object import ActionObject from ..action.action_permissions import ActionObjectPermission from ..action.action_permissions import ActionPermission from ..action.action_service import ActionService @@ -252,19 +251,8 @@ def delete( del_msg = f"Failed to delete {msg}: {del_res.message}" logger.error(del_msg) return del_res - logger.info(f"Successfully deleted {msg}: {del_res.message}") - res = action_service.set( - context=context, - action_object=ActionObject.from_obj( - syft_action_data=None, id=asset.action_id - ), - ) - - if isinstance(res, SyftError): - set_msg = f"Failed to create a None {msg}: {res.message}" - logger.error(set_msg) - logger.info(f"Successfully created a None {msg}: {res.message}") + logger.info(f"Successfully deleted {msg}: {del_res.message}") return_msg.append(f"Asset with id '{asset.id}' successfully deleted.") # soft delete the dataset object from the store From b8d1e5588a2cbc93255528108a324f7626d79cd8 Mon Sep 17 00:00:00 2001 From: khoaguin Date: Mon, 15 Jul 2024 14:15:55 +0700 Subject: [PATCH 057/117] [syft/dataset_service] add an option to delete a dataset object without deleting its assets - update a dataset's repr if it was deleted - modify respective tests --- .../src/syft/service/action/action_service.py | 17 ++++-- .../syft/src/syft/service/dataset/dataset.py | 2 + .../syft/service/dataset/dataset_service.py | 61 ++++++++++--------- .../service/dataset/dataset_service_test.py | 46 +++++++++++--- 4 files changed, 85 insertions(+), 41 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index dc0be3500bd..a97d7368d3b 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -861,7 +861,7 @@ def exists( @service_method(path="action.delete", name="delete", roles=ADMIN_ROLE_LEVEL) def delete( - self, context: AuthedServiceContext, uid: UID, soft_delete: bool = True + self, context: AuthedServiceContext, uid: UID, soft_delete: bool = False ) -> SyftSuccess | SyftError: get_res = self.store.get(uid=uid, credentials=context.credentials) if get_res.is_err(): @@ -902,6 +902,7 @@ def _delete_blob_storage_entry( if isinstance(blob_del_res, SyftError): return SyftError(message=blob_del_res.message) deleted_blob_ids.append(obj.syft_blob_storage_entry_id) + if isinstance(obj, TwinObject): if obj.private.syft_blob_storage_entry_id: blob_del_res = blob_store_service.delete( @@ -910,6 +911,7 @@ def _delete_blob_storage_entry( if isinstance(blob_del_res, SyftError): return SyftError(message=blob_del_res.message) deleted_blob_ids.append(obj.private.syft_blob_storage_entry_id) + if obj.mock.syft_blob_storage_entry_id: blob_del_res = blob_store_service.delete( context=context, uid=obj.mock.syft_blob_storage_entry_id @@ -926,13 +928,14 @@ def _delete_from_action_store( self, context: AuthedServiceContext, uid: UID, - soft_delete: bool = True, + soft_delete: bool = False, ) -> SyftSuccess | SyftError: if soft_delete: get_res = self.store.get(uid=uid, credentials=context.credentials) if get_res.is_err(): return SyftError(message=get_res.err()) obj: ActionObject | TwinObject = get_res.ok() + if isinstance(obj, TwinObject): res = self._soft_delete_action_obj( context=context, action_obj=obj.private @@ -942,8 +945,9 @@ def _delete_from_action_store( res = self._soft_delete_action_obj(context=context, action_obj=obj.mock) if res.is_err(): return SyftError(message=res.err()) - else: # ActionObject - res = self._soft_delete_action_obj(context, obj) + + if isinstance(obj, ActionObject): + res = self._soft_delete_action_obj(context=context, action_obj=obj) if res.is_err(): return SyftError(message=res.err()) else: @@ -956,11 +960,16 @@ def _delete_from_action_store( def _soft_delete_action_obj( self, context: AuthedServiceContext, action_obj: ActionObject ) -> Result[ActionObject, str]: + """ + Delete the provided action object and create an empty one with the same UID + """ uid: UID = action_obj.id del_res = self.store.delete(credentials=context.credentials, uid=uid) if del_res.is_err(): return del_res + none_action_obj = ActionObject.from_obj(syft_action_data=None, id=uid) + none_action_obj.syft_action_saved_to_blob_store = False set_result = self._set( context=context, action_object=none_action_obj, diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index f7fdf0b3e5e..e0d3c8a41d1 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -561,6 +561,8 @@ def _repr_html_(self) -> Any: """ else: description_info_message = "" + if self.to_be_deleted: + return "This dataset has been marked for deletion. The underlying data may be not available." return f""" \n", + "
\n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "034f839d-f656-4deb-92c5-f1e42fe8561f", + "metadata": {}, + "outputs": [], + "source": [ + "# what minimum settings do we need to be able to run jobs?\n", + "# create_producer=True,\n", + "# n_consumers=1," + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b5a02956-9196-405e-aec8-3c59c1b016e7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Stopping test-datasite-1\n", + "INFO: 127.0.0.1:53987 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54156 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54204 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54204 - \"POST /api/v2/login HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54204 - \"GET /api/v2/api?verify_key=8142e576c07f91243818f902b3ec8b2f49cd5a7eec2c126e8df11ce1bc36d7c2&communication_protocol=dev HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54206 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:root:Invalid SMTP credentials timed out\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: 127.0.0.1:54209 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:root:Invalid SMTP credentials timed out\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: 127.0.0.1:54495 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54618 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54621 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54658 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54660 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54667 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54669 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54791 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54808 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54810 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54812 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54815 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54817 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54819 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54823 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54825 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54827 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54829 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54831 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54833 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54835 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54837 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54839 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54856 - \"GET /api/v2/api?verify_key=e117b2b343c7bf0dc2c88a0b2e104e04118143220f0d7ff8ed2f178d1da0c167&communication_protocol=dev HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54856 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54858 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:syft.server.routes:Register Error: You don't have permission to create an account on the datasite: a. Please contact the Datasite Owner.. user={'id': , 'email': 'a@b.com', 'name': 'a', 'role': None, 'password': 'c', 'password_verify': 'c', 'verify_key': None, 'institution': None, 'website': None, 'created_by': {'signing_key': }, 'mock_execution_permission': False}\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: 127.0.0.1:54862 - \"POST /api/v2/register HTTP/1.1\" 200 OK\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:syft.server.routes:Register Error: You don't have permission to create an account on the datasite: a. Please contact the Datasite Owner.. user={'id': , 'email': 'a@b.com', 'name': 'a', 'role': None, 'password': 'c', 'password_verify': 'c', 'verify_key': None, 'institution': None, 'website': None, 'created_by': {'signing_key': }, 'mock_execution_permission': False}\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: 127.0.0.1:54864 - \"POST /api/v2/register HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54868 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54870 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:54872 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55056 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55058 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55062 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55127 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55129 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55131 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55134 - \"GET /api/v2/api?verify_key=ca989d05c9ef083b8f56c281b097570223ca1567761515eaeac9e2794d103f0a&communication_protocol=dev HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55134 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55136 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55149 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55152 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55155 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55157 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55159 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55177 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55180 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55182 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55184 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55186 - \"GET /api/v2/api?verify_key=863592d8f09e8410733073b3388c0a9219cda01aa4ab3c602ad35790adaf3a2a&communication_protocol=dev HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55188 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:syft.server.routes:Register Error: You don't have permission to create an account on the datasite: a. Please contact the Datasite Owner.. user={'id': , 'email': 'a@b.com', 'name': 'a', 'role': None, 'password': 'c', 'password_verify': 'c', 'verify_key': None, 'institution': None, 'website': None, 'created_by': {'signing_key': }, 'mock_execution_permission': False}\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: 127.0.0.1:55186 - \"POST /api/v2/register HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55193 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55196 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55198 - \"POST /api/v2/register HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55200 - \"POST /api/v2/login HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55200 - \"GET /api/v2/api?verify_key=3a22a2dbfdfff9241974522007c3aefb3526cb709742bbe80594b39d5026621c&communication_protocol=dev HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55202 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55204 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55479 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55496 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55526 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55612 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55612 - \"POST /api/v2/login HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55612 - \"GET /api/v2/api?verify_key=8142e576c07f91243818f902b3ec8b2f49cd5a7eec2c126e8df11ce1bc36d7c2&communication_protocol=dev HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55614 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55617 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55619 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55621 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55623 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55625 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55627 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55633 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55635 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55637 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55639 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55641 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55643 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55645 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56162 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56164 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56166 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56168 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56170 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56172 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56174 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56177 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:56179 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n" + ] + } + ], + "source": [ + "server.land()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fbfbb1b1-8a3b-4386-9b30-e373ca2cf8d5", + "metadata": {}, "outputs": [], "source": [] } diff --git a/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb b/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb index 7dd45cda15b..3825c2aafb6 100644 --- a/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb +++ b/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "9278cdde-2ddc-493f-ab1a-7a224f2c2338", "metadata": {}, "outputs": [], @@ -11,6 +11,1528 @@ "# -- optional: adding email settings (smtp with sendgrid free account)\n", "# -- changing passwords (importance of root account)" ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f9cac3bb-9310-4c6e-bf02-08752e9d70df", + "metadata": {}, + "outputs": [], + "source": [ + "SYFT_VERSION = \">=0.8.7.b0,<0.9\"\n", + "package_string = f'\"syft{SYFT_VERSION}\"'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d01b99d1-999f-4e85-abf3-c74484df8bef", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ The installed version of syft==0.8.7b14 matches the requirement >=0.8.7b0 and the requirement <0.9\n" + ] + } + ], + "source": [ + "# syft absolute\n", + "import syft as sy\n", + "\n", + "sy.requires(SYFT_VERSION)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2045933d-bc99-4483-9ca1-89c6ab166a0f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting test-datasite-1 server on 0.0.0.0:8081\n", + " Done.\n" + ] + }, + { + "data": { + "text/html": [ + "
SyftInfo:
You have launched a development server at http://0.0.0.0:8081.It is intended only for local use.

" + ], + "text/plain": [ + "SyftInfo: You have launched a development server at http://0.0.0.0:8081.It is intended only for local use." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# run a local webserver\n", + "server = sy.orchestra.launch(name=\"test-datasite-1\", port=8081)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "15470a8b-8760-49b5-8ab9-2947a4518075", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Logged into as GUEST\n", + "Logged into as \n" + ] + }, + { + "data": { + "text/html": [ + "
SyftWarning:
You are using a default password. Please change the password using `[your_client].me.set_password([new_password])`.

" + ], + "text/plain": [ + "SyftWarning: You are using a default password. Please change the password using `[your_client].me.set_password([new_password])`." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "client = server.login(email=\"info@openmined.org\", password=\"changethis\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "84cdb3e3-a165-4f7b-9390-56ebb3cf02a4", + "metadata": {}, + "outputs": [], + "source": [ + "# email" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1a0738a4-7acd-4e00-b659-651bf0af8a4e", + "metadata": {}, + "outputs": [], + "source": [ + "secrets = sy.get_nb_secrets(defaults={\"smtp_token\": \"ADD_POSTMARK_TOKEN\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "488d9fd4-6de9-46e0-9565-3f479af534e2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftError:
Invalid SMTP credentials. Please check your username and password.

" + ], + "text/plain": [ + "SyftError: Invalid SMTP credentials. Please check your username and password." + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "smtp_username, smtp_password, smtp_server, smtp_port = (\n", + " secrets[\"smtp_token\"],\n", + " secrets[\"smtp_token\"],\n", + " \"smtp.postmarkapp.com\",\n", + " \"25\",\n", + ")\n", + "# configure email settings\n", + "client.api.services.settings.enable_notifications(\n", + " email_username=smtp_username,\n", + " email_password=smtp_password,\n", + " email_sender=\"madhava@openmined.org\",\n", + " email_server=smtp_server,\n", + " email_port=smtp_port,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e0cbb4dc-3400-418e-ae06-fd3033e042a1", + "metadata": {}, + "outputs": [], + "source": [ + "ns = client.api.services.notifications.settings()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "1ec5f362-ecc1-44f6-99ac-ea8771ceb040", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ns.email_enabled" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "0731f6fb-82bc-4ee3-bce1-9988e38b842a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{: syft.service.notifier.notifier.EmailNotifier}" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ns.notifiers" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "ace1e4a6-f1db-4506-8b5a-47d2940b510e", + "metadata": {}, + "outputs": [], + "source": [ + "s = client.api.services.settings.get()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "c5556eee-1f9e-4eb0-b82a-ec4f523a3260", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + "
\n", + "

Settings

\n", + "

Id: 2baa8fe9deb94b6ead87ea7be4cb230e

\n", + "

Name: test-datasite-1

\n", + "

Organization: OpenMined

\n", + "

Description: This is the default description for a Datasite Server.

\n", + "

Deployed on: 07/15/2024

\n", + "

Signup enabled: False

\n", + "

Notifications enabled: True via email

\n", + "

Admin email: info@openmined.org

\n", + "
\n", + "\n", + " " + ], + "text/markdown": [ + "```python\n", + "class ServerSettings:\n", + " id: str = 2baa8fe9deb94b6ead87ea7be4cb230e\n", + " name: str = \"test-datasite-1\"\n", + " organization: str = \"OpenMined\"\n", + " description: str = \"This is the default description for a Datasite Server.\"\n", + " deployed_on: str = \"07/15/2024\"\n", + " signup_enabled: str = False\n", + " admin_email: str = \"info@openmined.org\"\n", + "\n", + "```" + ], + "text/plain": [ + "syft.service.settings.settings.ServerSettings" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "f81fd6f7-6e61-48d6-bf0c-e22718a109fb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftError:
Arg is `SyftError: Duplication Key Error for syft.service.settings.settings.ServerSettings.\n",
+       "The fields that should be unique are `id`.`. \n",
+       "It must be of type `ServerSettings`, not `SyftError`

" + ], + "text/plain": [ + "SyftError: Arg is `SyftError: Duplication Key Error for syft.service.settings.settings.ServerSettings.\n", + "The fields that should be unique are `id`.`. \n", + "It must be of type `ServerSettings`, not `SyftError`" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.api.services.settings.set(s)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "0ad33f86-3576-4dd7-9cac-5ccf7fefb943", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
Settings updated successfully. You must call .refresh() to sync your client with the changes.

" + ], + "text/plain": [ + "SyftSuccess: Settings updated successfully. You must call .refresh() to sync your client with the changes." + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.api.services.settings.update(\n", + " name=\"a\",\n", + " organization=\"b\",\n", + " description=\"c\",\n", + " admin_email=\"info2@openmined.org\",\n", + " association_request_auto_approval=True,\n", + " eager_execution_enabled=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "82eac269-4f51-45a8-8480-8a2e3a382862", + "metadata": {}, + "outputs": [], + "source": [ + "md = \"\"\"\n", + " An h1 header\n", + "============\n", + "\n", + "Paragraphs are separated by a blank line.\n", + "\n", + "2nd paragraph. *Italic*, **bold**, and `monospace`. Itemized lists\n", + "look like:\n", + "\n", + " * this one\n", + " * that one\n", + " * the other one\n", + "\n", + "Note that --- not considering the asterisk --- the actual text\n", + "content starts at 4-columns in.\n", + "\n", + "> Block quotes are\n", + "> written like so.\n", + ">\n", + "> They can span multiple paragraphs,\n", + "> if you like.\n", + "\n", + "Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., \"it's all\n", + "in chapters 12--14\"). Three dots ... will be converted to an ellipsis.\n", + "Unicode is supported. ☺\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "8389d1a4-027e-4282-ad91-274c34e0011c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "\n", + " An h1 header\n", + "============\n", + "\n", + "Paragraphs are separated by a blank line.\n", + "\n", + "2nd paragraph. *Italic*, **bold**, and `monospace`. Itemized lists\n", + "look like:\n", + "\n", + " * this one\n", + " * that one\n", + " * the other one\n", + "\n", + "Note that --- not considering the asterisk --- the actual text\n", + "content starts at 4-columns in.\n", + "\n", + "> Block quotes are\n", + "> written like so.\n", + ">\n", + "> They can span multiple paragraphs,\n", + "> if you like.\n", + "\n", + "Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., \"it's all\n", + "in chapters 12--14\"). Three dots ... will be converted to an ellipsis.\n", + "Unicode is supported. ☺\n" + ], + "text/plain": [ + "syft.util.misc_objs.MarkdownDescription" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.api.services.settings.welcome_preview(markdown=md)" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "53d16bdf-bcfa-4ca5-8b98-5124f480e81b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
Welcome Markdown was successfully updated!

" + ], + "text/plain": [ + "SyftSuccess: Welcome Markdown was successfully updated!" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.api.services.settings.welcome_customize(markdown=md)" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "d267ccf1-9cb0-4b02-80fe-2608d6c55549", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "\n", + " An h1 header\n", + "============\n", + "\n", + "Paragraphs are separated by a blank line.\n", + "\n", + "2nd paragraph. *Italic*, **bold**, and `monospace`. Itemized lists\n", + "look like:\n", + "\n", + " * this one\n", + " * that one\n", + " * the other one\n", + "\n", + "Note that --- not considering the asterisk --- the actual text\n", + "content starts at 4-columns in.\n", + "\n", + "> Block quotes are\n", + "> written like so.\n", + ">\n", + "> They can span multiple paragraphs,\n", + "> if you like.\n", + "\n", + "Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., \"it's all\n", + "in chapters 12--14\"). Three dots ... will be converted to an ellipsis.\n", + "Unicode is supported. ☺\n" + ], + "text/plain": [ + "syft.util.misc_objs.MarkdownDescription" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.api.services.settings.welcome_show()" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "bf5318ef-0aa5-4bb5-b366-3f5fc06f00b6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Logged into as GUEST\n" + ] + }, + { + "data": { + "text/html": [ + "
An h1 header\n",
+       "
\n", + "

============

\n", + "

Paragraphs are separated by a blank line.

\n", + "

2nd paragraph. Italic, bold, and monospace. Itemized lists\n", + "look like:

\n", + "
    \n", + "
  • this one
  • \n", + "
  • that one
  • \n", + "
  • the other one
  • \n", + "
\n", + "

Note that --- not considering the asterisk --- the actual text\n", + "content starts at 4-columns in.

\n", + "
\n", + "

Block quotes are\n", + "written like so.

\n", + "

They can span multiple paragraphs,\n", + "if you like.

\n", + "
\n", + "

Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., \"it's all\n", + "in chapters 12--14\"). Three dots ... will be converted to an ellipsis.\n", + "Unicode is supported. ☺

" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "guest_client = client.login_as_guest()\n", + "guest_client" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "1abfe0af-9566-4f78-892e-0b7397ec081c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftError:
You don't have permission to create an account on the datasite: a. Please contact the Datasite Owner.

" + ], + "text/plain": [ + "SyftError: You don't have permission to create an account on the datasite: a. Please contact the Datasite Owner." + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "guest_client.register(name=\"a\", email=\"a@b.com\", password=\"c\", password_verify=\"c\")" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "a19d34bd-0033-4c90-9ef7-c88fe4d87dad", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
Registration feature successfully enabled

" + ], + "text/plain": [ + "SyftSuccess: Registration feature successfully enabled" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.api.services.settings.allow_guest_signup(enable=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "bd7e84e7-8bd5-42cc-b5d0-86efbd6a56eb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
User 'a' successfully registered!

" + ], + "text/plain": [ + "SyftSuccess: User 'a' successfully registered!" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "guest_client.register(name=\"a\", email=\"a@b.com\", password=\"c\", password_verify=\"c\")" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "1270cfa4-c771-4e79-8744-6a8276db153d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Logged into as \n" + ] + }, + { + "data": { + "text/html": [ + "
An h1 header\n",
+       "
\n", + "

============

\n", + "

Paragraphs are separated by a blank line.

\n", + "

2nd paragraph. Italic, bold, and monospace. Itemized lists\n", + "look like:

\n", + "
    \n", + "
  • this one
  • \n", + "
  • that one
  • \n", + "
  • the other one
  • \n", + "
\n", + "

Note that --- not considering the asterisk --- the actual text\n", + "content starts at 4-columns in.

\n", + "
\n", + "

Block quotes are\n", + "written like so.

\n", + "

They can span multiple paragraphs,\n", + "if you like.

\n", + "
\n", + "

Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., \"it's all\n", + "in chapters 12--14\"). Three dots ... will be converted to an ellipsis.\n", + "Unicode is supported. ☺

" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "guest_client.login(email=\"a@b.com\", password=\"c\")" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "d8453c72-6095-44c5-82aa-6f11bb71599e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Stopping test-datasite-1\n" + ] + } + ], + "source": [ + "server.land()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3571ba3-709a-4d5b-8e8e-346bf840a19e", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/notebooks/scenarios/getting-started/04-uploading-data.ipynb b/notebooks/scenarios/getting-started/04-uploading-data.ipynb index 1ba607547bb..d6e0dc4ff22 100644 --- a/notebooks/scenarios/getting-started/04-uploading-data.ipynb +++ b/notebooks/scenarios/getting-started/04-uploading-data.ipynb @@ -17,9 +17,8300 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, + "id": "845fd5a5-03aa-44fb-b6aa-532936ffc941", + "metadata": {}, + "outputs": [], + "source": [ + "SYFT_VERSION = \">=0.8.7.b0,<0.9\"\n", + "package_string = f'\"syft{SYFT_VERSION}\"'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "43db561b-b80c-447a-ae85-cc37496a9965", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ The installed version of syft==0.8.7b14 matches the requirement >=0.8.7b0 and the requirement <0.9\n" + ] + } + ], + "source": [ + "# syft absolute\n", + "import syft as sy\n", + "\n", + "sy.requires(SYFT_VERSION)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, "id": "150862d6-0395-4fbb-ad19-9bdae91e33fa", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting test-datasite-1 server on 0.0.0.0:8081\n", + " Done.\n" + ] + }, + { + "data": { + "text/html": [ + "
SyftInfo:
You have launched a development server at http://0.0.0.0:8081.It is intended only for local use.

" + ], + "text/plain": [ + "SyftInfo: You have launched a development server at http://0.0.0.0:8081.It is intended only for local use." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# run a local webserver\n", + "server = sy.orchestra.launch(name=\"test-datasite-1\", port=8081)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "86e27ecb-f661-4fe4-a939-da060d001be2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Logged into as GUEST\n", + "Logged into as \n" + ] + }, + { + "data": { + "text/html": [ + "
SyftWarning:
You are using a default password. Please change the password using `[your_client].me.set_password([new_password])`.

" + ], + "text/plain": [ + "SyftWarning: You are using a default password. Please change the password using `[your_client].me.set_password([new_password])`." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "client = server.login(email=\"info@openmined.org\", password=\"changethis\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e2eeed1f-41d7-4e17-84db-e7897242bcec", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " % Total % Received % Xferd Average Speed Time Time Time Current\n", + " Dload Upload Total Spent Left Speed\n", + "100 157M 100 157M 0 0 2122k 0 0:01:16 0:01:16 --:--:-- 2137k48k 0 0 1694k 0 0:01:35 0:00:05 0:01:30 1921k 0 0:01:40 0:00:10 0:01:30 1516k 0:01:15 2333k 0 0 2257k 0 0:01:11 0:01:01 0:00:10 917k 0 2150k 0 0:01:15 0:01:08 0:00:07 1455k\n" + ] + } + ], + "source": [ + "# stdlib\n", + "import os\n", + "\n", + "if not os.path.exists(\"ages_dataset.csv\"):\n", + " !curl -O https://openminedblob.blob.core.windows.net/csvs/ages_dataset.csv" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "c25ffa3b-6415-4b63-b1ce-7ed3365eeeeb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
IdNameShort descriptionGenderCountryOccupationBirth yearDeath yearManner of deathAge of deathAssociated CountriesAssociated Country Coordinates (Lat/Lon)Associated Country Life Expectancy
0Q23George Washington1st president of the United States (1732–1799)MaleUnited States of America; Kingdom of Great Bri...Politician17321799.0natural causes67.0['United Kingdom', 'United States'][(55.378051, -3.435973), (37.09024, -95.712891)][81.3, 78.5]
1Q42Douglas AdamsEnglish writer and humoristMaleUnited KingdomArtist19522001.0natural causes49.0['United Kingdom'][(55.378051, -3.435973)][81.3]
2Q91Abraham Lincoln16th president of the United States (1809-1865)MaleUnited States of AmericaPolitician18091865.0homicide56.0['United States'][(37.09024, -95.712891)][78.5]
5Q260Jean-François ChampollionFrench classical scholarMaleKingdom of France; First French EmpireEgyptologist17901832.0natural causes42.0['France'][(46.227638, 2.213749)][82.5]
7Q296Claude MonetFrench impressionist painter (1840-1926)MaleFranceArtist18401926.0natural causes86.0['France'][(46.227638, 2.213749)][82.5]
\n", + "
" + ], + "text/plain": [ + " Id Name \\\n", + "0 Q23 George Washington \n", + "1 Q42 Douglas Adams \n", + "2 Q91 Abraham Lincoln \n", + "5 Q260 Jean-François Champollion \n", + "7 Q296 Claude Monet \n", + "\n", + " Short description Gender \\\n", + "0 1st president of the United States (1732–1799) Male \n", + "1 English writer and humorist Male \n", + "2 16th president of the United States (1809-1865) Male \n", + "5 French classical scholar Male \n", + "7 French impressionist painter (1840-1926) Male \n", + "\n", + " Country Occupation \\\n", + "0 United States of America; Kingdom of Great Bri... Politician \n", + "1 United Kingdom Artist \n", + "2 United States of America Politician \n", + "5 Kingdom of France; First French Empire Egyptologist \n", + "7 France Artist \n", + "\n", + " Birth year Death year Manner of death Age of death \\\n", + "0 1732 1799.0 natural causes 67.0 \n", + "1 1952 2001.0 natural causes 49.0 \n", + "2 1809 1865.0 homicide 56.0 \n", + "5 1790 1832.0 natural causes 42.0 \n", + "7 1840 1926.0 natural causes 86.0 \n", + "\n", + " Associated Countries \\\n", + "0 ['United Kingdom', 'United States'] \n", + "1 ['United Kingdom'] \n", + "2 ['United States'] \n", + "5 ['France'] \n", + "7 ['France'] \n", + "\n", + " Associated Country Coordinates (Lat/Lon) \\\n", + "0 [(55.378051, -3.435973), (37.09024, -95.712891)] \n", + "1 [(55.378051, -3.435973)] \n", + "2 [(37.09024, -95.712891)] \n", + "5 [(46.227638, 2.213749)] \n", + "7 [(46.227638, 2.213749)] \n", + "\n", + " Associated Country Life Expectancy \n", + "0 [81.3, 78.5] \n", + "1 [81.3] \n", + "2 [78.5] \n", + "5 [82.5] \n", + "7 [82.5] " + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# third party\n", + "import pandas as pd\n", + "\n", + "# syft absolute\n", + "import syft as sy\n", + "\n", + "age_df = pd.read_csv(\"ages_dataset.csv\")\n", + "age_df = age_df.dropna(how=\"any\")\n", + "age_df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "b0fdc5b3-2cc5-4084-8904-525079b7fe00", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " % Total % Received % Xferd Average Speed Time Time Time Current\n", + " Dload Upload Total Spent Left Speed\n", + "100 8217k 100 8217k 0 0 1501k 0 0:00:05 0:00:05 --:--:-- 1671k\n" + ] + } + ], + "source": [ + "# stdlib\n", + "# TODO: also move to dataset repo\n", + "import os\n", + "\n", + "if not os.path.exists(\"ages_mock_dataset.csv\"):\n", + " !curl -O https://openminedblob.blob.core.windows.net/csvs/ages_mock_dataset.csv" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "0e130662-73f4-43a4-afb6-c6ecc107c5a7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
IdGenderAge of deathAssociated CountriesAssociated Country Life ExpectancyManner of deathNameShort descriptionOccupationDeath yearBirth yearCountryAssociated Country Coordinates (Lat/Lon)
0Q19723Gender 153.0['United States'][78.5]homicideNorma FisherMagazine truth stop whose group through despite.Corporate treasurer1989.01936Not AvailableNot Available
1Q20057Gender 151.0['United Kingdom'][81.3]natural causesBrandon LloydTotal financial role together range line beyon...Chief Financial Officer2018.01967Not AvailableNot Available
2Q8791Gender 184.0['Sweden'][82.5]natural causesMichelle GloverPartner stock four. Region as true develop sou...Speech and language therapist2000.01916Not AvailableNot Available
3Q30567Gender 164.0['Belgium'][81.6]natural causesWillie GoldenFeeling fact by four. Data son natural explain...Financial controller1989.01925Not AvailableNot Available
4Q14013Gender 188.0['United Kingdom'][81.3]suicideRoberto JohnsonAttorney quickly candidate change although bag...Sound technician, broadcasting/film/video2016.01928Not AvailableNot Available
\n", + "
" + ], + "text/plain": [ + " Id Gender Age of death Associated Countries \\\n", + "0 Q19723 Gender 1 53.0 ['United States'] \n", + "1 Q20057 Gender 1 51.0 ['United Kingdom'] \n", + "2 Q8791 Gender 1 84.0 ['Sweden'] \n", + "3 Q30567 Gender 1 64.0 ['Belgium'] \n", + "4 Q14013 Gender 1 88.0 ['United Kingdom'] \n", + "\n", + " Associated Country Life Expectancy Manner of death Name \\\n", + "0 [78.5] homicide Norma Fisher \n", + "1 [81.3] natural causes Brandon Lloyd \n", + "2 [82.5] natural causes Michelle Glover \n", + "3 [81.6] natural causes Willie Golden \n", + "4 [81.3] suicide Roberto Johnson \n", + "\n", + " Short description \\\n", + "0 Magazine truth stop whose group through despite. \n", + "1 Total financial role together range line beyon... \n", + "2 Partner stock four. Region as true develop sou... \n", + "3 Feeling fact by four. Data son natural explain... \n", + "4 Attorney quickly candidate change although bag... \n", + "\n", + " Occupation Death year Birth year \\\n", + "0 Corporate treasurer 1989.0 1936 \n", + "1 Chief Financial Officer 2018.0 1967 \n", + "2 Speech and language therapist 2000.0 1916 \n", + "3 Financial controller 1989.0 1925 \n", + "4 Sound technician, broadcasting/film/video 2016.0 1928 \n", + "\n", + " Country Associated Country Coordinates (Lat/Lon) \n", + "0 Not Available Not Available \n", + "1 Not Available Not Available \n", + "2 Not Available Not Available \n", + "3 Not Available Not Available \n", + "4 Not Available Not Available " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "age_mock_df = pd.read_csv(\"ages_mock_dataset.csv\")\n", + "age_mock_df = age_mock_df.dropna(how=\"any\")\n", + "age_mock_df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "0bbc6868-d66c-4a96-ad39-fb340e7037b3", + "metadata": {}, + "outputs": [], + "source": [ + "# How an asset for low side and high-side would be defined:\n", + "main_contributor = sy.Contributor(\n", + " name=\"Jeffrey Salazar\", role=\"Dataset Creator\", email=\"jsala@ailab.com\"\n", + ")\n", + "\n", + "asset = sy.Asset(\n", + " name=\"asset_name\",\n", + " data=age_df, # real dataframe\n", + " mock=age_mock_df, # mock dataframe\n", + " contributors=[main_contributor],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "43474e47-20dd-437a-9b16-324831f692f4", + "metadata": {}, + "outputs": [], + "source": [ + "description_template = \"\"\"### About the dataset\n", + "This extensive dataset provides a rich collection of demographic and life events records for individuals across multiple countries. It covers a wide range of indicators and attributes related to personal information, birth and death events, gender, occupation, and associated countries. The dataset offers valuable insights into population dynamics and various aspects of human life, enabling comprehensive analyses and cross-country comparisons. The dataset is the largest one on notable deceased people and includes individ- uals from a variety of social groups, including but not limited to 107k females, 90k researchers, and 124 non-binary indi- viduals, spread across more than 300 contemporary or histor- ical regions.\n", + "\n", + "### Dataset usage policy\n", + "This dataset is subject to compliance with internal data use and mis-use policies at our organisation. The following rules apply:\n", + "- only aggregate statistics can be released from data computation\n", + "- data subjects should never be identifiable through the data computation outcomes\n", + "- a fixed privacy budget of eps=5 must be preserved by each researcher\n", + "\n", + "### Data collection and pre-processing\n", + "The dataset is based on open data hosted by Wikimedia Foundation.\n", + "\n", + "**Age**\n", + "Whenever possible, age was calculated based on the birth and death year mentioned in the description of the individual.\n", + "\n", + "**Gender**\n", + "Gender was available in the original dataset for 50% of participants. For the remaining, it was added from predictions based on name, country and century in which they lived. (97.51% accuracy and 98.89% F1-score)\n", + "\n", + "**Occupation**\n", + "The occupation was available in the original dataset for 66% of the individuals. For the remaining, it was added from predictions from a multiclass text classificator model. (93.4% accuracy for 84% of the dataset)\n", + "\n", + "More details about the features can be found by reading the paper.\n", + "\n", + "### Key features\n", + "1. **Id**: Unique identifier for each individual.\n", + "2. **Name**: Name of the person.\n", + "3. **Short description**: Brief description or summary of the individual.\n", + "4. **Gender**: Gender/s of the individual.\n", + "5. **Country**: Countries/Kingdoms of residence and/or origin.\n", + "6. **Occupation**: Occupation or profession of the individual.\n", + "7. **Birth year**: Year of birth for the individual.\n", + "8. **Death year**: Year of death for the individual.\n", + "9. **Manner of death**: Details about the circumstances or manner of death.\n", + "10. **Age of death**: Age at the time of death for the individual.\n", + "11. **Associated Countries**: Modern Day Countries associated with the individual.\n", + "12. **Associated Country Coordinates (Lat/Lon)**: Modern Day Latitude and longitude coordinates of the associated countries.\n", + "13. **Associated Country Life Expectancy**: Life expectancy of the associated countries.\n", + "\n", + "### Use cases\n", + "- Analyze demographic trends and birth rates in different countries.\n", + "- Investigate factors affecting life expectancy and mortality rates.\n", + "- Study the relationship between gender and occupation across regions.\n", + "- Explore correlations between age of death and associated country attributes.\n", + "- Examine patterns of migration and associated countries' life expectancy.\n", + "\n", + "\n", + "### Getting started\n", + "\n", + "```\n", + "!curl -O https://openminedblob.blob.core.windows.net/csvs/ages_dataset.csv\n", + "\n", + "age_df = pd.read_csv(\"ages_dataset.csv\")\n", + "```\n", + "\n", + "### Execution environment\n", + "The data is hosted in a remote compute environment with the following specifications:\n", + "- X CPU cores\n", + "- 1 GPU of type Y\n", + "- Z RAM\n", + "- A additional available storage\n", + "\n", + "### Citation\n", + "Annamoradnejad, Issa; Annamoradnejad, Rahimberdi (2022), “Age dataset: A structured general-purpose dataset on life, work, and death of 1.22 million distinguished people”, In Workshop Proceedings of the 16th International AAAI Conference on Web and Social Media (ICWSM), doi: 10.36190/2022.82\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "ebfed140-db5b-4bd1-886a-dabeb52dbe9a", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = sy.Dataset(\n", + " name=\"Dataset name\",\n", + " description=description_template,\n", + " asset_list=[asset],\n", + " contributors=[main_contributor],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6901ddcc-b72a-4e79-9071-a47531ff4eba", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "18b4056a-260e-4d61-9333-c2a2d3e50f21", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Uploading: asset_name: 100%|\u001b[32m████████████████\u001b[0m| 1/1 [00:00<00:00, 1.35it/s]\u001b[0m\n" + ] + }, + { + "data": { + "text/html": [ + "
SyftSuccess:
Dataset uploaded to 'a'. To see the datasets uploaded by a client on this server, use command `[your_client].datasets`

" + ], + "text/plain": [ + "SyftSuccess: Dataset uploaded to 'a'. To see the datasets uploaded by a client on this server, use command `[your_client].datasets`" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Uploading the dataset\n", + "client.upload_dataset(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "0ade7507-77f7-450b-9b59-a34bad501609", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "

Dataset Dicttuple

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

Total: 0

\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.datasets" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "f19c0bc1-1466-4002-a23e-1f3afdd84f25", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + "
\n", + "

Dataset name

\n", + "

Summary

\n", + " \n", + " \n", + "

Description

\n", + "

About the dataset

\n", + "

This extensive dataset provides a rich collection of demographic and life events records for individuals across multiple countries. It covers a wide range of indicators and attributes related to personal information, birth and death events, gender, occupation, and associated countries. The dataset offers valuable insights into population dynamics and various aspects of human life, enabling comprehensive analyses and cross-country comparisons. The dataset is the largest one on notable deceased people and includes individ- uals from a variety of social groups, including but not limited to 107k females, 90k researchers, and 124 non-binary indi- viduals, spread across more than 300 contemporary or histor- ical regions.

\n", + "

Dataset usage policy

\n", + "

This dataset is subject to compliance with internal data use and mis-use policies at our organisation. The following rules apply:\n", + "- only aggregate statistics can be released from data computation\n", + "- data subjects should never be identifiable through the data computation outcomes\n", + "- a fixed privacy budget of eps=5 must be preserved by each researcher

\n", + "

Data collection and pre-processing

\n", + "

The dataset is based on open data hosted by Wikimedia Foundation.

\n", + "

Age\n", + "Whenever possible, age was calculated based on the birth and death year mentioned in the description of the individual.

\n", + "

Gender\n", + "Gender was available in the original dataset for 50% of participants. For the remaining, it was added from predictions based on name, country and century in which they lived. (97.51% accuracy and 98.89% F1-score)

\n", + "

Occupation\n", + "The occupation was available in the original dataset for 66% of the individuals. For the remaining, it was added from predictions from a multiclass text classificator model. (93.4% accuracy for 84% of the dataset)

\n", + "

More details about the features can be found by reading the paper.

\n", + "

Key features

\n", + "
    \n", + "
  1. Id: Unique identifier for each individual.
  2. \n", + "
  3. Name: Name of the person.
  4. \n", + "
  5. Short description: Brief description or summary of the individual.
  6. \n", + "
  7. Gender: Gender/s of the individual.
  8. \n", + "
  9. Country: Countries/Kingdoms of residence and/or origin.
  10. \n", + "
  11. Occupation: Occupation or profession of the individual.
  12. \n", + "
  13. Birth year: Year of birth for the individual.
  14. \n", + "
  15. Death year: Year of death for the individual.
  16. \n", + "
  17. Manner of death: Details about the circumstances or manner of death.
  18. \n", + "
  19. Age of death: Age at the time of death for the individual.
  20. \n", + "
  21. Associated Countries: Modern Day Countries associated with the individual.
  22. \n", + "
  23. Associated Country Coordinates (Lat/Lon): Modern Day Latitude and longitude coordinates of the associated countries.
  24. \n", + "
  25. Associated Country Life Expectancy: Life expectancy of the associated countries.
  26. \n", + "
\n", + "

Use cases

\n", + "
    \n", + "
  • Analyze demographic trends and birth rates in different countries.
  • \n", + "
  • Investigate factors affecting life expectancy and mortality rates.
  • \n", + "
  • Study the relationship between gender and occupation across regions.
  • \n", + "
  • Explore correlations between age of death and associated country attributes.
  • \n", + "
  • Examine patterns of migration and associated countries' life expectancy.
  • \n", + "
\n", + "

Getting started

\n", + "
!curl -O https://openminedblob.blob.core.windows.net/csvs/ages_dataset.csv\n",
+       "\n",
+       "age_df = pd.read_csv(\"ages_dataset.csv\")\n",
+       "
\n", + "

Execution environment

\n", + "

The data is hosted in a remote compute environment with the following specifications:\n", + "- X CPU cores\n", + "- 1 GPU of type Y\n", + "- Z RAM\n", + "- A additional available storage

\n", + "

Citation

\n", + "

Annamoradnejad, Issa; Annamoradnejad, Rahimberdi (2022), “Age dataset: A structured general-purpose dataset on life, work, and death of 1.22 million distinguished people”, In Workshop Proceedings of the 16th International AAAI Conference on Web and Social Media (ICWSM), doi: 10.36190/2022.82

\n", + " \n", + "

Dataset Details

\n", + "

Uploaded by: Jane Doe (info@openmined.org)

\n", + "

Created on: 2024-07-14 20:58:44

\n", + "

URL:\n", + " None

\n", + "

Contributors:\n", + " To see full details call dataset.contributors.

\n", + "

Assets

\n", + " \n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "

Asset Dicttuple

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

Total: 0

\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "" + ], + "text/markdown": [ + "Syft Dataset: Dataset name\n", + "\n", + "Assets:\n", + "\n", + "\tasset_name\n", + "\n", + "Description: \n", + "\n", + "### About the dataset\n", + "This extensive dataset provides a rich collection of demographic and life events records for individuals across multiple countries. It covers a wide range of indicators and attributes related to personal information, birth and death events, gender, occupation, and associated countries. The dataset offers valuable insights into population dynamics and various aspects of human life, enabling comprehensive analyses and cross-country comparisons. The dataset is the largest one on notable deceased people and includes individ- uals from a variety of social groups, including but not limited to 107k females, 90k researchers, and 124 non-binary indi- viduals, spread across more than 300 contemporary or histor- ical regions.\n", + "\n", + "### Dataset usage policy\n", + "This dataset is subject to compliance with internal data use and mis-use policies at our organisation. The following rules apply:\n", + "- only aggregate statistics can be released from data computation\n", + "- data subjects should never be identifiable through the data computation outcomes\n", + "- a fixed privacy budget of eps=5 must be preserved by each researcher\n", + "\n", + "### Data collection and pre-processing\n", + "The dataset is based on open data hosted by Wikimedia Foundation.\n", + "\n", + "**Age**\n", + "Whenever possible, age was calculated based on the birth and death year mentioned in the description of the individual.\n", + "\n", + "**Gender**\n", + "Gender was available in the original dataset for 50% of participants. For the remaining, it was added from predictions based on name, country and century in which they lived. (97.51% accuracy and 98.89% F1-score)\n", + "\n", + "**Occupation**\n", + "The occupation was available in the original dataset for 66% of the individuals. For the remaining, it was added from predictions from a multiclass text classificator model. (93.4% accuracy for 84% of the dataset)\n", + "\n", + "More details about the features can be found by reading the paper.\n", + "\n", + "### Key features\n", + "1. **Id**: Unique identifier for each individual.\n", + "2. **Name**: Name of the person.\n", + "3. **Short description**: Brief description or summary of the individual.\n", + "4. **Gender**: Gender/s of the individual.\n", + "5. **Country**: Countries/Kingdoms of residence and/or origin.\n", + "6. **Occupation**: Occupation or profession of the individual.\n", + "7. **Birth year**: Year of birth for the individual.\n", + "8. **Death year**: Year of death for the individual.\n", + "9. **Manner of death**: Details about the circumstances or manner of death.\n", + "10. **Age of death**: Age at the time of death for the individual.\n", + "11. **Associated Countries**: Modern Day Countries associated with the individual.\n", + "12. **Associated Country Coordinates (Lat/Lon)**: Modern Day Latitude and longitude coordinates of the associated countries.\n", + "13. **Associated Country Life Expectancy**: Life expectancy of the associated countries.\n", + "\n", + "### Use cases\n", + "- Analyze demographic trends and birth rates in different countries.\n", + "- Investigate factors affecting life expectancy and mortality rates.\n", + "- Study the relationship between gender and occupation across regions.\n", + "- Explore correlations between age of death and associated country attributes.\n", + "- Examine patterns of migration and associated countries' life expectancy.\n", + "\n", + "\n", + "### Getting started\n", + "\n", + "```\n", + "!curl -O https://openminedblob.blob.core.windows.net/csvs/ages_dataset.csv\n", + "\n", + "age_df = pd.read_csv(\"ages_dataset.csv\")\n", + "```\n", + "\n", + "### Execution environment\n", + "The data is hosted in a remote compute environment with the following specifications:\n", + "- X CPU cores\n", + "- 1 GPU of type Y\n", + "- Z RAM\n", + "- A additional available storage\n", + "\n", + "### Citation\n", + "Annamoradnejad, Issa; Annamoradnejad, Rahimberdi (2022), “Age dataset: A structured general-purpose dataset on life, work, and death of 1.22 million distinguished people”, In Workshop Proceedings of the 16th International AAAI Conference on Web and Social Media (ICWSM), doi: 10.36190/2022.82\n", + "\n", + "\n" + ], + "text/plain": [ + "syft.service.dataset.dataset.Dataset" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d = client.datasets[0]\n", + "d" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "43e920d4-b400-4551-b4c2-a78b92f7f892", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + "\n", + "
\n", + "

asset_name

\n", + "

None

\n", + "

Asset ID: c8b177dd01d74fc4bde31cdcf3bafcc6

\n", + "

Action Object ID: 61d18e2bd00c4f4f8a284a4ddb2acbe0

\n", + "

Uploaded by: Jane Doe (info@openmined.org)

\n", + "

Created on: 2024-07-14 20:58:44

\n", + "

Data:

\n", + "
\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
IdNameShort descriptionGenderCountryOccupationBirth yearDeath yearManner of deathAge of deathAssociated CountriesAssociated Country Coordinates (Lat/Lon)Associated Country Life Expectancy
Loading... (need help?)
\n", + "\n", + "\n", + "
\n", + "\n", + "

Mock Data:

\n", + "
\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
IdGenderAge of deathAssociated CountriesAssociated Country Life ExpectancyManner of deathNameShort descriptionOccupationDeath yearBirth yearCountryAssociated Country Coordinates (Lat/Lon)
Loading... (need help?)
\n", + "\n", + "\n", + "
\n", + "\n", + "
" + ], + "text/markdown": [ + "```python\n", + "Asset: asset_name\n", + "Pointer Id: 61d18e2bd00c4f4f8a284a4ddb2acbe0\n", + "Description: None\n", + "Total Data Subjects: 0\n", + "Shape: (44211, 13)\n", + "Contributors: 2\n", + "\tJane Doe: info@openmined.org\n", + "\tJeffrey Salazar: jsala@ailab.com\n", + "\n", + "```" + ], + "text/plain": [ + "Asset(name='asset_name', server_uid='2baa8fe9deb94b6ead87ea7be4cb230e', action_id='61d18e2bd00c4f4f8a284a4ddb2acbe0')" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = d.assets[0]\n", + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "86eb6f5c-ac2e-4dee-bac7-dcaa0dd972cf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
IdGenderAge of deathAssociated CountriesAssociated Country Life ExpectancyManner of deathNameShort descriptionOccupationDeath yearBirth yearCountryAssociated Country Coordinates (Lat/Lon)
0Q19723Gender 153.0['United States'][78.5]homicideNorma FisherMagazine truth stop whose group through despite.Corporate treasurer1989.01936Not AvailableNot Available
1Q20057Gender 151.0['United Kingdom'][81.3]natural causesBrandon LloydTotal financial role together range line beyon...Chief Financial Officer2018.01967Not AvailableNot Available
2Q8791Gender 184.0['Sweden'][82.5]natural causesMichelle GloverPartner stock four. Region as true develop sou...Speech and language therapist2000.01916Not AvailableNot Available
3Q30567Gender 164.0['Belgium'][81.6]natural causesWillie GoldenFeeling fact by four. Data son natural explain...Financial controller1989.01925Not AvailableNot Available
4Q14013Gender 188.0['United Kingdom'][81.3]suicideRoberto JohnsonAttorney quickly candidate change although bag...Sound technician, broadcasting/film/video2016.01928Not AvailableNot Available
..........................................
44206Q21223Gender 187.0['United States'][78.5]natural causesSteven HillOccur site mean. None imagine social collectio...Television/film/video producer2014.01927Not AvailableNot Available
44207Q18681Gender 175.0['Austria'][81.6]natural causesLaura SmithFive help event as sort. Class training possib...Race relations officer2018.01943Not AvailableNot Available
44208Q34424Gender 156.0['France'][82.5]natural causesDiana JacobsMiddle style capital describe increase. Fly si...Civil Service fast streamer2009.01953Not AvailableNot Available
44209Q33102Gender 175.0['France'][82.5]natural causesLarry FosterWatch size character piece speak moment outsid...Speech and language therapist1982.01907Not AvailableNot Available
44210Q34422Gender 163.0['Poland'][77.6]unnatural deathThomas GonzalesFact thousand week professional.Biochemist, clinical2005.01942Not AvailableNot Available
\n", + "

44211 rows × 13 columns

\n", + "
" + ], + "text/plain": [ + " Id Gender Age of death Associated Countries \\\n", + "0 Q19723 Gender 1 53.0 ['United States'] \n", + "1 Q20057 Gender 1 51.0 ['United Kingdom'] \n", + "2 Q8791 Gender 1 84.0 ['Sweden'] \n", + "3 Q30567 Gender 1 64.0 ['Belgium'] \n", + "4 Q14013 Gender 1 88.0 ['United Kingdom'] \n", + "... ... ... ... ... \n", + "44206 Q21223 Gender 1 87.0 ['United States'] \n", + "44207 Q18681 Gender 1 75.0 ['Austria'] \n", + "44208 Q34424 Gender 1 56.0 ['France'] \n", + "44209 Q33102 Gender 1 75.0 ['France'] \n", + "44210 Q34422 Gender 1 63.0 ['Poland'] \n", + "\n", + " Associated Country Life Expectancy Manner of death Name \\\n", + "0 [78.5] homicide Norma Fisher \n", + "1 [81.3] natural causes Brandon Lloyd \n", + "2 [82.5] natural causes Michelle Glover \n", + "3 [81.6] natural causes Willie Golden \n", + "4 [81.3] suicide Roberto Johnson \n", + "... ... ... ... \n", + "44206 [78.5] natural causes Steven Hill \n", + "44207 [81.6] natural causes Laura Smith \n", + "44208 [82.5] natural causes Diana Jacobs \n", + "44209 [82.5] natural causes Larry Foster \n", + "44210 [77.6] unnatural death Thomas Gonzales \n", + "\n", + " Short description \\\n", + "0 Magazine truth stop whose group through despite. \n", + "1 Total financial role together range line beyon... \n", + "2 Partner stock four. Region as true develop sou... \n", + "3 Feeling fact by four. Data son natural explain... \n", + "4 Attorney quickly candidate change although bag... \n", + "... ... \n", + "44206 Occur site mean. None imagine social collectio... \n", + "44207 Five help event as sort. Class training possib... \n", + "44208 Middle style capital describe increase. Fly si... \n", + "44209 Watch size character piece speak moment outsid... \n", + "44210 Fact thousand week professional. \n", + "\n", + " Occupation Death year Birth year \\\n", + "0 Corporate treasurer 1989.0 1936 \n", + "1 Chief Financial Officer 2018.0 1967 \n", + "2 Speech and language therapist 2000.0 1916 \n", + "3 Financial controller 1989.0 1925 \n", + "4 Sound technician, broadcasting/film/video 2016.0 1928 \n", + "... ... ... ... \n", + "44206 Television/film/video producer 2014.0 1927 \n", + "44207 Race relations officer 2018.0 1943 \n", + "44208 Civil Service fast streamer 2009.0 1953 \n", + "44209 Speech and language therapist 1982.0 1907 \n", + "44210 Biochemist, clinical 2005.0 1942 \n", + "\n", + " Country Associated Country Coordinates (Lat/Lon) \n", + "0 Not Available Not Available \n", + "1 Not Available Not Available \n", + "2 Not Available Not Available \n", + "3 Not Available Not Available \n", + "4 Not Available Not Available \n", + "... ... ... \n", + "44206 Not Available Not Available \n", + "44207 Not Available Not Available \n", + "44208 Not Available Not Available \n", + "44209 Not Available Not Available \n", + "44210 Not Available Not Available \n", + "\n", + "[44211 rows x 13 columns]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.mock" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "2fdd319f-8c51-4203-82f1-fbf29ad5d614", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
IdNameShort descriptionGenderCountryOccupationBirth yearDeath yearManner of deathAge of deathAssociated CountriesAssociated Country Coordinates (Lat/Lon)Associated Country Life Expectancy
0Q23George Washington1st president of the United States (1732–1799)MaleUnited States of America; Kingdom of Great Bri...Politician17321799.0natural causes67.0['United Kingdom', 'United States'][(55.378051, -3.435973), (37.09024, -95.712891)][81.3, 78.5]
1Q42Douglas AdamsEnglish writer and humoristMaleUnited KingdomArtist19522001.0natural causes49.0['United Kingdom'][(55.378051, -3.435973)][81.3]
2Q91Abraham Lincoln16th president of the United States (1809-1865)MaleUnited States of AmericaPolitician18091865.0homicide56.0['United States'][(37.09024, -95.712891)][78.5]
5Q260Jean-François ChampollionFrench classical scholarMaleKingdom of France; First French EmpireEgyptologist17901832.0natural causes42.0['France'][(46.227638, 2.213749)][82.5]
7Q296Claude MonetFrench impressionist painter (1840-1926)MaleFranceArtist18401926.0natural causes86.0['France'][(46.227638, 2.213749)][82.5]
..........................................
1215502Q75349931John SaxtonBritish diarist and settler in New ZealandMaleUnited Kingdom of Great Britain and IrelandSettler18071866.0suicide59.0['United Kingdom'][(55.378051, -3.435973)][81.3]
1217919Q75717629Antonín GrunclCzechoslovak musicianMaleCzechoslovakiaArtist19051942.0capital punishment37.0['Slovakia'][(48.669026, 19.699024)][77.2]
1221308Q76161186Sara ChampionBritish archaeologistFemaleUnited KingdomResearcher19462000.0natural causes54.0['United Kingdom'][(55.378051, -3.435973)][81.3]
1222916Q76857201Dolores Millanesbaaŋa ŋun nyɛ paɣaFemaleSpainArtist18591906.0shipwrecking47.0['Spain'][(40.463667, -3.74922)][83.3]
1222958Q76995470David Hillhouse BuelUnion Army officerMaleUnited States of AmericaMilitary personnel18391870.0homicide31.0['United States'][(37.09024, -95.712891)][78.5]
\n", + "

44211 rows × 13 columns

\n", + "
" + ], + "text/plain": [ + " Id Name \\\n", + "0 Q23 George Washington \n", + "1 Q42 Douglas Adams \n", + "2 Q91 Abraham Lincoln \n", + "5 Q260 Jean-François Champollion \n", + "7 Q296 Claude Monet \n", + "... ... ... \n", + "1215502 Q75349931 John Saxton \n", + "1217919 Q75717629 Antonín Gruncl \n", + "1221308 Q76161186 Sara Champion \n", + "1222916 Q76857201 Dolores Millanes \n", + "1222958 Q76995470 David Hillhouse Buel \n", + "\n", + " Short description Gender \\\n", + "0 1st president of the United States (1732–1799) Male \n", + "1 English writer and humorist Male \n", + "2 16th president of the United States (1809-1865) Male \n", + "5 French classical scholar Male \n", + "7 French impressionist painter (1840-1926) Male \n", + "... ... ... \n", + "1215502 British diarist and settler in New Zealand Male \n", + "1217919 Czechoslovak musician Male \n", + "1221308 British archaeologist Female \n", + "1222916 baaŋa ŋun nyɛ paɣa Female \n", + "1222958 Union Army officer Male \n", + "\n", + " Country \\\n", + "0 United States of America; Kingdom of Great Bri... \n", + "1 United Kingdom \n", + "2 United States of America \n", + "5 Kingdom of France; First French Empire \n", + "7 France \n", + "... ... \n", + "1215502 United Kingdom of Great Britain and Ireland \n", + "1217919 Czechoslovakia \n", + "1221308 United Kingdom \n", + "1222916 Spain \n", + "1222958 United States of America \n", + "\n", + " Occupation Birth year Death year Manner of death \\\n", + "0 Politician 1732 1799.0 natural causes \n", + "1 Artist 1952 2001.0 natural causes \n", + "2 Politician 1809 1865.0 homicide \n", + "5 Egyptologist 1790 1832.0 natural causes \n", + "7 Artist 1840 1926.0 natural causes \n", + "... ... ... ... ... \n", + "1215502 Settler 1807 1866.0 suicide \n", + "1217919 Artist 1905 1942.0 capital punishment \n", + "1221308 Researcher 1946 2000.0 natural causes \n", + "1222916 Artist 1859 1906.0 shipwrecking \n", + "1222958 Military personnel 1839 1870.0 homicide \n", + "\n", + " Age of death Associated Countries \\\n", + "0 67.0 ['United Kingdom', 'United States'] \n", + "1 49.0 ['United Kingdom'] \n", + "2 56.0 ['United States'] \n", + "5 42.0 ['France'] \n", + "7 86.0 ['France'] \n", + "... ... ... \n", + "1215502 59.0 ['United Kingdom'] \n", + "1217919 37.0 ['Slovakia'] \n", + "1221308 54.0 ['United Kingdom'] \n", + "1222916 47.0 ['Spain'] \n", + "1222958 31.0 ['United States'] \n", + "\n", + " Associated Country Coordinates (Lat/Lon) \\\n", + "0 [(55.378051, -3.435973), (37.09024, -95.712891)] \n", + "1 [(55.378051, -3.435973)] \n", + "2 [(37.09024, -95.712891)] \n", + "5 [(46.227638, 2.213749)] \n", + "7 [(46.227638, 2.213749)] \n", + "... ... \n", + "1215502 [(55.378051, -3.435973)] \n", + "1217919 [(48.669026, 19.699024)] \n", + "1221308 [(55.378051, -3.435973)] \n", + "1222916 [(40.463667, -3.74922)] \n", + "1222958 [(37.09024, -95.712891)] \n", + "\n", + " Associated Country Life Expectancy \n", + "0 [81.3, 78.5] \n", + "1 [81.3] \n", + "2 [78.5] \n", + "5 [82.5] \n", + "7 [82.5] \n", + "... ... \n", + "1215502 [81.3] \n", + "1217919 [77.2] \n", + "1221308 [81.3] \n", + "1222916 [83.3] \n", + "1222958 [78.5] \n", + "\n", + "[44211 rows x 13 columns]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5aff9d42-9241-48f1-85c6-8a0dbc4ab83a", + "metadata": {}, "outputs": [], "source": [] } diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index 2cd91e5aefa..d61d8de882f 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -84,6 +84,7 @@ from .util.patch_ipython import patch_ipython from .util.telemetry import instrument from .util.util import autocache +from .util.util import get_nb_secrets from .util.util import get_root_data_path from .util.version_compare import make_requires diff --git a/packages/syft/src/syft/orchestra.py b/packages/syft/src/syft/orchestra.py index 8acc07ac3f4..eb17bcea483 100644 --- a/packages/syft/src/syft/orchestra.py +++ b/packages/syft/src/syft/orchestra.py @@ -210,7 +210,14 @@ def deploy_to_python( kwargs["in_memory_workers"] = True if port == "auto": port = get_random_available_port() - kwargs["port"] = port + else: + try: + port = int(port) + except ValueError: + raise ValueError( + f"port must be either 'auto' or a valid int not: {port}" + ) + kwargs["port"] = port sig = inspect.signature(serve_server) supported_kwargs = {k: v for k, v in kwargs.items() if k in sig.parameters} diff --git a/packages/syft/src/syft/service/action/action_object.py b/packages/syft/src/syft/service/action/action_object.py index 318d81bec2c..521e0a7117f 100644 --- a/packages/syft/src/syft/service/action/action_object.py +++ b/packages/syft/src/syft/service/action/action_object.py @@ -828,7 +828,9 @@ def reload_cache(self) -> SyftError | None: self.syft_action_data_type = type(self.syft_action_data) return None else: - return SyftError("Could not reload cache, could not get read method") + return SyftError( + message="Could not reload cache, could not get read method" + ) return None diff --git a/packages/syft/src/syft/service/code/user_code.py b/packages/syft/src/syft/service/code/user_code.py index 299c80a47c4..a52da7ce217 100644 --- a/packages/syft/src/syft/service/code/user_code.py +++ b/packages/syft/src/syft/service/code/user_code.py @@ -862,7 +862,7 @@ def wrapper(*args: Any, **kwargs: Any) -> Callable | SyftError: # return the results return result except Exception as e: - return SyftError(f"Failed to execute 'run'. Error: {e}") + return SyftError(message=f"Failed to execute 'run'. Error: {e}") return wrapper diff --git a/packages/syft/src/syft/service/code/user_code_service.py b/packages/syft/src/syft/service/code/user_code_service.py index 05cba51a6b8..89456b2bf6f 100644 --- a/packages/syft/src/syft/service/code/user_code_service.py +++ b/packages/syft/src/syft/service/code/user_code_service.py @@ -379,7 +379,7 @@ def is_execution_allowed( elif not (has_code_permission := self.has_code_permission(code, context)): return has_code_permission elif not code.is_output_policy_approved(context): - return SyftError("Output policy not approved", code) + return SyftError(message=f"Output policy not approved. {code}") policy_is_valid = output_policy is not None and output_policy._is_valid(context) if not policy_is_valid: diff --git a/packages/syft/src/syft/util/util.py b/packages/syft/src/syft/util/util.py index d4a98d91e07..43620c4cab5 100644 --- a/packages/syft/src/syft/util/util.py +++ b/packages/syft/src/syft/util/util.py @@ -996,3 +996,18 @@ def get_latest_tag(registry: str, repo: str) -> str | None: if len(tag_times) > 0: return tag_times[0][0] return None + + +def get_nb_secrets(defaults: dict | None = None) -> dict: + if defaults is None: + defaults = {} + + try: + filename = "./secrets.json" + with open(filename) as f: + loaded = json.loads(f.read()) + defaults.update(loaded) + except Exception: + print(f"Unable to load {filename}") + + return defaults From ebd4854ddbcadaae0be9d1a5dc1104161f664c1e Mon Sep 17 00:00:00 2001 From: Madhava Jay Date: Tue, 9 Jul 2024 12:51:00 +1000 Subject: [PATCH 059/117] Updated tests for user autosplat --- packages/syft/src/syft/service/user/user.py | 8 ++--- packages/syft/tests/syft/api_test.py | 6 ++-- .../tests/syft/service_permission_test.py | 6 ++-- .../syft/settings/settings_service_test.py | 2 +- .../tests/syft/users/user_service_test.py | 22 +++++--------- packages/syft/tests/syft/users/user_test.py | 29 +++++++------------ packages/syft/tests/syft/worker_test.py | 2 +- 7 files changed, 29 insertions(+), 46 deletions(-) diff --git a/packages/syft/src/syft/service/user/user.py b/packages/syft/src/syft/service/user/user.py index 42bf7bad9d5..886c5ffa678 100644 --- a/packages/syft/src/syft/service/user/user.py +++ b/packages/syft/src/syft/service/user/user.py @@ -214,9 +214,7 @@ def _set_password(self, new_password: str) -> SyftError | SyftSuccess: if api is None: return SyftError(message=f"You must login to {self.server_uid}") - api.services.user.update( - uid=self.id, user_update=UserUpdate(password=new_password) - ) + api.services.user.update(uid=self.id, password=new_password) return SyftSuccess( message=f"Successfully updated password for " f"user '{self.name}' with email '{self.email}'." @@ -250,7 +248,7 @@ def set_email(self, email: str) -> SyftSuccess | SyftError: except ValidationError: return SyftError(message="{email} is not a valid email address.") - result = api.services.user.update(uid=self.id, user_update=user_update) + result = api.services.user.update(uid=self.id, **user_update) if isinstance(result, SyftError): return result @@ -283,7 +281,7 @@ def update( role=role, mock_execution_permission=mock_execution_permission, ) - result = api.services.user.update(uid=self.id, user_update=user_update) + result = api.services.user.update(uid=self.id, **user_update) if isinstance(result, SyftError): return result diff --git a/packages/syft/tests/syft/api_test.py b/packages/syft/tests/syft/api_test.py index 82969adfe46..eba70b9e25d 100644 --- a/packages/syft/tests/syft/api_test.py +++ b/packages/syft/tests/syft/api_test.py @@ -62,12 +62,10 @@ def get_role(verify_key): with pytest.raises(SyftAttributeError): assert guest_client.upload_dataset(dataset) - assert guest_client.api.services.user.update( - user_id, UserUpdate(user_id=user_id, name="abcdef") - ) + assert guest_client.api.services.user.update(uid=user_id, name="abcdef") assert worker.root_client.api.services.user.update( - user_id, UserUpdate(user_id=user_id, role=ServiceRole.DATA_OWNER) + uid=user_id, role=ServiceRole.DATA_OWNER ) assert get_role(guest_client.credentials.verify_key) == ServiceRole.DATA_OWNER diff --git a/packages/syft/tests/syft/service_permission_test.py b/packages/syft/tests/syft/service_permission_test.py index 559ba053ea1..a0476d1ff9d 100644 --- a/packages/syft/tests/syft/service_permission_test.py +++ b/packages/syft/tests/syft/service_permission_test.py @@ -19,7 +19,7 @@ def guest_mock_user(root_verify_key, user_stash, guest_user): def test_call_service_syftapi_with_permission(worker, guest_mock_user, update_user): user_id = guest_mock_user.id - res = worker.root_client.api.services.user.update(user_id, update_user) + res = worker.root_client.api.services.user.update(uid=user_id, **update_user) assert res @@ -35,8 +35,8 @@ def test_directly_call_service_with_permission(worker, guest_mock_user, update_u api_call = SyftAPICall( server_uid=root_datasite_client.id, path="user.update", - args=[user_id, update_user], - kwargs={}, + args=[], + kwargs={"uid": user_id, **update_user}, ) signed_call = api_call.sign(root_datasite_client.api.signing_key) signed_result = root_datasite_client.api.connection.make_call(signed_call) diff --git a/packages/syft/tests/syft/settings/settings_service_test.py b/packages/syft/tests/syft/settings/settings_service_test.py index 8bbc3366a58..286c92ba66f 100644 --- a/packages/syft/tests/syft/settings/settings_service_test.py +++ b/packages/syft/tests/syft/settings/settings_service_test.py @@ -302,7 +302,7 @@ def get_mock_client(faker, root_client, role): password="password", password_verify="password", ) - result = root_client.users.create(user_create=user_create) + result = root_client.users.create(**user_create) assert not isinstance(result, SyftError) guest_client = root_client.guest() diff --git a/packages/syft/tests/syft/users/user_service_test.py b/packages/syft/tests/syft/users/user_service_test.py index 579289e751f..dfb424663e1 100644 --- a/packages/syft/tests/syft/users/user_service_test.py +++ b/packages/syft/tests/syft/users/user_service_test.py @@ -42,7 +42,7 @@ def mock_get_by_email(credentials: SyftVerifyKey, email: str) -> Ok: return Ok(guest_create_user.to(User)) monkeypatch.setattr(user_service.stash, "get_by_email", mock_get_by_email) - response = user_service.create(authed_context, guest_create_user) + response = user_service.create(authed_context, **guest_create_user) assert isinstance(response, SyftError) expected_error_message = ( f"User already exists with email: {guest_create_user.email}" @@ -60,7 +60,7 @@ def mock_get_by_email(credentials: SyftVerifyKey, email: str) -> Err: return Err(f"No user exists with given email: {email}") monkeypatch.setattr(user_service.stash, "get_by_email", mock_get_by_email) - response = user_service.create(authed_context, guest_create_user) + response = user_service.create(authed_context, **guest_create_user) assert isinstance(response, SyftError) expected_error_message = mock_get_by_email(None, guest_create_user.email).err() assert response.message == expected_error_message @@ -90,7 +90,7 @@ def mock_set( monkeypatch.setattr(user_service.stash, "get_by_email", mock_get_by_email) monkeypatch.setattr(user_service.stash, "set", mock_set) - response = user_service.create(authed_context, guest_create_user) + response = user_service.create(authed_context, **guest_create_user) assert isinstance(response, UserView) assert response.to_dict() == expected_output.to_dict() @@ -116,7 +116,7 @@ def mock_set( monkeypatch.setattr(user_service.stash, "get_by_email", mock_get_by_email) monkeypatch.setattr(user_service.stash, "set", mock_set) - response = user_service.create(authed_context, guest_create_user) + response = user_service.create(authed_context, **guest_create_user) assert isinstance(response, SyftError) assert response.message == expected_error_msg @@ -301,9 +301,7 @@ def mock_get_by_uid(credentials: SyftVerifyKey, uid: UID) -> Err: monkeypatch.setattr(user_service.stash, "get_by_uid", mock_get_by_uid) - response = user_service.update( - authed_context, uid=random_uid, user_update=update_user - ) + response = user_service.update(authed_context, uid=random_uid, **update_user) assert isinstance(response, SyftError) assert response.message == expected_error_msg @@ -322,9 +320,7 @@ def mock_get_by_uid(credentials: SyftVerifyKey, uid: UID) -> Ok: monkeypatch.setattr(user_service.stash, "get_by_uid", mock_get_by_uid) - response = user_service.update( - authed_context, uid=random_uid, user_update=update_user - ) + response = user_service.update(authed_context, uid=random_uid, **update_user) assert isinstance(response, SyftError) assert response.message == expected_error_msg @@ -349,7 +345,7 @@ def mock_update(credentials: SyftVerifyKey, user: User, has_permission: bool) -> authed_context.role = ServiceRole.ADMIN resultant_user = user_service.update( - authed_context, uid=guest_user.id, user_update=update_user + authed_context, uid=guest_user.id, **update_user ) assert isinstance(resultant_user, UserView) assert resultant_user.email == update_user.email @@ -379,9 +375,7 @@ def mock_update(credentials: SyftVerifyKey, user, has_permission: bool) -> Err: monkeypatch.setattr(user_service.stash, "update", mock_update) monkeypatch.setattr(user_service.stash, "get_by_uid", mock_get_by_uid) - response = user_service.update( - authed_context, uid=guest_user.id, user_update=update_user - ) + response = user_service.update(authed_context, uid=guest_user.id, **update_user) assert isinstance(response, SyftError) assert response.message == expected_error_msg diff --git a/packages/syft/tests/syft/users/user_test.py b/packages/syft/tests/syft/users/user_test.py index f51fbe8456e..90f156c4173 100644 --- a/packages/syft/tests/syft/users/user_test.py +++ b/packages/syft/tests/syft/users/user_test.py @@ -47,9 +47,7 @@ def get_mock_client(root_client, role) -> DatasiteClient: ) assert user user_id = [u for u in get_users(worker) if u.email == mail][0].id - assert worker.root_client.api.services.user.update( - user_id, UserUpdate(user_id=user_id, role=role) - ) + assert worker.root_client.api.services.user.update(uid=user_id, role=role) client = client.login(email=mail, password=password) client._fetch_api(client.credentials) # hacky, but useful for testing: patch user id and role on client @@ -113,15 +111,11 @@ def test_user_create(worker, do_client, guest_client, ds_client, root_client): for client in [ds_client, guest_client]: assert not manually_call_service(worker, client, "user.create") for client in [do_client, root_client]: + user_create = UserCreate( + email=Faker().email(), name="z", password="pw", password_verify="pw" + ) res = manually_call_service( - worker, - client, - "user.create", - args=[ - UserCreate( - email=Faker().email(), name="z", password="pw", password_verify="pw" - ) - ], + worker, client, "user.create", args=[], kwargs={**user_create} ) assert isinstance(res, UserView) @@ -169,14 +163,14 @@ def test_user_update_roles(do_client, guest_client, ds_client, root_client, work clients = [get_mock_client(root_client, role) for role in DO_ROLES] for _c in clients: assert worker.root_client.api.services.user.update( - _c.user_id, UserUpdate(role=ServiceRole.ADMIN) + uid=_c.user_id, role=ServiceRole.ADMIN ) # DOs can update the roles of lower roles clients = [get_mock_client(root_client, role) for role in DS_ROLES] for _c in clients: assert do_client.api.services.user.update( - _c.user_id, UserUpdate(role=ServiceRole.DATA_SCIENTIST) + uid=_c.user_id, role=ServiceRole.DATA_SCIENTIST ) clients = [get_mock_client(root_client, role) for role in ADMIN_ROLES] @@ -225,16 +219,16 @@ def test_user_update(root_client): for target_client in target_clients: if executing_client.role != ServiceRole.ADMIN: assert not executing_client.api.services.user.update( - target_client.user_id, UserUpdate(name="abc") + uid=target_client.user_id, name="abc" ) else: assert executing_client.api.services.user.update( - target_client.user_id, UserUpdate(name="abc") + uid=target_client.user_id, name="abc" ) # you can update yourself assert executing_client.api.services.user.update( - executing_client.user_id, UserUpdate(name=Faker().name()) + uid=executing_client.user_id, name=Faker().name() ) @@ -245,10 +239,9 @@ def test_guest_user_update_to_root_email_failed( ds_client: DatasiteClient, ) -> None: default_root_email: str = get_default_root_email() - user_update_to_root_email = UserUpdate(email=default_root_email) for client in [root_client, do_client, guest_client, ds_client]: res = client.api.services.user.update( - uid=client.me.id, user_update=user_update_to_root_email + uid=client.me.id, email=default_root_email ) assert isinstance(res, SyftError) assert res.message == "User already exists" diff --git a/packages/syft/tests/syft/worker_test.py b/packages/syft/tests/syft/worker_test.py index 3f369e8c5a6..f2ba6eeedcb 100644 --- a/packages/syft/tests/syft/worker_test.py +++ b/packages/syft/tests/syft/worker_test.py @@ -147,7 +147,7 @@ def test_user_service(worker) -> None: ) # call the create function - user_view = user_service.create(context=context, user_create=new_user) + user_view = user_service.create(context=context, **new_user) # get the result assert user_view is not None From 5636505567be48e192aa83dfae6ae3a22664c42b Mon Sep 17 00:00:00 2001 From: Madhava Jay Date: Tue, 9 Jul 2024 13:01:34 +1000 Subject: [PATCH 060/117] Fixed more failing user autosplat tests --- .../tutorials/data-owner/02-account-management.ipynb | 3 +-- packages/syft/src/syft/service/user/user.py | 2 +- packages/syft/tests/syft/action_test.py | 5 +---- packages/syft/tests/syft/api_test.py | 1 - packages/syft/tests/syft/users/user_code_test.py | 5 +---- packages/syft/tests/syft/users/user_test.py | 9 ++++----- 6 files changed, 8 insertions(+), 17 deletions(-) diff --git a/notebooks/tutorials/data-owner/02-account-management.ipynb b/notebooks/tutorials/data-owner/02-account-management.ipynb index a41262f8a04..1488030630a 100644 --- a/notebooks/tutorials/data-owner/02-account-management.ipynb +++ b/notebooks/tutorials/data-owner/02-account-management.ipynb @@ -79,7 +79,6 @@ "# syft absolute\n", "from syft.service.user.user import ServiceRole\n", "from syft.service.user.user import UserCreate\n", - "from syft.service.user.user import UserUpdate\n", "\n", "client = server.login(email=\"info@openmined.org\", password=\"changethis\")" ] @@ -209,7 +208,7 @@ "outputs": [], "source": [ "updated_user = client.users.update(\n", - " new_user.id, UserUpdate(role=ServiceRole.DATA_SCIENTIST, password=\"123\")\n", + " uid=new_user.id, role=ServiceRole.DATA_SCIENTIST, password=\"123\"\n", ")" ] }, diff --git a/packages/syft/src/syft/service/user/user.py b/packages/syft/src/syft/service/user/user.py index 886c5ffa678..88b509c2d56 100644 --- a/packages/syft/src/syft/service/user/user.py +++ b/packages/syft/src/syft/service/user/user.py @@ -248,7 +248,7 @@ def set_email(self, email: str) -> SyftSuccess | SyftError: except ValidationError: return SyftError(message="{email} is not a valid email address.") - result = api.services.user.update(uid=self.id, **user_update) + result = api.services.user.update(uid=self.id, email=user_update.email) if isinstance(result, SyftError): return result diff --git a/packages/syft/tests/syft/action_test.py b/packages/syft/tests/syft/action_test.py index b461840ff4a..47868bc1baa 100644 --- a/packages/syft/tests/syft/action_test.py +++ b/packages/syft/tests/syft/action_test.py @@ -12,7 +12,6 @@ from syft.server.worker import Worker from syft.service.action.action_object import Action from syft.service.response import SyftError -from syft.service.user.user import UserUpdate from syft.service.user.user_roles import ServiceRole from syft.types.uid import LineageID @@ -58,9 +57,7 @@ def test_new_admin_has_action_object_permission( admin = root_client.login(email=email, password=pw) - root_client.api.services.user.update( - admin.me.id, UserUpdate(role=ServiceRole.ADMIN) - ) + root_client.api.services.user.update(uid=admin.me.id, role=ServiceRole.ADMIN) if delete_original_admin: res = root_client.api.services.user.delete(root_client.me.id) diff --git a/packages/syft/tests/syft/api_test.py b/packages/syft/tests/syft/api_test.py index eba70b9e25d..fd3d9f7339b 100644 --- a/packages/syft/tests/syft/api_test.py +++ b/packages/syft/tests/syft/api_test.py @@ -8,7 +8,6 @@ # syft absolute import syft as sy from syft.service.response import SyftAttributeError -from syft.service.user.user import UserUpdate from syft.service.user.user_roles import ServiceRole diff --git a/packages/syft/tests/syft/users/user_code_test.py b/packages/syft/tests/syft/users/user_code_test.py index ad585e2eaee..796b6a99753 100644 --- a/packages/syft/tests/syft/users/user_code_test.py +++ b/packages/syft/tests/syft/users/user_code_test.py @@ -18,7 +18,6 @@ from syft.service.response import SyftError from syft.service.response import SyftSuccess from syft.service.user.user import User -from syft.service.user.user import UserUpdate from syft.service.user.user_roles import ServiceRole # relative @@ -68,9 +67,7 @@ def test_new_admin_can_list_user_code( admin = root_client.login(email=email, password=pw) - root_client.api.services.user.update( - admin.me.id, UserUpdate(role=ServiceRole.ADMIN) - ) + root_client.api.services.user.update(uid=admin.me.id, role=ServiceRole.ADMIN) if delete_original_admin: res = root_client.api.services.user.delete(root_client.me.id) diff --git a/packages/syft/tests/syft/users/user_test.py b/packages/syft/tests/syft/users/user_test.py index 90f156c4173..8799ce39d5e 100644 --- a/packages/syft/tests/syft/users/user_test.py +++ b/packages/syft/tests/syft/users/user_test.py @@ -16,7 +16,6 @@ from syft.service.context import AuthedServiceContext from syft.service.user.user import ServiceRole from syft.service.user.user import UserCreate -from syft.service.user.user import UserUpdate from syft.service.user.user import UserView GUEST_ROLES = [ServiceRole.GUEST] @@ -179,7 +178,7 @@ def test_user_update_roles(do_client, guest_client, ds_client, root_client, work for _c in clients: for target_role in [ServiceRole.DATA_OWNER, ServiceRole.ADMIN]: assert not do_client.api.services.user.update( - _c.user_id, UserUpdate(role=target_role) + uid=_c.user_id, role=target_role ) # DOs cannot downgrade higher roles to lower levels @@ -191,7 +190,7 @@ def test_user_update_roles(do_client, guest_client, ds_client, root_client, work for target_role in DO_ROLES: if target_role < _c.role: assert not do_client.api.services.user.update( - _c.user_id, UserUpdate(role=target_role) + uid=_c.user_id, role=target_role ) # DSs cannot update any roles @@ -199,7 +198,7 @@ def test_user_update_roles(do_client, guest_client, ds_client, root_client, work for _c in clients: for target_role in ADMIN_ROLES: assert not ds_client.api.services.user.update( - _c.user_id, UserUpdate(role=target_role) + uid=_c.user_id, role=target_role ) # Guests cannot update any roles @@ -207,7 +206,7 @@ def test_user_update_roles(do_client, guest_client, ds_client, root_client, work for _c in clients: for target_role in ADMIN_ROLES: assert not guest_client.api.services.user.update( - _c.user_id, UserUpdate(role=target_role) + uid=_c.user_id, role=target_role ) From 66ae61e8cf515c02cbddecda7e3991c0a224adfb Mon Sep 17 00:00:00 2001 From: Madhava Jay Date: Mon, 15 Jul 2024 17:57:54 +1000 Subject: [PATCH 061/117] Added ruff ignore rule and missing autosplat --- notebooks/scenarios/getting-started/.ruff.toml | 2 ++ packages/syft/src/syft/service/user/user_service.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 notebooks/scenarios/getting-started/.ruff.toml diff --git a/notebooks/scenarios/getting-started/.ruff.toml b/notebooks/scenarios/getting-started/.ruff.toml new file mode 100644 index 00000000000..4df73d6ade3 --- /dev/null +++ b/notebooks/scenarios/getting-started/.ruff.toml @@ -0,0 +1,2 @@ +[lint] +ignore = ["E501"] diff --git a/packages/syft/src/syft/service/user/user_service.py b/packages/syft/src/syft/service/user/user_service.py index 71651496a21..b5e91395d9d 100644 --- a/packages/syft/src/syft/service/user/user_service.py +++ b/packages/syft/src/syft/service/user/user_service.py @@ -55,7 +55,7 @@ def __init__(self, store: DocumentStore) -> None: self.store = store self.stash = UserStash(store=store) - @service_method(path="user.create", name="create") + @service_method(path="user.create", name="create", autosplat="user_create") def create( self, context: AuthedServiceContext, user_create: UserCreate ) -> UserView | SyftError: @@ -265,6 +265,7 @@ def get_by_verify_key_endpoint( path="user.update", name="update", roles=GUEST_ROLE_LEVEL, + autosplat="user_update", ) def update( self, context: AuthedServiceContext, uid: UID, user_update: UserUpdate From 599b54ef4d27010a886ae3dafcdf5f6b907ae7e5 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Mon, 15 Jul 2024 13:39:01 +0530 Subject: [PATCH 062/117] [action_service]: rename syft_node_location to syft_server_location --- packages/syft/src/syft/service/action/action_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index 5bfc02146cc..30e77fb8191 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -828,7 +828,7 @@ def flatten_action_arg(self, context: AuthedServiceContext, arg: UID) -> UID | N id=action_object.id, syft_blob_storage_entry_id=action_object.syft_blob_storage_entry_id, syft_client_verify_key=action_object.syft_client_verify_key, - syft_node_location=action_object.syft_node_location, + syft_server_location=action_object.syft_server_location, ) new_action_object._save_to_blob_storage() res = self._set( From f17816acce9ca0b6f1a7d1be6e1462671413c143 Mon Sep 17 00:00:00 2001 From: khoaguin Date: Mon, 15 Jul 2024 15:09:35 +0700 Subject: [PATCH 063/117] [syft/action_service] stop deleting the action object but just setting its `syft_action_data_cache` and `syft_action_saved_to_blob_store` to None Co-authored-by: Shubham Gupta --- .../src/syft/service/action/action_service.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index a97d7368d3b..ddff023c0d0 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -960,20 +960,13 @@ def _delete_from_action_store( def _soft_delete_action_obj( self, context: AuthedServiceContext, action_obj: ActionObject ) -> Result[ActionObject, str]: - """ - Delete the provided action object and create an empty one with the same UID - """ - uid: UID = action_obj.id - del_res = self.store.delete(credentials=context.credentials, uid=uid) - if del_res.is_err(): - return del_res - - none_action_obj = ActionObject.from_obj(syft_action_data=None, id=uid) - none_action_obj.syft_action_saved_to_blob_store = False + action_obj.syft_action_data_cache = None + res = action_obj._save_to_blob_storage() + if isinstance(res, SyftError): + return Err(res.message) set_result = self._set( context=context, - action_object=none_action_obj, - ignore_detached_objs=True, + action_object=action_obj, ) return set_result From 44e42a8d019875c7a22b9c764573650dd8220253 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Mon, 15 Jul 2024 12:18:51 +0200 Subject: [PATCH 064/117] fix merge --- packages/syft/src/syft/__init__.py | 5 +++ packages/syft/src/syft/serde/recursive.py | 24 ++++++++--- .../src/syft/serde/recursive_primitives.py | 43 +++++++++---------- packages/syft/src/syft/serde/third_party.py | 2 + packages/syft/src/syft/types/syft_object.py | 7 +-- packages/syft/src/syft/util/__init__.py | 2 - 6 files changed, 49 insertions(+), 34 deletions(-) diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index 2cd91e5aefa..73417a1a0fe 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -86,6 +86,7 @@ from .util.util import autocache from .util.util import get_root_data_path from .util.version_compare import make_requires +from .serde.recursive import MISSING_CANONICAL_NAME requires = make_requires(LATEST_STABLE_SYFT, __version__) @@ -147,3 +148,7 @@ def hello_baby() -> None: def search(name: str) -> SearchResults: return Search(_datasites()).search(name=name) + + +if len(MISSING_CANONICAL_NAME): + print(f"{len(MISSING_CANONICAL_NAME)} classes found without canonical names") diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index 1ef7c1acd74..d5df3e0ab7e 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -21,6 +21,7 @@ from .util import compatible_with_large_file_writes_capnp TYPE_BANK = {} +MISSING_CANONICAL_NAME = [] recursive_scheme = get_capnp_schema("recursive_serde.capnp").RecursiveSerde @@ -78,12 +79,20 @@ def check_fqn_alias(cls: object | type) -> tuple | None: return None -def validate_cannonical_name_version( +def has_canonical_name_version( cls: type, cannonical_name: str | None, version: int | None +) -> bool: + cls_canonical_name = getattr(cls, "__canonical_name__", None) + cls_version = getattr(cls, "__version__", None) + return (cls_canonical_name or cannonical_name) and (cls_version or version) + + +def validate_cannonical_name_version( + cls: type, canonical_name: str | None, version: int | None ) -> tuple[str, int]: cls_canonical_name = getattr(cls, "__canonical_name__", None) cls_version = getattr(cls, "__version__", None) - if cls_canonical_name and cannonical_name: + if cls_canonical_name and canonical_name: raise ValueError( "Cannot specify both __canonical_name__ attribute and cannonical_name argument." ) @@ -91,7 +100,7 @@ def validate_cannonical_name_version( raise ValueError( "Cannot specify both __version__ attribute and version argument." ) - if cls_canonical_name is None and cannonical_name is None: + if cls_canonical_name is None and canonical_name is None: raise ValueError( "Must specify either __canonical_name__ attribute or cannonical_name argument." ) @@ -100,9 +109,9 @@ def validate_cannonical_name_version( "Must specify either __version__ attribute or version argument." ) - cannonical_name = cannonical_name or cls_canonical_name + canonical_name = canonical_name or cls_canonical_name version = version or cls_version - return cannonical_name, version # type: ignore + return canonical_name, version # type: ignore def recursive_serde_register( @@ -123,6 +132,11 @@ def recursive_serde_register( alias_fqn = check_fqn_alias(cls) cls = type(cls) if not isinstance(cls, type) else cls fqn = f"{cls.__module__}.{cls.__name__}" + + if not has_canonical_name_version(cls, canonical_name, version): + MISSING_CANONICAL_NAME.append(cls) + return + canonical_name, version = validate_cannonical_name_version( cls, canonical_name, version ) diff --git a/packages/syft/src/syft/serde/recursive_primitives.py b/packages/syft/src/syft/serde/recursive_primitives.py index 02f2a8048ec..7e8a65c5884 100644 --- a/packages/syft/src/syft/serde/recursive_primitives.py +++ b/packages/syft/src/syft/serde/recursive_primitives.py @@ -27,7 +27,6 @@ import weakref # relative -from ..types.syft_object import SYFT_OBJECT_VERSION_1 from .capnp import get_capnp_schema from .recursive import chunk_bytes from .recursive import combine_bytes @@ -212,7 +211,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda x: x.to_bytes((x.bit_length() + 7) // 8 + 1, "big", signed=True), deserialize=lambda x_bytes: int.from_bytes(x_bytes, "big", signed=True), canonical_name="int", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -220,7 +219,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda x: x.hex().encode(), deserialize=lambda x: float.fromhex(x.decode()), canonical_name="float", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -228,7 +227,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda x: x, deserialize=lambda x: x, canonical_name="bytes", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -236,7 +235,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda x: x.encode(), deserialize=lambda x: x.decode(), canonical_name="str", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -244,7 +243,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, list), canonical_name="list", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -252,7 +251,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, tuple), canonical_name="tuple", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -260,7 +259,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_kv, deserialize=functools.partial(deserialize_kv, dict), canonical_name="dict", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -268,7 +267,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_defaultdict, deserialize=deserialize_defaultdict, canonical_name="defaultdict", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -276,7 +275,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_kv, deserialize=functools.partial(deserialize_kv, OrderedDict), canonical_name="OrderedDict", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -284,7 +283,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda _: b"1", deserialize=lambda _: None, canonical_name="NoneType", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -292,7 +291,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda x: b"1" if x else b"0", deserialize=lambda x: False if x == b"0" else True, canonical_name="bool", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -300,7 +299,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, set), canonical_name="set", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -308,7 +307,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, weakref.WeakSet), canonical_name="WeakSet", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -316,7 +315,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_iterable, deserialize=functools.partial(deserialize_iterable, frozenset), canonical_name="frozenset", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -324,7 +323,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda x: serialize_iterable((x.real, x.imag)), deserialize=lambda x: complex(*deserialize_iterable(tuple, x)), canonical_name="complex", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -332,7 +331,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda x: serialize_iterable((x.start, x.stop, x.step)), deserialize=lambda x: range(*deserialize_iterable(tuple, x)), canonical_name="range", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -340,7 +339,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=lambda x: serialize_iterable((x.start, x.stop, x.step)), deserialize=lambda x: slice(*deserialize_iterable(tuple, x)), canonical_name="slice", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -348,7 +347,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_type, deserialize=deserialize_type, canonical_name="type", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -356,7 +355,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_kv, deserialize=functools.partial(deserialize_kv, MappingProxyType), canonical_name="MappingProxyType", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register( @@ -364,7 +363,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_path, deserialize=functools.partial(deserialize_path, PurePath), canonical_name="PurePath", - version=SYFT_OBJECT_VERSION_1, + version=1, ) for __path_type in ( @@ -476,7 +475,7 @@ def deserialize_union_type(type_blob: bytes) -> type: serialize=serialize_union_type, deserialize=deserialize_union_type, canonical_name="UnionType", - version=SYFT_OBJECT_VERSION_1, + version=1, ) recursive_serde_register_type(_SpecialForm, canonical_name="_SpecialForm", version=1) diff --git a/packages/syft/src/syft/serde/third_party.py b/packages/syft/src/syft/serde/third_party.py index 3d8cde57451..de10bd9cc5b 100644 --- a/packages/syft/src/syft/serde/third_party.py +++ b/packages/syft/src/syft/serde/third_party.py @@ -161,12 +161,14 @@ def _serialize_dicttuple(x: DictTuple) -> bytes: serialize=serialize_type, deserialize=deserialize_type, canonical_name="dicttuple_meta", + version=1, ) recursive_serde_register( DictTuple, serialize=_serialize_dicttuple, deserialize=functools.partial(deserialize_kv, DictTuple), canonical_name="dicttuple", + version=1, ) diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 2c416843912..ac3242a12e5 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -33,6 +33,7 @@ from pydantic import model_validator from pydantic.fields import PydanticUndefined from result import OkErr +from syft.serde.serializable import serializable from typeguard import check_type from typing_extensions import Self @@ -722,6 +723,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: TupleGenerator = Generator[tuple[str, Any], None, None] +@serializable() class PartialSyftObject(SyftObject, metaclass=PartialModelMetaclass): """Syft Object to which partial arguments can be provided.""" @@ -732,11 +734,6 @@ def __iter__(self) -> TupleGenerator: yield from ((k, v) for k, v in super().__iter__() if v is not Empty) -recursive_serde_register_type( - PartialSyftObject, canonical_name="PartialSyftObject", version=1 -) - - def attach_attribute_to_syft_object(result: Any, attr_dict: dict[str, Any]) -> None: iterator: Iterable if isinstance(result, OkErr): diff --git a/packages/syft/src/syft/util/__init__.py b/packages/syft/src/syft/util/__init__.py index aec1f392faf..e69de29bb2d 100644 --- a/packages/syft/src/syft/util/__init__.py +++ b/packages/syft/src/syft/util/__init__.py @@ -1,2 +0,0 @@ -# relative -from .schema import generate_json_schemas From a3ca33e460245cb35a1610086243dab770c1ec2d Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Mon, 15 Jul 2024 18:21:11 +0530 Subject: [PATCH 065/117] refactor to update existing action object with the flattened action object --- .../syft/src/syft/service/action/action_service.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index 30e77fb8191..95f83d596ac 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -822,18 +822,12 @@ def flatten_action_arg(self, context: AuthedServiceContext, arg: UID) -> UID | N if self.contains_nested_actionobjects(data): new_data = self.unwrap_nested_actionobjects(context, data) - - new_action_object = ActionObject.from_obj( - new_data, - id=action_object.id, - syft_blob_storage_entry_id=action_object.syft_blob_storage_entry_id, - syft_client_verify_key=action_object.syft_client_verify_key, - syft_server_location=action_object.syft_server_location, - ) - new_action_object._save_to_blob_storage() + # Update existing action object with the new flattened data + action_object.syft_action_data_cache = new_data + action_object._save_to_blob_storage() res = self._set( context=context, - action_object=new_action_object, + action_object=action_object, ) return None From d50d06c901e836376ef3e5df8171e59f43276d4c Mon Sep 17 00:00:00 2001 From: Aziz Berkay Yesilyurt Date: Mon, 15 Jul 2024 15:38:09 +0200 Subject: [PATCH 066/117] rename public and private server to low- and high-side server as part of https://github.com/OpenMined/Heartbeat/issues/1600 --- packages/syft/src/syft/service/sync/diff_state.py | 8 ++++---- packages/syft/src/syft/service/sync/resolve_widget.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/syft/src/syft/service/sync/diff_state.py b/packages/syft/src/syft/service/sync/diff_state.py index 75752f170c9..e520d8c341e 100644 --- a/packages/syft/src/syft/service/sync/diff_state.py +++ b/packages/syft/src/syft/service/sync/diff_state.py @@ -1344,11 +1344,11 @@ def _repr_markdown_(self) -> None: # type: ignore def _repr_html_(self) -> Any: n = len(self.batches) if self.direction == SyncDirection.LOW_TO_HIGH: - name1 = "Public Server" - name2 = "Private Server" + name1 = "Low-side Server" + name2 = "High-side Server" else: - name1 = "Private Server" - name2 = "Public Server" + name1 = "High-side Server" + name2 = "Low-side Server" repr_html = f"""

Comparing sync states
diff --git a/packages/syft/src/syft/service/sync/resolve_widget.py b/packages/syft/src/syft/service/sync/resolve_widget.py index b4a2a8f83ca..39d0ff08b7b 100644 --- a/packages/syft/src/syft/service/sync/resolve_widget.py +++ b/packages/syft/src/syft/service/sync/resolve_widget.py @@ -143,7 +143,7 @@ def share_private_data(self) -> bool: @property def warning_html(self) -> str: if isinstance(self.diff.non_empty_object, TwinAPIEndpoint): - message = "Only the public function of a TwinAPI will be synced to the public server." + message = "Only the public function of a TwinAPI will be synced to the low-side server." return Alert(message=message).to_html() elif self.show_share_warning: message = ( From b48a5a67ca7310d4dd4689c5fc71320f7ebdffe7 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Mon, 15 Jul 2024 17:06:58 +0200 Subject: [PATCH 067/117] autogenerate canonicalname/version --- packages/syft/src/syft/__init__.py | 5 -- packages/syft/src/syft/abstract_server.py | 4 +- packages/syft/src/syft/client/api.py | 10 ++-- packages/syft/src/syft/client/client.py | 2 +- .../syft/src/syft/client/datasite_client.py | 2 +- .../syft/src/syft/client/enclave_client.py | 2 +- .../syft/src/syft/client/gateway_client.py | 2 +- .../syft/src/syft/client/sync_decision.py | 2 +- .../syft/src/syft/custom_worker/config.py | 6 +-- .../syft/src/syft/serde/lib_permissions.py | 8 ++-- packages/syft/src/syft/serde/recursive.py | 48 ++++++++++++------- .../src/syft/serde/recursive_primitives.py | 1 + packages/syft/src/syft/serde/serializable.py | 4 ++ packages/syft/src/syft/serde/third_party.py | 3 ++ packages/syft/src/syft/server/credentials.py | 6 +-- packages/syft/src/syft/server/datasite.py | 2 +- packages/syft/src/syft/server/enclave.py | 2 +- packages/syft/src/syft/server/gateway.py | 2 +- .../syft/src/syft/server/service_registry.py | 2 +- packages/syft/src/syft/server/worker.py | 2 +- .../src/syft/service/action/action_object.py | 4 +- .../syft/service/action/action_permissions.py | 6 +-- .../src/syft/service/action/action_service.py | 2 +- .../src/syft/service/action/action_store.py | 8 ++-- .../syft/src/syft/service/api/api_service.py | 2 +- .../syft/src/syft/service/api/api_stash.py | 2 +- .../attestation/attestation_service.py | 2 +- .../service/blob_storage/remote_profile.py | 2 +- .../src/syft/service/blob_storage/service.py | 2 +- .../src/syft/service/blob_storage/stash.py | 2 +- .../src/syft/service/code/status_service.py | 4 +- .../syft/src/syft/service/code/user_code.py | 2 +- .../syft/service/code/user_code_service.py | 2 +- .../src/syft/service/code/user_code_stash.py | 2 +- .../code_history/code_history_service.py | 2 +- .../code_history/code_history_stash.py | 2 +- .../data_subject_member_service.py | 4 +- .../data_subject/data_subject_service.py | 4 +- .../syft/service/dataset/dataset_service.py | 2 +- .../src/syft/service/dataset/dataset_stash.py | 2 +- .../syft/service/enclave/enclave_service.py | 2 +- .../syft/src/syft/service/job/job_service.py | 2 +- .../syft/src/syft/service/job/job_stash.py | 6 +-- .../syft/src/syft/service/log/log_service.py | 2 +- .../syft/src/syft/service/log/log_stash.py | 2 +- .../syft/service/metadata/metadata_service.py | 2 +- .../syft/service/metadata/server_metadata.py | 2 +- .../service/migration/migration_service.py | 2 +- .../migration/object_migration_state.py | 2 +- .../syft/service/network/network_service.py | 6 +-- .../syft/src/syft/service/network/rathole.py | 2 +- .../src/syft/service/network/server_peer.py | 2 +- .../syft/src/syft/service/network/utils.py | 2 +- .../notification/notification_service.py | 2 +- .../notification/notification_stash.py | 2 +- .../service/notification/notifications.py | 4 +- .../syft/service/notifier/notifier_enums.py | 2 +- .../syft/service/notifier/notifier_service.py | 2 +- .../syft/service/notifier/notifier_stash.py | 2 +- .../src/syft/service/output/output_service.py | 4 +- .../syft/src/syft/service/policy/policy.py | 8 ++-- .../src/syft/service/policy/policy_service.py | 2 +- .../syft/service/policy/user_policy_stash.py | 2 +- .../syft/src/syft/service/project/project.py | 4 +- .../syft/service/project/project_service.py | 2 +- .../src/syft/service/project/project_stash.py | 2 +- .../syft/src/syft/service/queue/base_queue.py | 18 ++++--- packages/syft/src/syft/service/queue/queue.py | 4 +- .../src/syft/service/queue/queue_service.py | 2 +- .../src/syft/service/queue/queue_stash.py | 4 +- .../syft/src/syft/service/queue/zmq_queue.py | 8 ++-- .../syft/src/syft/service/request/request.py | 2 +- .../syft/service/request/request_service.py | 2 +- .../src/syft/service/request/request_stash.py | 2 +- packages/syft/src/syft/service/response.py | 14 +++--- .../syft/service/settings/settings_service.py | 2 +- .../syft/service/settings/settings_stash.py | 2 +- .../src/syft/service/sync/sync_service.py | 2 +- .../syft/src/syft/service/sync/sync_stash.py | 2 +- .../syft/src/syft/service/user/user_roles.py | 2 +- .../src/syft/service/user/user_service.py | 2 +- .../syft/src/syft/service/user/user_stash.py | 2 +- packages/syft/src/syft/service/warnings.py | 10 ++-- .../syft/service/worker/image_identifier.py | 2 +- .../service/worker/image_registry_service.py | 2 +- .../service/worker/image_registry_stash.py | 2 +- .../service/worker/worker_image_service.py | 2 +- .../syft/service/worker/worker_image_stash.py | 2 +- .../src/syft/service/worker/worker_pool.py | 10 ++-- .../service/worker/worker_pool_service.py | 2 +- .../syft/service/worker/worker_pool_stash.py | 2 +- .../src/syft/service/worker/worker_service.py | 2 +- .../src/syft/service/worker/worker_stash.py | 2 +- .../src/syft/store/blob_storage/__init__.py | 6 +-- .../src/syft/store/blob_storage/on_disk.py | 6 +-- .../src/syft/store/blob_storage/seaweedfs.py | 8 ++-- .../src/syft/store/dict_document_store.py | 6 +-- .../syft/src/syft/store/document_store.py | 22 +++++---- .../syft/src/syft/store/kv_document_store.py | 2 +- packages/syft/src/syft/store/locks.py | 6 +-- packages/syft/src/syft/store/mongo_client.py | 2 +- .../src/syft/store/mongo_document_store.py | 10 ++-- .../src/syft/store/sqlite_document_store.py | 12 +++-- packages/syft/src/syft/types/cache_object.py | 2 +- packages/syft/src/syft/types/identity.py | 2 +- packages/syft/src/syft/types/server_url.py | 6 ++- .../syft/src/syft/types/syft_metaclass.py | 2 +- packages/syft/src/syft/types/syft_object.py | 3 +- packages/syft/src/syft/types/uid.py | 4 +- 109 files changed, 245 insertions(+), 207 deletions(-) diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index 73417a1a0fe..2cd91e5aefa 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -86,7 +86,6 @@ from .util.util import autocache from .util.util import get_root_data_path from .util.version_compare import make_requires -from .serde.recursive import MISSING_CANONICAL_NAME requires = make_requires(LATEST_STABLE_SYFT, __version__) @@ -148,7 +147,3 @@ def hello_baby() -> None: def search(name: str) -> SearchResults: return Search(_datasites()).search(name=name) - - -if len(MISSING_CANONICAL_NAME): - print(f"{len(MISSING_CANONICAL_NAME)} classes found without canonical names") diff --git a/packages/syft/src/syft/abstract_server.py b/packages/syft/src/syft/abstract_server.py index 8a312b0113d..4f0fba356c5 100644 --- a/packages/syft/src/syft/abstract_server.py +++ b/packages/syft/src/syft/abstract_server.py @@ -12,7 +12,7 @@ from .service.service import AbstractService -@serializable() +@serializable(canonical_name="ServerType", version=1) class ServerType(str, Enum): DATASITE = "datasite" NETWORK = "network" @@ -24,7 +24,7 @@ def __str__(self) -> str: return self.value -@serializable() +@serializable(canonical_name="ServerSideType", version=1) class ServerSideType(str, Enum): LOW_SIDE = "low" HIGH_SIDE = "high" diff --git a/packages/syft/src/syft/client/api.py b/packages/syft/src/syft/client/api.py index 54a589c8c57..6f7253076c4 100644 --- a/packages/syft/src/syft/client/api.py +++ b/packages/syft/src/syft/client/api.py @@ -288,7 +288,7 @@ def prepare_args_and_kwargs( to_protocol=self.communication_protocol, args=args, kwargs=kwargs ) - return args, kwargs + return tuple(args), kwargs def function_call( self, path: str, *args: Any, cache_result: bool = True, **kwargs: Any @@ -448,7 +448,7 @@ class RemoteUserCodeFunction(RemoteFunction): def prepare_args_and_kwargs( self, args: list | tuple, kwargs: dict[str, Any] - ) -> SyftError | tuple[tuple, dict[str, Any]]: + ) -> tuple[tuple, dict[str, Any]] | SyftError: # relative from ..service.action.action_object import convert_to_pointers @@ -479,7 +479,7 @@ def prepare_args_and_kwargs( to_protocol=self.communication_protocol, args=args, kwargs=kwargs ) - return args, kwargs + return tuple(args), kwargs @property def user_code_id(self) -> UID | None: @@ -643,7 +643,7 @@ def _coll_repr_(self) -> dict[str, Any]: return {"submodule": self.submodule, "endpoints": "\n".join(self.endpoints)} -@serializable() +@serializable(canonical_name="APIModule", version=1) class APIModule: _modules: list[str] path: str @@ -1275,7 +1275,7 @@ def monkey_patch_getdef(self: Any, obj: Any, oname: str = "") -> str | None: pass # nosec -@serializable() +@serializable(canonical_name="ServerIdentity", version=1) class ServerIdentity(Identity): server_name: str diff --git a/packages/syft/src/syft/client/client.py b/packages/syft/src/syft/client/client.py index 53c33ead318..191e5253608 100644 --- a/packages/syft/src/syft/client/client.py +++ b/packages/syft/src/syft/client/client.py @@ -593,7 +593,7 @@ def get_client_type(self) -> type[SyftClient] | SyftError: @instrument -@serializable() +@serializable(canonical_name="SyftClient", version=1) class SyftClient: connection: ServerConnection metadata: ServerMetadataJSON | None diff --git a/packages/syft/src/syft/client/datasite_client.py b/packages/syft/src/syft/client/datasite_client.py index e30681c6698..9ef0638acb6 100644 --- a/packages/syft/src/syft/client/datasite_client.py +++ b/packages/syft/src/syft/client/datasite_client.py @@ -90,7 +90,7 @@ def add_default_uploader( return obj -@serializable() +@serializable(canonical_name="DatasiteClient", version=1) class DatasiteClient(SyftClient): def __repr__(self) -> str: return f"" diff --git a/packages/syft/src/syft/client/enclave_client.py b/packages/syft/src/syft/client/enclave_client.py index fc0544e03ad..f3fc2571ab5 100644 --- a/packages/syft/src/syft/client/enclave_client.py +++ b/packages/syft/src/syft/client/enclave_client.py @@ -34,7 +34,7 @@ class EnclaveMetadata(SyftObject): route: ServerRouteType -@serializable() +@serializable(canonical_name="EnclaveClient", version=1) class EnclaveClient(SyftClient): # TODO: add widget repr for enclave client diff --git a/packages/syft/src/syft/client/gateway_client.py b/packages/syft/src/syft/client/gateway_client.py index c8e4929f99e..3be3b04631b 100644 --- a/packages/syft/src/syft/client/gateway_client.py +++ b/packages/syft/src/syft/client/gateway_client.py @@ -18,7 +18,7 @@ from .connection import ServerConnection -@serializable() +@serializable(canonical_name="GatewayClient", version=1) class GatewayClient(SyftClient): # TODO: add widget repr for gateway client diff --git a/packages/syft/src/syft/client/sync_decision.py b/packages/syft/src/syft/client/sync_decision.py index 02432d13b75..30f0098bab7 100644 --- a/packages/syft/src/syft/client/sync_decision.py +++ b/packages/syft/src/syft/client/sync_decision.py @@ -5,7 +5,7 @@ from ..serde.serializable import serializable -@serializable() +@serializable(canonical_name="SyncDirection", version=1) class SyncDirection(str, Enum): LOW_TO_HIGH = "low_to_high" HIGH_TO_LOW = "high_to_low" diff --git a/packages/syft/src/syft/custom_worker/config.py b/packages/syft/src/syft/custom_worker/config.py index 1b2d995d2bb..254d64b702e 100644 --- a/packages/syft/src/syft/custom_worker/config.py +++ b/packages/syft/src/syft/custom_worker/config.py @@ -83,7 +83,7 @@ class WorkerConfig(SyftBaseModel): pass -@serializable() +@serializable(canonical_name="CustomWorkerConfig", version=1) class CustomWorkerConfig(WorkerConfig): build: CustomBuildConfig version: str = "1" @@ -107,7 +107,7 @@ def get_signature(self) -> str: return sha256(self.json(sort_keys=True).encode()).hexdigest() -@serializable() +@serializable(canonical_name="PrebuiltWorkerConfig", version=1) class PrebuiltWorkerConfig(WorkerConfig): # tag that is already built and pushed in some registry tag: str @@ -126,7 +126,7 @@ def __hash__(self) -> int: return hash(self.tag) -@serializable() +@serializable(canonical_name="DockerWorkerConfig", version=1) class DockerWorkerConfig(WorkerConfig): dockerfile: str file_name: str | None = None diff --git a/packages/syft/src/syft/serde/lib_permissions.py b/packages/syft/src/syft/serde/lib_permissions.py index 98ae4968fa3..751f72df410 100644 --- a/packages/syft/src/syft/serde/lib_permissions.py +++ b/packages/syft/src/syft/serde/lib_permissions.py @@ -6,13 +6,13 @@ from .serializable import serializable -@serializable() +@serializable(canonical_name="CMPCRUDPermission", version=1) class CMPCRUDPermission(Enum): NONE_EXECUTE = 1 ALL_EXECUTE = 2 -@serializable() +@serializable(canonical_name="CMPPermission", version=1) class CMPPermission: @property def permissions_string(self) -> str: @@ -22,7 +22,7 @@ def __repr__(self) -> str: return self.permission_string -@serializable() +@serializable(canonical_name="CMPUserPermission", version=1) class CMPUserPermission(CMPPermission): def __init__(self, user_id: UID, permission: CMPCRUDPermission): self.user_id = user_id @@ -36,7 +36,7 @@ def __repr__(self) -> str: return self.permission_string -@serializable() +@serializable(canonical_name="CMPCompoundPermission", version=1) class CMPCompoundPermission(CMPPermission): def __init__(self, permission: CMPCRUDPermission): self.permissions = permission diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index d5df3e0ab7e..77ede49f96b 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -2,6 +2,7 @@ from collections.abc import Callable from enum import Enum from enum import EnumMeta +import os import sys import tempfile import types @@ -20,8 +21,8 @@ from .capnp import get_capnp_schema from .util import compatible_with_large_file_writes_capnp -TYPE_BANK = {} -MISSING_CANONICAL_NAME = [] +TYPE_BANK = {} # type: ignore +SYFT_CLASSES_MISSING_CANONICAL_NAME = [] recursive_scheme = get_capnp_schema("recursive_serde.capnp").RecursiveSerde @@ -84,7 +85,7 @@ def has_canonical_name_version( ) -> bool: cls_canonical_name = getattr(cls, "__canonical_name__", None) cls_version = getattr(cls, "__version__", None) - return (cls_canonical_name or cannonical_name) and (cls_version or version) + return bool(cls_canonical_name or cannonical_name) and bool(cls_version or version) def validate_cannonical_name_version( @@ -114,6 +115,27 @@ def validate_cannonical_name_version( return canonical_name, version # type: ignore +def skip_unregistered_class( + cls: type, canonical_name: str | None, version: str | None +) -> bool: + """ + Used to gather all classes that are missing canonical_name and version for development. + + Returns True if the class should be skipped, False otherwise. + """ + + search_unregistered_classes = ( + os.getenv("SYFT_SEARCH_UNREGISTERED_CLASSES", False) == "1" + ) + if not search_unregistered_classes: + return False + if not has_canonical_name_version(cls, canonical_name, version): + if cls.__module__.startswith("syft."): + SYFT_CLASSES_MISSING_CANONICAL_NAME.append(cls) + return True + return False + + def recursive_serde_register( cls: object | type, serialize: Callable | None = None, @@ -129,12 +151,10 @@ def recursive_serde_register( base_attrs = None attribute_list: set[str] = set() - alias_fqn = check_fqn_alias(cls) cls = type(cls) if not isinstance(cls, type) else cls - fqn = f"{cls.__module__}.{cls.__name__}" + # fqn = f"{cls.__module__}.{cls.__name__}" - if not has_canonical_name_version(cls, canonical_name, version): - MISSING_CANONICAL_NAME.append(cls) + if skip_unregistered_class(cls, canonical_name, version): return canonical_name, version = validate_cannonical_name_version( @@ -203,20 +223,16 @@ def recursive_serde_register( version, ) - TYPE_BANK[fqn] = serde_attributes + # TYPE_BANK[fqn] = serde_attributes SyftObjectRegistry.register_cls(canonical_name, version, serde_attributes) + alias_fqn = check_fqn_alias(cls) if isinstance(alias_fqn, tuple): for alias in alias_fqn: - TYPE_BANK[alias] = serde_attributes - - # TODO Refactor alias, required for typing.Any in python 3.12, - alias_canonical_name = alias - alias_version = 1 - SyftObjectRegistry.register_cls( - alias_canonical_name, alias_version, serde_attributes - ) + # TYPE_BANK[alias] = serde_attributes + alias_canonical_name = canonical_name + alias.__name__ + SyftObjectRegistry.register_cls(alias_canonical_name, 1, serde_attributes) def chunk_bytes( diff --git a/packages/syft/src/syft/serde/recursive_primitives.py b/packages/syft/src/syft/serde/recursive_primitives.py index 7e8a65c5884..9385219b8e0 100644 --- a/packages/syft/src/syft/serde/recursive_primitives.py +++ b/packages/syft/src/syft/serde/recursive_primitives.py @@ -378,6 +378,7 @@ def deserialize_path(path_type: type[TPath], buf: bytes) -> TPath: serialize=serialize_path, deserialize=functools.partial(deserialize_path, __path_type), canonical_name=f"pathlib_{__path_type.__name__}", + version=1, ) diff --git a/packages/syft/src/syft/serde/serializable.py b/packages/syft/src/syft/serde/serializable.py index 4dda2ee3af9..9a683dbcf57 100644 --- a/packages/syft/src/syft/serde/serializable.py +++ b/packages/syft/src/syft/serde/serializable.py @@ -19,6 +19,8 @@ def serializable( without: list[str] | None = None, inherit: bool | None = True, inheritable: bool | None = True, + canonical_name: str | None = None, + version: int | None = None, ) -> Callable[[T], T]: """ Recursively serialize attributes of the class. @@ -52,6 +54,8 @@ def rs_decorator(cls: T) -> T: exclude_attrs=without, inherit_attrs=inherit, inheritable_attrs=inheritable, + canonical_name=canonical_name, + version=version, ) return cls diff --git a/packages/syft/src/syft/serde/third_party.py b/packages/syft/src/syft/serde/third_party.py index de10bd9cc5b..90d84103360 100644 --- a/packages/syft/src/syft/serde/third_party.py +++ b/packages/syft/src/syft/serde/third_party.py @@ -142,6 +142,7 @@ def deserialize_series(blob: bytes) -> Series: serialize=lambda x: serialize(x.isoformat(), to_bytes=True), deserialize=lambda x: parser.parse(deserialize(x, from_bytes=True)).date(), canonical_name="datetime_date", + version=1, ) recursive_serde_register( @@ -149,6 +150,7 @@ def deserialize_series(blob: bytes) -> Series: serialize=lambda x: serialize(x.value, to_bytes=True), deserialize=lambda x: Timestamp(deserialize(x, from_bytes=True)), canonical_name="pandas_timestamp", + version=1, ) @@ -177,6 +179,7 @@ def _serialize_dicttuple(x: DictTuple) -> bytes: serialize=serialize_type, deserialize=deserialize_type, canonical_name="empty_type", + version=1, ) diff --git a/packages/syft/src/syft/server/credentials.py b/packages/syft/src/syft/server/credentials.py index 35380a11ae3..4b811aa0db5 100644 --- a/packages/syft/src/syft/server/credentials.py +++ b/packages/syft/src/syft/server/credentials.py @@ -17,7 +17,7 @@ SIGNING_KEY_FOR = "Corresponding Public Key" -@serializable() +@serializable(canonical_name="SyftVerifyKey", version=1) class SyftVerifyKey(SyftBaseModel): verify_key: VerifyKey @@ -49,7 +49,7 @@ def __hash__(self) -> int: return hash(self.verify_key) -@serializable() +@serializable(canonical_name="SyftSigningKey", version=1) class SyftSigningKey(SyftBaseModel): signing_key: SigningKey @@ -97,7 +97,7 @@ def __eq__(self, other: Any) -> bool: SyftCredentials = SyftVerifyKey | SyftSigningKey -@serializable() +@serializable(canonical_name="UserLoginCredentials", version=1) class UserLoginCredentials(SyftBaseModel): email: str password: str diff --git a/packages/syft/src/syft/server/datasite.py b/packages/syft/src/syft/server/datasite.py index 3ff677e5a29..97fe976721a 100644 --- a/packages/syft/src/syft/server/datasite.py +++ b/packages/syft/src/syft/server/datasite.py @@ -3,6 +3,6 @@ from .server import Server -@serializable(without=["queue_manager"]) +@serializable(without=["queue_manager"], canonical_name="Datasite", version=1) class Datasite(Server): pass diff --git a/packages/syft/src/syft/server/enclave.py b/packages/syft/src/syft/server/enclave.py index b2ae0007ca5..919916c4581 100644 --- a/packages/syft/src/syft/server/enclave.py +++ b/packages/syft/src/syft/server/enclave.py @@ -4,7 +4,7 @@ from .server import Server -@serializable() +@serializable(canonical_name="Enclave", version=1) class Enclave(Server): def post_init(self) -> None: self.server_type = ServerType.ENCLAVE diff --git a/packages/syft/src/syft/server/gateway.py b/packages/syft/src/syft/server/gateway.py index 55fe0322178..47e7b1c2475 100644 --- a/packages/syft/src/syft/server/gateway.py +++ b/packages/syft/src/syft/server/gateway.py @@ -4,7 +4,7 @@ from .server import Server -@serializable() +@serializable(canonical_name="Gateway", version=1) class Gateway(Server): def post_init(self) -> None: self.server_type = ServerType.GATEWAY diff --git a/packages/syft/src/syft/server/service_registry.py b/packages/syft/src/syft/server/service_registry.py index 0d8ecc5d996..d7c3555f10c 100644 --- a/packages/syft/src/syft/server/service_registry.py +++ b/packages/syft/src/syft/server/service_registry.py @@ -46,7 +46,7 @@ from .server import Server -@serializable() +@serializable(canonical_name="ServiceRegistry", version=1) @dataclass class ServiceRegistry: action: ActionService diff --git a/packages/syft/src/syft/server/worker.py b/packages/syft/src/syft/server/worker.py index fef642cfba9..2658492d6fc 100644 --- a/packages/syft/src/syft/server/worker.py +++ b/packages/syft/src/syft/server/worker.py @@ -3,6 +3,6 @@ from .server import Server -@serializable() +@serializable(canonical_name="Worker", version=1) class Worker(Server): pass diff --git a/packages/syft/src/syft/service/action/action_object.py b/packages/syft/src/syft/service/action/action_object.py index 318d81bec2c..ea6c1fb6d9f 100644 --- a/packages/syft/src/syft/service/action/action_object.py +++ b/packages/syft/src/syft/service/action/action_object.py @@ -75,14 +75,14 @@ NoneType = type(None) -@serializable() +@serializable(canonical_name="TwinMode", version=1) class TwinMode(Enum): NONE = 0 PRIVATE = 1 MOCK = 2 -@serializable() +@serializable(canonical_name="ActionType", version=1) class ActionType(Enum): GETATTRIBUTE = 1 METHOD = 2 diff --git a/packages/syft/src/syft/service/action/action_permissions.py b/packages/syft/src/syft/service/action/action_permissions.py index 77bba2474dc..03992eeab07 100644 --- a/packages/syft/src/syft/service/action/action_permissions.py +++ b/packages/syft/src/syft/service/action/action_permissions.py @@ -8,7 +8,7 @@ from ...types.uid import UID -@serializable() +@serializable(canonical_name="ActionPermission", version=1) class ActionPermission(Enum): OWNER = 1 READ = 2 @@ -26,7 +26,7 @@ class ActionPermission(Enum): } -@serializable() +@serializable(canonical_name="ActionObjectPermission", version=1) class ActionObjectPermission: def __init__( self, @@ -108,7 +108,7 @@ def __init__(self, uid: UID, credentials: SyftVerifyKey): self.permission = ActionPermission.EXECUTE -@serializable() +@serializable(canonical_name="StoragePermission", version=1) class StoragePermission: def __init__(self, uid: UID, server_uid: UID): self.uid = uid diff --git a/packages/syft/src/syft/service/action/action_service.py b/packages/syft/src/syft/service/action/action_service.py index ab3b8c51fba..c78ad0a819d 100644 --- a/packages/syft/src/syft/service/action/action_service.py +++ b/packages/syft/src/syft/service/action/action_service.py @@ -52,7 +52,7 @@ logger = logging.getLogger(__name__) -@serializable() +@serializable(canonical_name="ActionService", version=1) class ActionService(AbstractService): store_type = ActionStore diff --git a/packages/syft/src/syft/service/action/action_store.py b/packages/syft/src/syft/service/action/action_store.py index 46270fd9c4d..250b3c5e9b5 100644 --- a/packages/syft/src/syft/service/action/action_store.py +++ b/packages/syft/src/syft/service/action/action_store.py @@ -38,7 +38,7 @@ class ActionStore: pass -@serializable() +@serializable(canonical_name="KeyValueActionStore", version=1) class KeyValueActionStore(ActionStore): """Generic Key-Value Action store. @@ -371,7 +371,7 @@ def migrate_data( return Err("You don't have permissions to migrate data.") -@serializable() +@serializable(canonical_name="DictActionStore", version=1) class DictActionStore(KeyValueActionStore): """Dictionary-Based Key-Value Action store. @@ -398,7 +398,7 @@ def __init__( ) -@serializable() +@serializable(canonical_name="SQLiteActionStore", version=1) class SQLiteActionStore(KeyValueActionStore): """SQLite-Based Key-Value Action store. @@ -412,7 +412,7 @@ class SQLiteActionStore(KeyValueActionStore): pass -@serializable() +@serializable(canonical_name="MongoActionStore", version=1) class MongoActionStore(KeyValueActionStore): """Mongo-Based Action store. diff --git a/packages/syft/src/syft/service/api/api_service.py b/packages/syft/src/syft/service/api/api_service.py index c6e5b639c93..87051d9b4b4 100644 --- a/packages/syft/src/syft/service/api/api_service.py +++ b/packages/syft/src/syft/service/api/api_service.py @@ -37,7 +37,7 @@ @instrument -@serializable() +@serializable(canonical_name="APIService", version=1) class APIService(AbstractService): store: DocumentStore stash: TwinAPIEndpointStash diff --git a/packages/syft/src/syft/service/api/api_stash.py b/packages/syft/src/syft/service/api/api_stash.py index 0725dbb9d4a..3b6daac1422 100644 --- a/packages/syft/src/syft/service/api/api_stash.py +++ b/packages/syft/src/syft/service/api/api_stash.py @@ -16,7 +16,7 @@ MISSING_PATH_STRING = "Endpoint path: {path} does not exist." -@serializable() +@serializable(canonical_name="TwinAPIEndpointStash", version=1) class TwinAPIEndpointStash(BaseUIDStoreStash): object_type = TwinAPIEndpoint settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/attestation/attestation_service.py b/packages/syft/src/syft/service/attestation/attestation_service.py index 82a8348dc68..87289278bf3 100644 --- a/packages/syft/src/syft/service/attestation/attestation_service.py +++ b/packages/syft/src/syft/service/attestation/attestation_service.py @@ -19,7 +19,7 @@ from .attestation_constants import ATTEST_GPU_ENDPOINT -@serializable() +@serializable(canonical_name="AttestationService", version=1) class AttestationService(AbstractService): """This service is responsible for getting all sorts of attestations for any client.""" diff --git a/packages/syft/src/syft/service/blob_storage/remote_profile.py b/packages/syft/src/syft/service/blob_storage/remote_profile.py index 7ff8f76427d..c2a0d8facad 100644 --- a/packages/syft/src/syft/service/blob_storage/remote_profile.py +++ b/packages/syft/src/syft/service/blob_storage/remote_profile.py @@ -24,7 +24,7 @@ class AzureRemoteProfile(RemoteProfile): container_name: str -@serializable() +@serializable(canonical_name="RemoteProfileStash", version=1) class RemoteProfileStash(BaseUIDStoreStash): object_type = RemoteProfile settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/blob_storage/service.py b/packages/syft/src/syft/service/blob_storage/service.py index ff2c1e6a4d8..dfcddbe2c66 100644 --- a/packages/syft/src/syft/service/blob_storage/service.py +++ b/packages/syft/src/syft/service/blob_storage/service.py @@ -35,7 +35,7 @@ BlobDepositType = OnDiskBlobDeposit | SeaweedFSBlobDeposit -@serializable() +@serializable(canonical_name="BlobStorageService", version=1) class BlobStorageService(AbstractService): store: DocumentStore stash: BlobStorageStash diff --git a/packages/syft/src/syft/service/blob_storage/stash.py b/packages/syft/src/syft/service/blob_storage/stash.py index 33456a67fe3..8fc93a4f034 100644 --- a/packages/syft/src/syft/service/blob_storage/stash.py +++ b/packages/syft/src/syft/service/blob_storage/stash.py @@ -6,7 +6,7 @@ from ...types.blob_storage import BlobStorageEntry -@serializable() +@serializable(canonical_name="BlobStorageStash", version=1) class BlobStorageStash(BaseUIDStoreStash): object_type = BlobStorageEntry settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/code/status_service.py b/packages/syft/src/syft/service/code/status_service.py index 20b5fc0d47e..2baafb2ea57 100644 --- a/packages/syft/src/syft/service/code/status_service.py +++ b/packages/syft/src/syft/service/code/status_service.py @@ -25,7 +25,7 @@ @instrument -@serializable() +@serializable(canonical_name="StatusStash", version=1) class StatusStash(BaseUIDStoreStash): object_type = UserCodeStatusCollection settings: PartitionSettings = PartitionSettings( @@ -47,7 +47,7 @@ def get_by_uid( @instrument -@serializable() +@serializable(canonical_name="UserCodeStatusService", version=1) class UserCodeStatusService(AbstractService): store: DocumentStore stash: StatusStash diff --git a/packages/syft/src/syft/service/code/user_code.py b/packages/syft/src/syft/service/code/user_code.py index 299c80a47c4..9be2c11869b 100644 --- a/packages/syft/src/syft/service/code/user_code.py +++ b/packages/syft/src/syft/service/code/user_code.py @@ -126,7 +126,7 @@ PyCodeObject = Any -@serializable() +@serializable(canonical_name="UserCodeStatus", version=1) class UserCodeStatus(Enum): PENDING = "pending" DENIED = "denied" diff --git a/packages/syft/src/syft/service/code/user_code_service.py b/packages/syft/src/syft/service/code/user_code_service.py index 05cba51a6b8..10854e6f421 100644 --- a/packages/syft/src/syft/service/code/user_code_service.py +++ b/packages/syft/src/syft/service/code/user_code_service.py @@ -50,7 +50,7 @@ @instrument -@serializable() +@serializable(canonical_name="UserCodeService", version=1) class UserCodeService(AbstractService): store: DocumentStore stash: UserCodeStash diff --git a/packages/syft/src/syft/service/code/user_code_stash.py b/packages/syft/src/syft/service/code/user_code_stash.py index 6586fbc709c..0fcb41b2087 100644 --- a/packages/syft/src/syft/service/code/user_code_stash.py +++ b/packages/syft/src/syft/service/code/user_code_stash.py @@ -19,7 +19,7 @@ @instrument -@serializable() +@serializable(canonical_name="UserCodeStash", version=1) class UserCodeStash(BaseUIDStoreStash): object_type = UserCode settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/code_history/code_history_service.py b/packages/syft/src/syft/service/code_history/code_history_service.py index 2e0253a5838..762d7c5da91 100644 --- a/packages/syft/src/syft/service/code_history/code_history_service.py +++ b/packages/syft/src/syft/service/code_history/code_history_service.py @@ -25,7 +25,7 @@ @instrument -@serializable() +@serializable(canonical_name="CodeHistoryService", version=1) class CodeHistoryService(AbstractService): store: DocumentStore stash: CodeHistoryStash diff --git a/packages/syft/src/syft/service/code_history/code_history_stash.py b/packages/syft/src/syft/service/code_history/code_history_stash.py index cc8a4fa5cc3..c419416664a 100644 --- a/packages/syft/src/syft/service/code_history/code_history_stash.py +++ b/packages/syft/src/syft/service/code_history/code_history_stash.py @@ -17,7 +17,7 @@ VerifyKeyPartitionKey = PartitionKey(key="user_verify_key", type_=SyftVerifyKey) -@serializable() +@serializable(canonical_name="CodeHistoryStash", version=1) class CodeHistoryStash(BaseUIDStoreStash): object_type = CodeHistory settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/data_subject/data_subject_member_service.py b/packages/syft/src/syft/service/data_subject/data_subject_member_service.py index 174ea963399..097c14a6ffa 100644 --- a/packages/syft/src/syft/service/data_subject/data_subject_member_service.py +++ b/packages/syft/src/syft/service/data_subject/data_subject_member_service.py @@ -23,7 +23,7 @@ @instrument -@serializable() +@serializable(canonical_name="DataSubjectMemberStash", version=1) class DataSubjectMemberStash(BaseUIDStoreStash): object_type = DataSubjectMemberRelationship settings: PartitionSettings = PartitionSettings( @@ -48,7 +48,7 @@ def get_all_for_child( @instrument -@serializable() +@serializable(canonical_name="DataSubjectMemberService", version=1) class DataSubjectMemberService(AbstractService): store: DocumentStore stash: DataSubjectMemberStash diff --git a/packages/syft/src/syft/service/data_subject/data_subject_service.py b/packages/syft/src/syft/service/data_subject/data_subject_service.py index 4e919f355f7..dfcd20b7110 100644 --- a/packages/syft/src/syft/service/data_subject/data_subject_service.py +++ b/packages/syft/src/syft/service/data_subject/data_subject_service.py @@ -25,7 +25,7 @@ @instrument -@serializable() +@serializable(canonical_name="DataSubjectStash", version=1) class DataSubjectStash(BaseUIDStoreStash): object_type = DataSubject settings: PartitionSettings = PartitionSettings( @@ -55,7 +55,7 @@ def update( @instrument -@serializable() +@serializable(canonical_name="DataSubjectService", version=1) class DataSubjectService(AbstractService): store: DocumentStore stash: DataSubjectStash diff --git a/packages/syft/src/syft/service/dataset/dataset_service.py b/packages/syft/src/syft/service/dataset/dataset_service.py index ae05d9bee69..3eeaaf80551 100644 --- a/packages/syft/src/syft/service/dataset/dataset_service.py +++ b/packages/syft/src/syft/service/dataset/dataset_service.py @@ -66,7 +66,7 @@ def _paginate_dataset_collection( @instrument -@serializable() +@serializable(canonical_name="DatasetService", version=1) class DatasetService(AbstractService): store: DocumentStore stash: DatasetStash diff --git a/packages/syft/src/syft/service/dataset/dataset_stash.py b/packages/syft/src/syft/service/dataset/dataset_stash.py index 3788f939ea8..6846af8220a 100644 --- a/packages/syft/src/syft/service/dataset/dataset_stash.py +++ b/packages/syft/src/syft/service/dataset/dataset_stash.py @@ -21,7 +21,7 @@ @instrument -@serializable() +@serializable(canonical_name="DatasetStash", version=1) class DatasetStash(BaseUIDStoreStash): object_type = Dataset settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/enclave/enclave_service.py b/packages/syft/src/syft/service/enclave/enclave_service.py index 0807ada8da0..2f88c60e123 100644 --- a/packages/syft/src/syft/service/enclave/enclave_service.py +++ b/packages/syft/src/syft/service/enclave/enclave_service.py @@ -6,7 +6,7 @@ from ..service import AbstractService -@serializable() +@serializable(canonical_name="EnclaveService", version=1) class EnclaveService(AbstractService): store: DocumentStore diff --git a/packages/syft/src/syft/service/job/job_service.py b/packages/syft/src/syft/service/job/job_service.py index 7cff1f6272e..3cfbe356f09 100644 --- a/packages/syft/src/syft/service/job/job_service.py +++ b/packages/syft/src/syft/service/job/job_service.py @@ -45,7 +45,7 @@ def wait_until( @instrument -@serializable() +@serializable(canonical_name="JobService", version=1) class JobService(AbstractService): store: DocumentStore stash: JobStash diff --git a/packages/syft/src/syft/service/job/job_stash.py b/packages/syft/src/syft/service/job/job_stash.py index 617bded3eed..53a1a1a8dae 100644 --- a/packages/syft/src/syft/service/job/job_stash.py +++ b/packages/syft/src/syft/service/job/job_stash.py @@ -57,7 +57,7 @@ from .html_template import job_repr_template -@serializable() +@serializable(canonical_name="JobStatus", version=1) class JobStatus(str, Enum): CREATED = "created" PROCESSING = "processing" @@ -108,7 +108,7 @@ class JobV4(SyncableSyftObject): __exclude_sync_diff_attrs__ = ["action"] -@serializable() +@serializable(canonical_name="JobType", version=1) class JobType(str, Enum): JOB = "job" TWINAPIJOB = "twinapijob" @@ -869,7 +869,7 @@ def from_job( @instrument -@serializable() +@serializable(canonical_name="JobStash", version=1) class JobStash(BaseUIDStoreStash): object_type = Job settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/log/log_service.py b/packages/syft/src/syft/service/log/log_service.py index 5e3666ed32b..8925b88a1a0 100644 --- a/packages/syft/src/syft/service/log/log_service.py +++ b/packages/syft/src/syft/service/log/log_service.py @@ -17,7 +17,7 @@ @instrument -@serializable() +@serializable(canonical_name="LogService", version=1) class LogService(AbstractService): store: DocumentStore stash: LogStash diff --git a/packages/syft/src/syft/service/log/log_stash.py b/packages/syft/src/syft/service/log/log_stash.py index f1c37d9f6b2..54657982633 100644 --- a/packages/syft/src/syft/service/log/log_stash.py +++ b/packages/syft/src/syft/service/log/log_stash.py @@ -8,7 +8,7 @@ @instrument -@serializable() +@serializable(canonical_name="LogStash", version=1) class LogStash(BaseUIDStoreStash): object_type = SyftLog settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/metadata/metadata_service.py b/packages/syft/src/syft/service/metadata/metadata_service.py index 0169941fc8f..ccdb0c0a8ec 100644 --- a/packages/syft/src/syft/service/metadata/metadata_service.py +++ b/packages/syft/src/syft/service/metadata/metadata_service.py @@ -12,7 +12,7 @@ @instrument -@serializable() +@serializable(canonical_name="MetadataService", version=1) class MetadataService(AbstractService): def __init__(self, store: DocumentStore) -> None: self.store = store diff --git a/packages/syft/src/syft/service/metadata/server_metadata.py b/packages/syft/src/syft/service/metadata/server_metadata.py index 96fb87d6e2a..073f3738dbb 100644 --- a/packages/syft/src/syft/service/metadata/server_metadata.py +++ b/packages/syft/src/syft/service/metadata/server_metadata.py @@ -95,7 +95,7 @@ def check_version(self, client_version: str) -> bool: ) -@serializable() +@serializable(canonical_name="ServerMetadataJSON", version=1) class ServerMetadataJSON(BaseModel, StorableObjectType): metadata_version: int name: str diff --git a/packages/syft/src/syft/service/migration/migration_service.py b/packages/syft/src/syft/service/migration/migration_service.py index fe1fd9335b8..0075768f9ce 100644 --- a/packages/syft/src/syft/service/migration/migration_service.py +++ b/packages/syft/src/syft/service/migration/migration_service.py @@ -31,7 +31,7 @@ from .object_migration_state import SyftObjectMigrationState -@serializable() +@serializable(canonical_name="MigrationService", version=1) class MigrationService(AbstractService): store: DocumentStore stash: SyftMigrationStateStash diff --git a/packages/syft/src/syft/service/migration/object_migration_state.py b/packages/syft/src/syft/service/migration/object_migration_state.py index 897be6921b4..bb15c9faafa 100644 --- a/packages/syft/src/syft/service/migration/object_migration_state.py +++ b/packages/syft/src/syft/service/migration/object_migration_state.py @@ -62,7 +62,7 @@ def supported_versions(self) -> list: KlassNamePartitionKey = PartitionKey(key="canonical_name", type_=str) -@serializable() +@serializable(canonical_name="SyftMigrationStateStash", version=1) class SyftMigrationStateStash(BaseStash): object_type = SyftObjectMigrationState settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/network/network_service.py b/packages/syft/src/syft/service/network/network_service.py index 1d313bbe362..24f117b7323 100644 --- a/packages/syft/src/syft/service/network/network_service.py +++ b/packages/syft/src/syft/service/network/network_service.py @@ -74,7 +74,7 @@ def reverse_tunnel_enabled() -> bool: return str_to_bool(get_env(REVERSE_TUNNEL_ENABLED, "false")) -@serializable() +@serializable(canonical_name="ServerPeerAssociationStatus", version=1) class ServerPeerAssociationStatus(Enum): PEER_ASSOCIATED = "PEER_ASSOCIATED" PEER_ASSOCIATION_PENDING = "PEER_ASSOCIATION_PENDING" @@ -82,7 +82,7 @@ class ServerPeerAssociationStatus(Enum): @instrument -@serializable() +@serializable(canonical_name="NetworkStash", version=1) class NetworkStash(BaseUIDStoreStash): object_type = ServerPeer settings: PartitionSettings = PartitionSettings( @@ -157,7 +157,7 @@ def get_by_server_type( @instrument -@serializable() +@serializable(canonical_name="NetworkService", version=1) class NetworkService(AbstractService): store: DocumentStore stash: NetworkStash diff --git a/packages/syft/src/syft/service/network/rathole.py b/packages/syft/src/syft/service/network/rathole.py index 98280a52ccb..96abcd08af6 100644 --- a/packages/syft/src/syft/service/network/rathole.py +++ b/packages/syft/src/syft/service/network/rathole.py @@ -12,7 +12,7 @@ def get_rathole_port() -> int: return int(get_env("RATHOLE_PORT", "2333")) -@serializable() +@serializable(canonical_name="RatholeConfig", version=1) class RatholeConfig(SyftBaseModel): uuid: str secret_token: str diff --git a/packages/syft/src/syft/service/network/server_peer.py b/packages/syft/src/syft/service/network/server_peer.py index 330cf2ba511..4d237175a28 100644 --- a/packages/syft/src/syft/service/network/server_peer.py +++ b/packages/syft/src/syft/service/network/server_peer.py @@ -39,7 +39,7 @@ logger = logging.getLogger(__name__) -@serializable() +@serializable(canonical_name="ServerPeerConnectionStatus", version=1) class ServerPeerConnectionStatus(Enum): ACTIVE = "ACTIVE" INACTIVE = "INACTIVE" diff --git a/packages/syft/src/syft/service/network/utils.py b/packages/syft/src/syft/service/network/utils.py index 423fa61fa2d..c5b9e0c084e 100644 --- a/packages/syft/src/syft/service/network/utils.py +++ b/packages/syft/src/syft/service/network/utils.py @@ -18,7 +18,7 @@ logger = logging.getLogger(__name__) -@serializable(without=["thread"]) +@serializable(without=["thread"], canonical_name="PeerHealthCheckTask", version=1) class PeerHealthCheckTask: repeat_time = 10 # in seconds diff --git a/packages/syft/src/syft/service/notification/notification_service.py b/packages/syft/src/syft/service/notification/notification_service.py index 7e741847b99..9873a78ad2c 100644 --- a/packages/syft/src/syft/service/notification/notification_service.py +++ b/packages/syft/src/syft/service/notification/notification_service.py @@ -26,7 +26,7 @@ @instrument -@serializable() +@serializable(canonical_name="NotificationService", version=1) class NotificationService(AbstractService): store: DocumentStore stash: NotificationStash diff --git a/packages/syft/src/syft/service/notification/notification_stash.py b/packages/syft/src/syft/service/notification/notification_stash.py index 6fe79875387..8521080fee5 100644 --- a/packages/syft/src/syft/service/notification/notification_stash.py +++ b/packages/syft/src/syft/service/notification/notification_stash.py @@ -33,7 +33,7 @@ @instrument -@serializable() +@serializable(canonical_name="NotificationStash", version=1) class NotificationStash(BaseUIDStoreStash): object_type = Notification settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/notification/notifications.py b/packages/syft/src/syft/service/notification/notifications.py index 72d77c8039d..a7bb7aa5a3d 100644 --- a/packages/syft/src/syft/service/notification/notifications.py +++ b/packages/syft/src/syft/service/notification/notifications.py @@ -24,13 +24,13 @@ from .email_templates import EmailTemplate -@serializable() +@serializable(canonical_name="NotificationStatus", version=1) class NotificationStatus(Enum): UNREAD = 0 READ = 1 -@serializable() +@serializable(canonical_name="NotificationRequestStatus", version=1) class NotificationRequestStatus(Enum): NO_ACTION = 0 diff --git a/packages/syft/src/syft/service/notifier/notifier_enums.py b/packages/syft/src/syft/service/notifier/notifier_enums.py index 0cb438b4fb2..023843f7d6c 100644 --- a/packages/syft/src/syft/service/notifier/notifier_enums.py +++ b/packages/syft/src/syft/service/notifier/notifier_enums.py @@ -6,7 +6,7 @@ from ...serde.serializable import serializable -@serializable() +@serializable(canonical_name="NOTIFIERS", version=1) class NOTIFIERS(Enum): EMAIL = auto() SMS = auto() diff --git a/packages/syft/src/syft/service/notifier/notifier_service.py b/packages/syft/src/syft/service/notifier/notifier_service.py index ff2696a1be7..a201c850c22 100644 --- a/packages/syft/src/syft/service/notifier/notifier_service.py +++ b/packages/syft/src/syft/service/notifier/notifier_service.py @@ -25,7 +25,7 @@ logger = logging.getLogger(__name__) -@serializable() +@serializable(canonical_name="NotifierService", version=1) class NotifierService(AbstractService): store: DocumentStore stash: NotifierStash # Which stash should we use? diff --git a/packages/syft/src/syft/service/notifier/notifier_stash.py b/packages/syft/src/syft/service/notifier/notifier_stash.py index a9e218e509f..1d28c90a380 100644 --- a/packages/syft/src/syft/service/notifier/notifier_stash.py +++ b/packages/syft/src/syft/service/notifier/notifier_stash.py @@ -23,7 +23,7 @@ @instrument -@serializable() +@serializable(canonical_name="NotifierStash", version=1) class NotifierStash(BaseStash): object_type = NotifierSettings settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/output/output_service.py b/packages/syft/src/syft/service/output/output_service.py index 373c6113e51..8c45a18af86 100644 --- a/packages/syft/src/syft/service/output/output_service.py +++ b/packages/syft/src/syft/service/output/output_service.py @@ -225,7 +225,7 @@ def get_sync_dependencies(self, context: AuthedServiceContext) -> list[UID]: @instrument -@serializable() +@serializable(canonical_name="OutputStash", version=1) class OutputStash(BaseUIDStoreStash): object_type = ExecutionOutput settings: PartitionSettings = PartitionSettings( @@ -290,7 +290,7 @@ def downgrade_execution_output() -> list[Callable]: @instrument -@serializable() +@serializable(canonical_name="OutputService", version=1) class OutputService(AbstractService): store: DocumentStore stash: OutputStash diff --git a/packages/syft/src/syft/service/policy/policy.py b/packages/syft/src/syft/service/policy/policy.py index 3b0e4468dd8..c1a0fc046cb 100644 --- a/packages/syft/src/syft/service/policy/policy.py +++ b/packages/syft/src/syft/service/policy/policy.py @@ -133,7 +133,7 @@ def public_state(self) -> Any: raise NotImplementedError -@serializable() +@serializable(canonical_name="UserPolicyStatus", version=1) class UserPolicyStatus(Enum): SUBMITTED = "submitted" DENIED = "denied" @@ -431,7 +431,7 @@ def __init__( kwarg_rules_current_server[kw] = Matches( kw=kw, val=user_code_arg2id(arg) ) - elif arg in [str, float, int, bool, dict, list, set, tuple]: + elif arg in [str, float, int, bool, dict, list, set, tuple]: # type: ignore[unreachable] kwarg_rules_current_server[kw] = UserOwned(kw=kw, type=arg) elif isinstance(arg, CreatePolicyRule): kwarg_rules_current_server[kw] = arg.to_policy_rule(kw) @@ -802,7 +802,7 @@ class OutputPolicyExecuteOnce(OutputPolicyExecuteCount): SingleExecutionExactOutput = OutputPolicyExecuteOnce -@serializable() +@serializable(canonical_name="CustomPolicy", version=1) class CustomPolicy(type): # capture the init_kwargs transparently def __call__(cls, *args: Any, **kwargs: Any) -> None: @@ -814,7 +814,7 @@ def __call__(cls, *args: Any, **kwargs: Any) -> None: recursive_serde_register_type(CustomPolicy, canonical_name="CustomPolicy", version=1) -@serializable() +@serializable(canonical_name="CustomOutputPolicy", version=1) class CustomOutputPolicy(metaclass=CustomPolicy): def apply_to_output( self, diff --git a/packages/syft/src/syft/service/policy/policy_service.py b/packages/syft/src/syft/service/policy/policy_service.py index 23b89dd478d..bea4c2a66ae 100644 --- a/packages/syft/src/syft/service/policy/policy_service.py +++ b/packages/syft/src/syft/service/policy/policy_service.py @@ -15,7 +15,7 @@ from .user_policy_stash import UserPolicyStash -@serializable() +@serializable(canonical_name="PolicyService", version=1) class PolicyService(AbstractService): store: DocumentStore stash: UserPolicyStash diff --git a/packages/syft/src/syft/service/policy/user_policy_stash.py b/packages/syft/src/syft/service/policy/user_policy_stash.py index df1413bed6d..4779be12215 100644 --- a/packages/syft/src/syft/service/policy/user_policy_stash.py +++ b/packages/syft/src/syft/service/policy/user_policy_stash.py @@ -14,7 +14,7 @@ from .policy import UserPolicy -@serializable() +@serializable(canonical_name="UserPolicyStash", version=1) class UserPolicyStash(BaseUIDStoreStash): object_type = UserPolicy settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/project/project.py b/packages/syft/src/syft/service/project/project.py index dd9608e3eea..e3a3d292951 100644 --- a/packages/syft/src/syft/service/project/project.py +++ b/packages/syft/src/syft/service/project/project.py @@ -55,7 +55,7 @@ from ..user.user import UserView -@serializable() +@serializable(canonical_name="EventAlreadyAddedException", version=1) class EventAlreadyAddedException(SyftException): pass @@ -601,7 +601,7 @@ class ConsensusModel: pass -@serializable() +@serializable(canonical_name="DemocraticConsensusModel", version=1) class DemocraticConsensusModel(ConsensusModel): threshold: float = 50 diff --git a/packages/syft/src/syft/service/project/project_service.py b/packages/syft/src/syft/service/project/project_service.py index 1b29bb9dd89..0da9d043e18 100644 --- a/packages/syft/src/syft/service/project/project_service.py +++ b/packages/syft/src/syft/service/project/project_service.py @@ -28,7 +28,7 @@ @instrument -@serializable() +@serializable(canonical_name="ProjectService", version=1) class ProjectService(AbstractService): store: DocumentStore stash: ProjectStash diff --git a/packages/syft/src/syft/service/project/project_stash.py b/packages/syft/src/syft/service/project/project_stash.py index 12759272ae5..dcd258938b3 100644 --- a/packages/syft/src/syft/service/project/project_stash.py +++ b/packages/syft/src/syft/service/project/project_stash.py @@ -22,7 +22,7 @@ @instrument -@serializable() +@serializable(canonical_name="ProjectStash", version=1) class ProjectStash(BaseUIDStoreStash): object_type = Project settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/queue/base_queue.py b/packages/syft/src/syft/service/queue/base_queue.py index 415c1b110d5..aed6f2244d4 100644 --- a/packages/syft/src/syft/service/queue/base_queue.py +++ b/packages/syft/src/syft/service/queue/base_queue.py @@ -12,12 +12,12 @@ from ..worker.worker_stash import WorkerStash -@serializable() +@serializable(canonical_name="QueueClientConfig", version=1) class QueueClientConfig: pass -@serializable() +@serializable(canonical_name="AbstractMessageHandler", version=1) class AbstractMessageHandler: queue_name: ClassVar[str] @@ -26,7 +26,11 @@ def handle_message(message: bytes, syft_worker_id: UID) -> None: raise NotImplementedError -@serializable(attrs=["message_handler", "queue_name", "address"]) +@serializable( + attrs=["message_handler", "queue_name", "address"], + canonical_name="QueueConsumer", + version=1, +) class QueueConsumer: message_handler: AbstractMessageHandler queue_name: str @@ -42,7 +46,7 @@ def close(self) -> None: raise NotImplementedError -@serializable() +@serializable(canonical_name="QueueProducer", version=1) class QueueProducer: queue_name: str @@ -61,13 +65,13 @@ def close(self) -> None: raise NotImplementedError -@serializable() +@serializable(canonical_name="QueueClient", version=1) class QueueClient: def __init__(self, config: QueueClientConfig) -> None: raise NotImplementedError -@serializable() +@serializable(canonical_name="QueueConfig", version=1) class QueueConfig: """Base Queue configuration""" @@ -75,7 +79,7 @@ class QueueConfig: client_config: QueueClientConfig -@serializable() +@serializable(canonical_name="BaseQueueManager", version=1) class BaseQueueManager: config: QueueConfig diff --git a/packages/syft/src/syft/service/queue/queue.py b/packages/syft/src/syft/service/queue/queue.py index a8ba85f46fc..67d3aa44a90 100644 --- a/packages/syft/src/syft/service/queue/queue.py +++ b/packages/syft/src/syft/service/queue/queue.py @@ -84,7 +84,7 @@ def terminate(self, job: Job) -> None: logger.warning(f"Failed to terminate job {job.id}: {e}") -@serializable() +@serializable(canonical_name="QueueManager", version=1) class QueueManager(BaseQueueManager): config: QueueConfig @@ -246,7 +246,7 @@ def handle_message_multiprocessing( monitor_thread.stop() -@serializable() +@serializable(canonical_name="APICallMessageHandler", version=1) class APICallMessageHandler(AbstractMessageHandler): queue_name = "api_call" diff --git a/packages/syft/src/syft/service/queue/queue_service.py b/packages/syft/src/syft/service/queue/queue_service.py index d1cf119076a..1c56b494b02 100644 --- a/packages/syft/src/syft/service/queue/queue_service.py +++ b/packages/syft/src/syft/service/queue/queue_service.py @@ -15,7 +15,7 @@ @instrument -@serializable() +@serializable(canonical_name="QueueService", version=1) class QueueService(AbstractService): store: DocumentStore stash: QueueStash diff --git a/packages/syft/src/syft/service/queue/queue_stash.py b/packages/syft/src/syft/service/queue/queue_stash.py index e7956da58de..13a46a82498 100644 --- a/packages/syft/src/syft/service/queue/queue_stash.py +++ b/packages/syft/src/syft/service/queue/queue_stash.py @@ -28,7 +28,7 @@ from ..response import SyftSuccess -@serializable() +@serializable(canonical_name="Status", version=1) class Status(str, Enum): CREATED = "created" PROCESSING = "processing" @@ -98,7 +98,7 @@ class APIEndpointQueueItem(QueueItem): @instrument -@serializable() +@serializable(canonical_name="QueueStash", version=1) class QueueStash(BaseStash): object_type = QueueItem settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/queue/zmq_queue.py b/packages/syft/src/syft/service/queue/zmq_queue.py index 3317c0ea447..1d3fd97a934 100644 --- a/packages/syft/src/syft/service/queue/zmq_queue.py +++ b/packages/syft/src/syft/service/queue/zmq_queue.py @@ -146,7 +146,7 @@ def __str__(self) -> str: ) -@serializable() +@serializable(canonical_name="ZMQProducer", version=1) class ZMQProducer(QueueProducer): INTERNAL_SERVICE_PREFIX = b"mmi." @@ -667,7 +667,7 @@ def alive(self) -> bool: return not self.socket.closed -@serializable(attrs=["_subscriber"]) +@serializable(attrs=["_subscriber"], canonical_name="ZMQConsumer", version=1) class ZMQConsumer(QueueConsumer): def __init__( self, @@ -905,7 +905,7 @@ class ZMQClientConfig(SyftObject, QueueClientConfig): consumer_service: str | None = None -@serializable(attrs=["host"]) +@serializable(attrs=["host"], canonical_name="ZMQClient", version=1) class ZMQClient(QueueClient): """ZMQ Client for creating producers and consumers.""" @@ -1044,7 +1044,7 @@ def purge_all(self) -> SyftError | SyftSuccess: return SyftSuccess(message="Successfully purged all queues.") -@serializable() +@serializable(canonical_name="ZMQQueueConfig", version=1) class ZMQQueueConfig(QueueConfig): def __init__( self, diff --git a/packages/syft/src/syft/service/request/request.py b/packages/syft/src/syft/service/request/request.py index b3a565b45a6..8468d29e067 100644 --- a/packages/syft/src/syft/service/request/request.py +++ b/packages/syft/src/syft/service/request/request.py @@ -65,7 +65,7 @@ logger = logging.getLogger(__name__) -@serializable() +@serializable(canonical_name="RequestStatus", version=1) class RequestStatus(Enum): PENDING = 0 REJECTED = 1 diff --git a/packages/syft/src/syft/service/request/request_service.py b/packages/syft/src/syft/service/request/request_service.py index 31ae60f228f..9adb82d283f 100644 --- a/packages/syft/src/syft/service/request/request_service.py +++ b/packages/syft/src/syft/service/request/request_service.py @@ -38,7 +38,7 @@ @instrument -@serializable() +@serializable(canonical_name="RequestService", version=1) class RequestService(AbstractService): store: DocumentStore stash: RequestStash diff --git a/packages/syft/src/syft/service/request/request_stash.py b/packages/syft/src/syft/service/request/request_stash.py index 4d603a057ec..b56bd6932e1 100644 --- a/packages/syft/src/syft/service/request/request_stash.py +++ b/packages/syft/src/syft/service/request/request_stash.py @@ -24,7 +24,7 @@ @instrument -@serializable() +@serializable(canonical_name="RequestStash", version=1) class RequestStash(BaseUIDStoreStash): object_type = Request settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/response.py b/packages/syft/src/syft/service/response.py index 2b2481f3964..ebecf9e2fcb 100644 --- a/packages/syft/src/syft/service/response.py +++ b/packages/syft/src/syft/service/response.py @@ -73,7 +73,7 @@ def _repr_html_(self) -> str: ) -@serializable() +@serializable(canonical_name="SyftError", version=1) class SyftError(SyftResponseMessage): _bool: bool = False @@ -88,14 +88,14 @@ def __bool__(self) -> bool: return False -@serializable() +@serializable(canonical_name="SyftSuccess", version=1) class SyftSuccess(SyftResponseMessage): @property def _repr_html_class_(self) -> str: return "alert-success" -@serializable() +@serializable(canonical_name="SyftNotReady", version=1) class SyftNotReady(SyftResponseMessage): _bool: bool = False @@ -104,14 +104,14 @@ def _repr_html_class_(self) -> str: return "alert-info" -@serializable() +@serializable(canonical_name="SyftWarning", version=1) class SyftWarning(SyftResponseMessage): @property def _repr_html_class_(self) -> str: return "alert-warning" -@serializable() +@serializable(canonical_name="SyftInfo", version=1) class SyftInfo(SyftResponseMessage): _bool: bool = False @@ -120,7 +120,7 @@ def _repr_html_class_(self) -> str: return "alert-info" -@serializable() +@serializable(canonical_name="SyftException", version=1) class SyftException(Exception): traceback: bool = False traceback_limit: int = 10 @@ -172,6 +172,6 @@ def syft_exception_handler( pass # nosec -@serializable() +@serializable(canonical_name="SyftAttributeError", version=1) class SyftAttributeError(AttributeError, SyftException): pass diff --git a/packages/syft/src/syft/service/settings/settings_service.py b/packages/syft/src/syft/service/settings/settings_service.py index a59773a0280..f1f56ce842d 100644 --- a/packages/syft/src/syft/service/settings/settings_service.py +++ b/packages/syft/src/syft/service/settings/settings_service.py @@ -33,7 +33,7 @@ from .settings_stash import SettingsStash -@serializable() +@serializable(canonical_name="SettingsService", version=1) class SettingsService(AbstractService): store: DocumentStore stash: SettingsStash diff --git a/packages/syft/src/syft/service/settings/settings_stash.py b/packages/syft/src/syft/service/settings/settings_stash.py index c97b2c960a4..52c134274f7 100644 --- a/packages/syft/src/syft/service/settings/settings_stash.py +++ b/packages/syft/src/syft/service/settings/settings_stash.py @@ -20,7 +20,7 @@ @instrument -@serializable() +@serializable(canonical_name="SettingsStash", version=1) class SettingsStash(BaseUIDStoreStash): object_type = ServerSettings settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/sync/sync_service.py b/packages/syft/src/syft/service/sync/sync_service.py index f3e1af9160d..2ec224e2fbc 100644 --- a/packages/syft/src/syft/service/sync/sync_service.py +++ b/packages/syft/src/syft/service/sync/sync_service.py @@ -49,7 +49,7 @@ def get_store(context: AuthedServiceContext, item: SyncableSyftObject) -> Any: @instrument -@serializable() +@serializable(canonical_name="SyncService", version=1) class SyncService(AbstractService): store: DocumentStore stash: SyncStash diff --git a/packages/syft/src/syft/service/sync/sync_stash.py b/packages/syft/src/syft/service/sync/sync_stash.py index ed044106c63..f83435e7785 100644 --- a/packages/syft/src/syft/service/sync/sync_stash.py +++ b/packages/syft/src/syft/service/sync/sync_stash.py @@ -21,7 +21,7 @@ @instrument -@serializable() +@serializable(canonical_name="SyncStash", version=1) class SyncStash(BaseUIDStoreStash): object_type = SyncState settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/user/user_roles.py b/packages/syft/src/syft/service/user/user_roles.py index 8177289a424..a879d32dcee 100644 --- a/packages/syft/src/syft/service/user/user_roles.py +++ b/packages/syft/src/syft/service/user/user_roles.py @@ -22,7 +22,7 @@ class ServiceRoleCapability(Enum): CAN_EDIT_DATASITE_SETTINGS = 512 -@serializable() +@serializable(canonical_name="ServiceRole", version=1) class ServiceRole(Enum): NONE = 0 GUEST = 1 diff --git a/packages/syft/src/syft/service/user/user_service.py b/packages/syft/src/syft/service/user/user_service.py index 71651496a21..59903e7a1de 100644 --- a/packages/syft/src/syft/service/user/user_service.py +++ b/packages/syft/src/syft/service/user/user_service.py @@ -46,7 +46,7 @@ @instrument -@serializable() +@serializable(canonical_name="UserService", version=1) class UserService(AbstractService): store: DocumentStore stash: UserStash diff --git a/packages/syft/src/syft/service/user/user_stash.py b/packages/syft/src/syft/service/user/user_stash.py index ff768757dc3..2b2b42db9e8 100644 --- a/packages/syft/src/syft/service/user/user_stash.py +++ b/packages/syft/src/syft/service/user/user_stash.py @@ -29,7 +29,7 @@ @instrument -@serializable() +@serializable(canonical_name="UserStash", version=1) class UserStash(BaseStash): object_type = User settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/warnings.py b/packages/syft/src/syft/service/warnings.py index 8b14df3a3a1..c028ca81f68 100644 --- a/packages/syft/src/syft/service/warnings.py +++ b/packages/syft/src/syft/service/warnings.py @@ -26,7 +26,7 @@ class WarningContext( role: ServiceRole -@serializable() +@serializable(canonical_name="APIEndpointWarning", version=1) class APIEndpointWarning(SyftBaseModel): confirmation: bool = False message: str | None = None @@ -68,7 +68,7 @@ def show(self) -> bool: return True -@serializable() +@serializable(canonical_name="CRUDWarning", version=1) class CRUDWarning(APIEndpointWarning): def message_from(self, context: WarningContext | None = None) -> Self: message = None @@ -94,7 +94,7 @@ def message_from(self, context: WarningContext | None = None) -> Self: return CRUDWarning(confirmation=confirmation, message=message) -@serializable() +@serializable(canonical_name="CRUDReminder", version=1) class CRUDReminder(CRUDWarning): confirmation: bool = False @@ -121,7 +121,7 @@ def message_from(self, context: WarningContext | None = None) -> Self: return CRUDReminder(confirmation=confirmation, message=message) -@serializable() +@serializable(canonical_name="LowSideCRUDWarning", version=1) class LowSideCRUDWarning(APIEndpointWarning): def message_from(self, context: WarningContext | None = None) -> Self: confirmation = self.confirmation @@ -141,7 +141,7 @@ def message_from(self, context: WarningContext | None = None) -> Self: return LowSideCRUDWarning(confirmation=confirmation, message=message) -@serializable() +@serializable(canonical_name="HighSideCRUDWarning", version=1) class HighSideCRUDWarning(APIEndpointWarning): def message_from(self, context: WarningContext | None = None) -> Self: confirmation = self.confirmation diff --git a/packages/syft/src/syft/service/worker/image_identifier.py b/packages/syft/src/syft/service/worker/image_identifier.py index 38025752710..85ea2414244 100644 --- a/packages/syft/src/syft/service/worker/image_identifier.py +++ b/packages/syft/src/syft/service/worker/image_identifier.py @@ -10,7 +10,7 @@ from .image_registry import SyftImageRegistry -@serializable() +@serializable(canonical_name="SyftWorkerImageIdentifier", version=1) class SyftWorkerImageIdentifier(SyftBaseModel): """ Class to identify syft worker images. diff --git a/packages/syft/src/syft/service/worker/image_registry_service.py b/packages/syft/src/syft/service/worker/image_registry_service.py index 00963f629bb..c52f855a2d6 100644 --- a/packages/syft/src/syft/service/worker/image_registry_service.py +++ b/packages/syft/src/syft/service/worker/image_registry_service.py @@ -18,7 +18,7 @@ __all__ = ["SyftImageRegistryService"] -@serializable() +@serializable(canonical_name="SyftImageRegistryService", version=1) class SyftImageRegistryService(AbstractService): store: DocumentStore stash: SyftImageRegistryStash diff --git a/packages/syft/src/syft/service/worker/image_registry_stash.py b/packages/syft/src/syft/service/worker/image_registry_stash.py index 13bc50b60a0..fc69b22cbd7 100644 --- a/packages/syft/src/syft/service/worker/image_registry_stash.py +++ b/packages/syft/src/syft/service/worker/image_registry_stash.py @@ -21,7 +21,7 @@ URLPartitionKey = PartitionKey(key="url", type_=str) -@serializable() +@serializable(canonical_name="SyftImageRegistryStash", version=1) class SyftImageRegistryStash(BaseUIDStoreStash): object_type = SyftImageRegistry settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/worker/worker_image_service.py b/packages/syft/src/syft/service/worker/worker_image_service.py index 296ec737152..fc4efd964d0 100644 --- a/packages/syft/src/syft/service/worker/worker_image_service.py +++ b/packages/syft/src/syft/service/worker/worker_image_service.py @@ -30,7 +30,7 @@ from .worker_image_stash import SyftWorkerImageStash -@serializable() +@serializable(canonical_name="SyftWorkerImageService", version=1) class SyftWorkerImageService(AbstractService): store: DocumentStore stash: SyftWorkerImageStash diff --git a/packages/syft/src/syft/service/worker/worker_image_stash.py b/packages/syft/src/syft/service/worker/worker_image_stash.py index b2761826558..4231698e11f 100644 --- a/packages/syft/src/syft/service/worker/worker_image_stash.py +++ b/packages/syft/src/syft/service/worker/worker_image_stash.py @@ -21,7 +21,7 @@ WorkerConfigPK = PartitionKey(key="config", type_=WorkerConfig) -@serializable() +@serializable(canonical_name="SyftWorkerImageStash", version=1) class SyftWorkerImageStash(BaseUIDStoreStash): object_type = SyftWorkerImage settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/worker/worker_pool.py b/packages/syft/src/syft/service/worker/worker_pool.py index 34a1bd96c11..788b529d4b8 100644 --- a/packages/syft/src/syft/service/worker/worker_pool.py +++ b/packages/syft/src/syft/service/worker/worker_pool.py @@ -30,7 +30,7 @@ from .worker_image import SyftWorkerImage -@serializable() +@serializable(canonical_name="WorkerStatus", version=1) class WorkerStatus(Enum): PENDING = "Pending" RUNNING = "Running" @@ -38,14 +38,14 @@ class WorkerStatus(Enum): RESTARTED = "Restarted" -@serializable() +@serializable(canonical_name="ConsumerState", version=1) class ConsumerState(Enum): IDLE = "Idle" CONSUMING = "Consuming" DETACHED = "Detached" -@serializable() +@serializable(canonical_name="WorkerHealth", version=1) class WorkerHealth(Enum): HEALTHY = "✅" UNHEALTHY = "❌" @@ -287,14 +287,14 @@ def workers(self) -> list[SyftWorker]: return resolved_workers -@serializable() +@serializable(canonical_name="WorkerOrchestrationType", version=1) class WorkerOrchestrationType(Enum): DOCKER = "docker" KUBERNETES = "k8s" PYTHON = "python" -@serializable() +@serializable(canonical_name="ContainerSpawnStatus", version=1) class ContainerSpawnStatus(SyftBaseModel): __repr_attrs__ = ["worker_name", "worker", "error"] diff --git a/packages/syft/src/syft/service/worker/worker_pool_service.py b/packages/syft/src/syft/service/worker/worker_pool_service.py index 53d8de9b194..0a1418f9c2d 100644 --- a/packages/syft/src/syft/service/worker/worker_pool_service.py +++ b/packages/syft/src/syft/service/worker/worker_pool_service.py @@ -49,7 +49,7 @@ logger = logging.getLogger(__name__) -@serializable() +@serializable(canonical_name="SyftWorkerPoolService", version=1) class SyftWorkerPoolService(AbstractService): store: DocumentStore stash: SyftWorkerPoolStash diff --git a/packages/syft/src/syft/service/worker/worker_pool_stash.py b/packages/syft/src/syft/service/worker/worker_pool_stash.py index 6baecc597d9..bf9498d13fb 100644 --- a/packages/syft/src/syft/service/worker/worker_pool_stash.py +++ b/packages/syft/src/syft/service/worker/worker_pool_stash.py @@ -20,7 +20,7 @@ PoolImageIDPartitionKey = PartitionKey(key="image_id", type_=UID) -@serializable() +@serializable(canonical_name="SyftWorkerPoolStash", version=1) class SyftWorkerPoolStash(BaseUIDStoreStash): object_type = WorkerPool settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/service/worker/worker_service.py b/packages/syft/src/syft/service/worker/worker_service.py index dfe2dd7eca2..fb2b512e7ce 100644 --- a/packages/syft/src/syft/service/worker/worker_service.py +++ b/packages/syft/src/syft/service/worker/worker_service.py @@ -37,7 +37,7 @@ @instrument -@serializable() +@serializable(canonical_name="WorkerService", version=1) class WorkerService(AbstractService): store: DocumentStore stash: WorkerStash diff --git a/packages/syft/src/syft/service/worker/worker_stash.py b/packages/syft/src/syft/service/worker/worker_stash.py index a55e6475200..05957fefac7 100644 --- a/packages/syft/src/syft/service/worker/worker_stash.py +++ b/packages/syft/src/syft/service/worker/worker_stash.py @@ -24,7 +24,7 @@ @instrument -@serializable() +@serializable(canonical_name="WorkerStash", version=1) class WorkerStash(BaseUIDStoreStash): object_type = SyftWorker settings: PartitionSettings = PartitionSettings( diff --git a/packages/syft/src/syft/store/blob_storage/__init__.py b/packages/syft/src/syft/store/blob_storage/__init__.py index 891aee269d0..d24ce09b171 100644 --- a/packages/syft/src/syft/store/blob_storage/__init__.py +++ b/packages/syft/src/syft/store/blob_storage/__init__.py @@ -236,7 +236,7 @@ def write(self, data: BytesIO) -> SyftSuccess | SyftError: raise NotImplementedError -@serializable() +@serializable(canonical_name="BlobStorageClientConfig", version=1) class BlobStorageClientConfig(BaseModel): pass @@ -263,7 +263,7 @@ def delete(self, fp: SecureFilePathLocation) -> bool: raise NotImplementedError -@serializable() +@serializable(canonical_name="BlobStorageClient", version=1) class BlobStorageClient(SyftBaseModel): config: BlobStorageClientConfig @@ -271,7 +271,7 @@ def connect(self) -> BlobStorageConnection: raise NotImplementedError -@serializable() +@serializable(canonical_name="BlobStorageConfig", version=1) class BlobStorageConfig(SyftBaseModel): client_type: type[BlobStorageClient] client_config: BlobStorageClientConfig diff --git a/packages/syft/src/syft/store/blob_storage/on_disk.py b/packages/syft/src/syft/store/blob_storage/on_disk.py index 318146f407e..4ef91e0db86 100644 --- a/packages/syft/src/syft/store/blob_storage/on_disk.py +++ b/packages/syft/src/syft/store/blob_storage/on_disk.py @@ -85,12 +85,12 @@ def delete(self, fp: SecureFilePathLocation) -> SyftSuccess | SyftError: return SyftError(message=f"Failed to delete file: {e}") -@serializable() +@serializable(canonical_name="OnDiskBlobStorageClientConfig", version=1) class OnDiskBlobStorageClientConfig(BlobStorageClientConfig): base_directory: Path -@serializable() +@serializable(canonical_name="OnDiskBlobStorageClient", version=1) class OnDiskBlobStorageClient(BlobStorageClient): config: OnDiskBlobStorageClientConfig @@ -102,7 +102,7 @@ def connect(self) -> BlobStorageConnection: return OnDiskBlobStorageConnection(self.config.base_directory) -@serializable() +@serializable(canonical_name="OnDiskBlobStorageConfig", version=1) class OnDiskBlobStorageConfig(BlobStorageConfig): client_type: type[BlobStorageClient] = OnDiskBlobStorageClient client_config: OnDiskBlobStorageClientConfig diff --git a/packages/syft/src/syft/store/blob_storage/seaweedfs.py b/packages/syft/src/syft/store/blob_storage/seaweedfs.py index 35b330f6bb7..06de6efcdb1 100644 --- a/packages/syft/src/syft/store/blob_storage/seaweedfs.py +++ b/packages/syft/src/syft/store/blob_storage/seaweedfs.py @@ -174,7 +174,7 @@ def add_chunks_to_queue( ) -@serializable() +@serializable(canonical_name="SeaweedFSClientConfig", version=1) class SeaweedFSClientConfig(BlobStorageClientConfig): host: str port: int @@ -197,7 +197,7 @@ def mount_url(self) -> str: return f"http://{self.host}:{self.mount_port}/configure_azure" -@serializable() +@serializable(canonical_name="SeaweedFSClient", version=1) class SeaweedFSClient(BlobStorageClient): config: SeaweedFSClientConfig @@ -216,7 +216,7 @@ def connect(self) -> BlobStorageConnection: ) -@serializable() +@serializable(canonical_name="SeaweedFSConnection", version=1) class SeaweedFSConnection(BlobStorageConnection): client: S3BaseClient default_bucket_name: str @@ -325,7 +325,7 @@ def delete( return SyftError(message=str(e)) -@serializable() +@serializable(canonical_name="SeaweedFSConfig", version=1) class SeaweedFSConfig(BlobStorageConfig): client_type: type[BlobStorageClient] = SeaweedFSClient client_config: SeaweedFSClientConfig diff --git a/packages/syft/src/syft/store/dict_document_store.py b/packages/syft/src/syft/store/dict_document_store.py index 2fdd80902b7..e97d9105645 100644 --- a/packages/syft/src/syft/store/dict_document_store.py +++ b/packages/syft/src/syft/store/dict_document_store.py @@ -19,7 +19,7 @@ from .locks import ThreadingLockingConfig -@serializable() +@serializable(canonical_name="DictBackingStore", version=1) class DictBackingStore(dict, KeyValueBackingStore): # type: ignore[misc] # TODO: fix the mypy issue """Dictionary-based Store core logic""" @@ -38,7 +38,7 @@ def __getitem__(self, key: Any) -> Any: raise e -@serializable() +@serializable(canonical_name="DictStorePartition", version=1) class DictStorePartition(KeyValueStorePartition): """Dictionary-based StorePartition @@ -54,7 +54,7 @@ def prune(self) -> None: # the base document store is already a dict but we can change it later -@serializable() +@serializable(canonical_name="DictDocumentStore", version=1) class DictDocumentStore(DocumentStore): """Dictionary-based Document Store diff --git a/packages/syft/src/syft/store/document_store.py b/packages/syft/src/syft/store/document_store.py index bda94797796..7cfa3867555 100644 --- a/packages/syft/src/syft/store/document_store.py +++ b/packages/syft/src/syft/store/document_store.py @@ -34,7 +34,7 @@ from .locks import SyftLock -@serializable() +@serializable(canonical_name="BasePartitionSettings", version=1) class BasePartitionSettings(SyftBaseModel): """Basic Partition Settings @@ -62,7 +62,7 @@ class StoreClientConfig(BaseModel): pass -@serializable() +@serializable(canonical_name="PartitionKey", version=1) class PartitionKey(BaseModel): key: str type_: type | object @@ -100,7 +100,7 @@ def type_list(self) -> bool: return is_generic_alias(self.type_) and self.type_.__origin__ == list -@serializable() +@serializable(canonical_name="PartitionKeys", version=1) class PartitionKeys(BaseModel): pks: PartitionKey | tuple[PartitionKey, ...] | list[PartitionKey] @@ -126,7 +126,7 @@ def from_dict(cks_dict: dict[str, type]) -> PartitionKeys: return PartitionKeys(pks=pks) -@serializable() +@serializable(canonical_name="QueryKey", version=1) class QueryKey(PartitionKey): value: Any = None @@ -183,7 +183,7 @@ def as_dict_mongo(self) -> dict[str, Any]: return {key: self.value} -@serializable() +@serializable(canonical_name="PartitionKeysWithUID", version=1) class PartitionKeysWithUID(PartitionKeys): uid_pk: PartitionKey @@ -195,7 +195,7 @@ def all(self) -> tuple[PartitionKey, ...] | list[PartitionKey]: return all_keys -@serializable() +@serializable(canonical_name="QueryKeys", version=1) class QueryKeys(SyftBaseModel): qks: QueryKey | tuple[QueryKey, ...] | list[QueryKey] @@ -276,7 +276,7 @@ def as_dict_mongo(self) -> dict: UIDPartitionKey = PartitionKey(key="id", type_=UID) -@serializable() +@serializable(canonical_name="PartitionSettings", version=1) class PartitionSettings(BasePartitionSettings): object_type: type store_key: PartitionKey = UIDPartitionKey @@ -292,7 +292,11 @@ def searchable_keys(self) -> PartitionKeys: @instrument -@serializable(attrs=["settings", "store_config", "unique_cks", "searchable_cks"]) +@serializable( + attrs=["settings", "store_config", "unique_cks", "searchable_cks"], + canonical_name="StorePartition", + version=1, +) class StorePartition: """Base StorePartition @@ -561,7 +565,7 @@ def _migrate_data( @instrument -@serializable() +@serializable(canonical_name="DocumentStore", version=1) class DocumentStore: """Base Document Store diff --git a/packages/syft/src/syft/store/kv_document_store.py b/packages/syft/src/syft/store/kv_document_store.py index 32c6ce7371e..d0f5c22d7df 100644 --- a/packages/syft/src/syft/store/kv_document_store.py +++ b/packages/syft/src/syft/store/kv_document_store.py @@ -34,7 +34,7 @@ from .document_store import StorePartition -@serializable() +@serializable(canonical_name="UniqueKeyCheck", version=1) class UniqueKeyCheck(Enum): EMPTY = 0 MATCHES = 1 diff --git a/packages/syft/src/syft/store/locks.py b/packages/syft/src/syft/store/locks.py index 48ae6ca1178..2494dffa895 100644 --- a/packages/syft/src/syft/store/locks.py +++ b/packages/syft/src/syft/store/locks.py @@ -16,7 +16,7 @@ THREAD_FILE_LOCKS: dict[int, dict[str, int]] = defaultdict(dict) -@serializable() +@serializable(canonical_name="LockingConfig", version=1) class LockingConfig(BaseModel): """ Locking config @@ -41,7 +41,7 @@ class LockingConfig(BaseModel): retry_interval: float = 0.1 -@serializable() +@serializable(canonical_name="NoLockingConfig", version=1) class NoLockingConfig(LockingConfig): """ No-locking policy @@ -50,7 +50,7 @@ class NoLockingConfig(LockingConfig): pass -@serializable() +@serializable(canonical_name="ThreadingLockingConfig", version=1) class ThreadingLockingConfig(LockingConfig): """ Threading-based locking policy diff --git a/packages/syft/src/syft/store/mongo_client.py b/packages/syft/src/syft/store/mongo_client.py index 317f53346db..7e751ce05d1 100644 --- a/packages/syft/src/syft/store/mongo_client.py +++ b/packages/syft/src/syft/store/mongo_client.py @@ -19,7 +19,7 @@ from .mongo_codecs import SYFT_CODEC_OPTIONS -@serializable() +@serializable(canonical_name="MongoStoreClientConfig", version=1) class MongoStoreClientConfig(StoreClientConfig): """ Paramaters: diff --git a/packages/syft/src/syft/store/mongo_document_store.py b/packages/syft/src/syft/store/mongo_document_store.py index bf2c8436fa6..ab1bc02712a 100644 --- a/packages/syft/src/syft/store/mongo_document_store.py +++ b/packages/syft/src/syft/store/mongo_document_store.py @@ -118,7 +118,7 @@ def from_mongo( return _deserialize(storage_obj["__blob__"], from_bytes=True) -@serializable(attrs=["storage_type"]) +@serializable(attrs=["storage_type"], canonical_name="MongoStorePartition", version=1) class MongoStorePartition(StorePartition): """Mongo StorePartition @@ -806,7 +806,7 @@ def _migrate_data( return Err("You don't have permissions to migrate data.") -@serializable() +@serializable(canonical_name="MongoDocumentStore", version=1) class MongoDocumentStore(DocumentStore): """Mongo Document Store @@ -818,7 +818,11 @@ class MongoDocumentStore(DocumentStore): partition_type = MongoStorePartition -@serializable(attrs=["index_name", "settings", "store_config"]) +@serializable( + attrs=["index_name", "settings", "store_config"], + canonical_name="MongoBackingStore", + version=1, +) class MongoBackingStore(KeyValueBackingStore): """ Core logic for the MongoDB key-value store diff --git a/packages/syft/src/syft/store/sqlite_document_store.py b/packages/syft/src/syft/store/sqlite_document_store.py index d992629b0b5..e27ce2c7d16 100644 --- a/packages/syft/src/syft/store/sqlite_document_store.py +++ b/packages/syft/src/syft/store/sqlite_document_store.py @@ -73,7 +73,11 @@ def raise_exception(table_name: str, e: Exception) -> None: raise e -@serializable(attrs=["index_name", "settings", "store_config"]) +@serializable( + attrs=["index_name", "settings", "store_config"], + canonical_name="SQLiteBackingStore", + version=1, +) class SQLiteBackingStore(KeyValueBackingStore): """Core Store logic for the SQLite stores. @@ -361,7 +365,7 @@ def __del__(self) -> None: logger.error("Could not close connection", exc_info=e) -@serializable() +@serializable(canonical_name="SQLiteStorePartition", version=1) class SQLiteStorePartition(KeyValueStorePartition): """SQLite StorePartition @@ -396,7 +400,7 @@ def commit(self) -> None: # the base document store is already a dict but we can change it later -@serializable() +@serializable(canonical_name="SQLiteDocumentStore", version=1) class SQLiteDocumentStore(DocumentStore): """SQLite Document Store @@ -408,7 +412,7 @@ class SQLiteDocumentStore(DocumentStore): partition_type = SQLiteStorePartition -@serializable() +@serializable(canonical_name="SQLiteStoreClientConfig", version=1) class SQLiteStoreClientConfig(StoreClientConfig): """SQLite connection config diff --git a/packages/syft/src/syft/types/cache_object.py b/packages/syft/src/syft/types/cache_object.py index ddee2e32a6d..5f13803e4e7 100644 --- a/packages/syft/src/syft/types/cache_object.py +++ b/packages/syft/src/syft/types/cache_object.py @@ -6,7 +6,7 @@ from .base import SyftBaseModel -@serializable() +@serializable(canonical_name="CachedSyftObject", version=1) class CachedSyftObject(SyftBaseModel): """This class is used to represent the cached result.""" diff --git a/packages/syft/src/syft/types/identity.py b/packages/syft/src/syft/types/identity.py index 6fc944747d0..f5c4f1f26ea 100644 --- a/packages/syft/src/syft/types/identity.py +++ b/packages/syft/src/syft/types/identity.py @@ -34,7 +34,7 @@ def from_client(cls, client: SyftClient) -> Self: return cls(server_id=client.id, verify_key=client.credentials.verify_key) -@serializable() +@serializable(canonical_name="UserIdentity", version=1) class UserIdentity(Identity): """This class is used to identify the data scientist users of the server""" diff --git a/packages/syft/src/syft/types/server_url.py b/packages/syft/src/syft/types/server_url.py index 0ccaeb10c23..c0bbab960a5 100644 --- a/packages/syft/src/syft/types/server_url.py +++ b/packages/syft/src/syft/types/server_url.py @@ -19,7 +19,11 @@ logger = logging.getLogger(__name__) -@serializable(attrs=["protocol", "host_or_ip", "port", "path", "query"]) +@serializable( + attrs=["protocol", "host_or_ip", "port", "path", "query"], + canonical_name="ServerURL", + version=1, +) class ServerURL: @classmethod def from_url(cls, url: str | ServerURL) -> ServerURL: diff --git a/packages/syft/src/syft/types/syft_metaclass.py b/packages/syft/src/syft/types/syft_metaclass.py index ae09b1c03c8..a8d18386e2b 100644 --- a/packages/syft/src/syft/types/syft_metaclass.py +++ b/packages/syft/src/syft/types/syft_metaclass.py @@ -18,7 +18,7 @@ def __bool__(self) -> bool: return False -@serializable() +@serializable(canonical_name="Empty", version=1) @final class Empty(metaclass=EmptyType): pass diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index ac3242a12e5..4e4218cb07b 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -33,12 +33,11 @@ from pydantic import model_validator from pydantic.fields import PydanticUndefined from result import OkErr -from syft.serde.serializable import serializable from typeguard import check_type from typing_extensions import Self # relative -from ..serde.recursive_primitives import recursive_serde_register_type +from ..serde.serializable import serializable from ..serde.serialize import _serialize as serialize from ..server.credentials import SyftVerifyKey from ..service.response import SyftError diff --git a/packages/syft/src/syft/types/uid.py b/packages/syft/src/syft/types/uid.py index 798214db3fb..96bc5af31b8 100644 --- a/packages/syft/src/syft/types/uid.py +++ b/packages/syft/src/syft/types/uid.py @@ -19,7 +19,7 @@ logger = logging.getLogger(__name__) -@serializable(attrs=["value"]) +@serializable(attrs=["value"], canonical_name="UID", version=1) class UID: """A unique ID for every Syft object. @@ -211,7 +211,7 @@ def _check_or_convert(cls, value: str | uuid.UUID | UID) -> UID: ) -@serializable(attrs=["syft_history_hash"]) +@serializable(attrs=["syft_history_hash"], canonical_name="LineageID", version=1) class LineageID(UID): """Extended UID containing a history hash as well, which is used for comparisons.""" From 95341f9bb2776486432b08af1dbe35bedcc60b91 Mon Sep 17 00:00:00 2001 From: dk Date: Tue, 16 Jul 2024 10:04:41 +0700 Subject: [PATCH 068/117] [tests/integration] debugging `test_delete_idle_worker` --- tests/integration/local/syft_worker_deletion_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/local/syft_worker_deletion_test.py b/tests/integration/local/syft_worker_deletion_test.py index 6de5f0b6078..07b89c39b4c 100644 --- a/tests/integration/local/syft_worker_deletion_test.py +++ b/tests/integration/local/syft_worker_deletion_test.py @@ -88,7 +88,11 @@ def test_delete_idle_worker(server: ServerHandle, force: bool) -> None: start = time.time() while True: - if len(client.worker.get_all()) == 0: + all_workers = client.worker.get_all() + if isinstance(all_workers, SyftError): + print(all_workers) + continue + if len(all_workers) == 0: break if time.time() - start > 3: raise TimeoutError("Worker did not get removed from stash.") From 4135f47b79b3e388c23fcdba7c49e6057244a365 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Tue, 16 Jul 2024 12:10:21 +0530 Subject: [PATCH 069/117] updated notebook for adding users --- .../03-configuring-datasite.ipynb | 2 +- .../getting-started/05-adding-users.ipynb | 16096 +++++++++++++++- 2 files changed, 16095 insertions(+), 3 deletions(-) diff --git a/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb b/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb index 3825c2aafb6..c4925c81311 100644 --- a/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb +++ b/notebooks/scenarios/getting-started/03-configuring-datasite.ipynb @@ -1551,7 +1551,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.11.5" } }, "nbformat": 4, diff --git a/notebooks/scenarios/getting-started/05-adding-users.ipynb b/notebooks/scenarios/getting-started/05-adding-users.ipynb index 881fb6a5a01..6e6befee17b 100644 --- a/notebooks/scenarios/getting-started/05-adding-users.ipynb +++ b/notebooks/scenarios/getting-started/05-adding-users.ipynb @@ -14,9 +14,16101 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, + "id": "3de6bc42-4b2f-4902-9676-a36a0621fef3", + "metadata": {}, + "outputs": [], + "source": [ + "# syft absolute\n", + "import syft as sy" + ] + }, + { + "cell_type": "code", + "execution_count": 3, "id": "3ac0c932-601f-4424-ad80-f02da291b2a3", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting test-datasite-1 server on 0.0.0.0:8081\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: Started server process [63035]\n", + "INFO: Waiting for application startup.\n", + "INFO: Application startup complete.\n", + "INFO: Uvicorn running on http://0.0.0.0:8081 (Press CTRL+C to quit)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: 127.0.0.1:55426 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "Waiting for server to start Done.\n" + ] + }, + { + "data": { + "text/html": [ + "
SyftInfo:
You have launched a development server at http://0.0.0.0:8081.It is intended only for local use.

" + ], + "text/plain": [ + "SyftInfo: You have launched a development server at http://0.0.0.0:8081.It is intended only for local use." + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: 127.0.0.1:55432 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55432 - \"POST /api/v2/login HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55432 - \"GET /api/v2/api?verify_key=d2dfbeeef378bf4737a4aec6a9406cd8a674a7831ec56f4ca8899e52e9c827e3&communication_protocol=dev HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55442 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55432 - \"POST /api/v2/register HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55456 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55472 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55474 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55490 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55500 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55516 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55518 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55534 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55542 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55542 - \"POST /api/v2/login HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:55542 - \"GET /api/v2/api?verify_key=d52fec1ad30b0934cf021e3925482276433f83c5943d5590a5298f4ce77fe8a5&communication_protocol=dev HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:40602 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:40604 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:40620 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:40632 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:40642 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:40652 - \"GET /api/v2/metadata HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:40652 - \"POST /api/v2/register HTTP/1.1\" 200 OK\n", + "INFO: 127.0.0.1:40662 - \"POST /api/v2/api_call HTTP/1.1\" 200 OK\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO: Shutting down\n", + "INFO: Waiting for application shutdown.\n", + "INFO: Application shutdown complete.\n", + "INFO: Finished server process [63035]\n" + ] + } + ], + "source": [ + "server = sy.orchestra.launch(name=\"test-datasite-1\", port=8081)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5ef99d40-8b1e-4be8-af42-0edb50df7250", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Logged into as GUEST\n", + "Logged into as \n" + ] + }, + { + "data": { + "text/html": [ + "
SyftWarning:
You are using a default password. Please change the password using `[your_client].me.set_password([new_password])`.

" + ], + "text/plain": [ + "SyftWarning: You are using a default password. Please change the password using `[your_client].me.set_password([new_password])`." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# logging in as root client with default credentials\n", + "client = server.login(email=\"info@openmined.org\", password=\"changethis\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "d970eaef-e27e-4d81-b959-da18a0af2f01", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
User 'John Doe' successfully registered! To see users, run `[your_client].users`

" + ], + "text/plain": [ + "SyftSuccess: User 'John Doe' successfully registered! To see users, run `[your_client].users`" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# register a new user\n", + "client.register(\n", + " name=\"John Doe\", email=\"john@email.com\", password=\"pass\", password_verify=\"pass\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "fd8f9701-1fe8-4a96-9d49-7ecb1a29adab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "

UserView List

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

Total: 0

\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Returns a list of all the existing users in the domain\n", + "client.users" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "db6af0e7-dceb-48ae-887d-614c41a38797", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'John Doe'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Selecting an user by index\n", + "client.users[1].name" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "74bc93da-0c86-4397-9a2f-fb4aa414ad3a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "

UserView List

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

Total: 0

\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "[syft.service.user.user.UserView]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Selecting an user by filtering\n", + "search_results = client.users.search(email=\"john@email.com\")\n", + "search_results" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "68d7a572-b90c-44a1-9ae8-e41db39f8f23", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'John Doe'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "searched_user = search_results[0]\n", + "searched_user.name" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "859f20c6-21d2-4448-8f3b-097e6df98b90", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
Successfully updated email for the user 'John Doe' to 'updatedjohn@email.com'.

" + ], + "text/plain": [ + "SyftSuccess: Successfully updated email for the user 'John Doe' to 'updatedjohn@email.com'." + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# update email\n", + "searched_user.set_email(email=\"updatedjohn@email.com\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ef702a91-0674-49ba-80bc-aaa66f83f434", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```python\n", + "class UserView:\n", + " id: str = e451c1c5c46e462dbc6e0484626559fc\n", + " name: str = \"John Doe\"\n", + " email: str = \"updatedjohn@email.com\"\n", + " institution: str = None\n", + " website: str = None\n", + " role: str = ServiceRole.DATA_SCIENTIST\n", + " notifications_enabled: str = {: True, : False, : False, : False}\n", + "\n", + "```" + ], + "text/plain": [ + "syft.service.user.user.UserView" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "searched_user" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "b8d5a650-2d4b-4fec-a45e-9f93f9e0f73e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
Successfully updated password for user 'John Doe' with email 'updatedjohn@email.com'.

" + ], + "text/plain": [ + "SyftSuccess: Successfully updated password for user 'John Doe' with email 'updatedjohn@email.com'." + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# update password\n", + "searched_user.set_password(new_password=\"newpass\", confirm=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "83aba8a1-98a2-4dea-ae18-2f70f2df078e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "

UserView List

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

Total: 0

\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.users" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "d4ca0ce8-4bb6-44a3-8e4b-6d89b91fd30d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
User details successfully updated.

" + ], + "text/plain": [ + "SyftSuccess: User details successfully updated." + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Update info of an existing user\n", + "searched_user.update(\n", + " name=\"Updated Jane Doe\",\n", + " institution=\"My institution\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "a4d7f854-3771-4dbd-94ad-ffa4a76272ee", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "

UserView List

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

Total: 0

\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.users" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b0d7b4fc-eaf3-45bf-b808-6caf91d74ccd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Logged into as GUEST\n", + "Logged into as \n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + "
\n", + " \"Logo\"\n",\n", + "

Welcome to test-datasite-1

\n", + "
\n", + " URL: http://localhost:8081
\n", + " Server Description: This is the default description for a Datasite Server.
\n", + " Server Type: Datasite
\n", + " Server Side Type:High Side
\n", + " Syft Version: 0.8.7-beta.14
\n", + "\n", + "
\n", + "
\n", + " ⓘ \n", + " This datasite is run by the library PySyft to learn more about how it works visit\n", + " github.com/OpenMined/PySyft.\n", + "
\n", + "

Commands to Get Started

\n", + " \n", + "
    \n", + " \n", + "
  • <your_client>.datasets - list datasets
  • \n", + "
  • <your_client>.code - list code
  • \n", + "
  • <your_client>.projects - list projects
  • \n", + "\n", + "
\n", + " \n", + "

\n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# validate login for new user\n", + "server.login(email=\"updatedjohn@email.com\", password=\"newpass\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "4b4c078c-663f-437e-b103-92f76602eee1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
ID: e451c1c5c46e462dbc6e0484626559fc deleted

" + ], + "text/plain": [ + "SyftSuccess: ID: e451c1c5c46e462dbc6e0484626559fc deleted" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Delete user\n", + "client.users.delete(searched_user.id)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "3167816a-5efc-4ae5-be5d-389398b74e3c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "

UserView List

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

Total: 0

\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.users" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "877d0945-0684-42b5-a5d4-4fd3e69f950b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
Registration feature successfully enabled

" + ], + "text/plain": [ + "SyftSuccess: Registration feature successfully enabled" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Enable user registration\n", + "client.settings.allow_guest_signup(enable=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "c2260402-642f-41f5-8217-f0d44f75d62b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Logged into as GUEST\n", + "Logged into as GUEST\n" + ] + } + ], + "source": [ + "guest_user = server.login_as_guest()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "fa874373-9289-4531-94cc-9342f1e244ff", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SyftSuccess:
User 'Curious Scientist' successfully registered!

" + ], + "text/plain": [ + "SyftSuccess: User 'Curious Scientist' successfully registered!" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# register the account\n", + "guest_user.register(\n", + " email=\"scientist@test.com\",\n", + " password=\"123\",\n", + " password_verify=\"123\",\n", + " name=\"Curious Scientist\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "a2db0aee-a380-4bf2-85bf-65c2914d719a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "

UserView List

\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "

Total: 0

\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client.users" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "17749554-e971-401b-977f-6d1819b2194a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Stopping test-datasite-1\n" + ] + } + ], + "source": [ + "server.land()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6f2c835-7a79-4331-9486-dfeb8acdfbf5", + "metadata": {}, "outputs": [], "source": [] } @@ -37,7 +16129,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.11.5" } }, "nbformat": 4, From afe62d1d425957f618d3fded65cac9c3dee7773b Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Tue, 16 Jul 2024 13:01:13 +0530 Subject: [PATCH 070/117] [tutorials/data-owner]: fix user create and update apis --- notebooks/tutorials/data-owner/02-account-management.ipynb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/notebooks/tutorials/data-owner/02-account-management.ipynb b/notebooks/tutorials/data-owner/02-account-management.ipynb index 1488030630a..4f145816565 100644 --- a/notebooks/tutorials/data-owner/02-account-management.ipynb +++ b/notebooks/tutorials/data-owner/02-account-management.ipynb @@ -78,7 +78,6 @@ "source": [ "# syft absolute\n", "from syft.service.user.user import ServiceRole\n", - "from syft.service.user.user import UserCreate\n", "\n", "client = server.login(email=\"info@openmined.org\", password=\"changethis\")" ] @@ -106,9 +105,7 @@ "metadata": {}, "outputs": [], "source": [ - "client.users.create(\n", - " UserCreate(email=\"newuser@openmined.org\", name=\"John Doe\", password=\"pw\")\n", - ")" + "client.users.create(email=\"newuser@openmined.org\", name=\"John Doe\", password=\"pw\")" ] }, { @@ -481,7 +478,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.3" + "version": "3.11.5" }, "toc": { "base_numbering": 1, From 0502efff3c14c49edad036351dfad1280d818850 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 09:36:03 +0200 Subject: [PATCH 071/117] add nb + fixes --- notebooks/generate_canonical_names.ipynb | 267 ++++++++++++++++++ packages/syft/src/syft/serde/recursive.py | 13 +- .../syft/src/syft/store/kv_document_store.py | 1 + .../src/syft/types/syft_object_registry.py | 13 +- 4 files changed, 285 insertions(+), 9 deletions(-) create mode 100644 notebooks/generate_canonical_names.ipynb diff --git a/notebooks/generate_canonical_names.ipynb b/notebooks/generate_canonical_names.ipynb new file mode 100644 index 00000000000..9b35509662c --- /dev/null +++ b/notebooks/generate_canonical_names.ipynb @@ -0,0 +1,267 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "107f1473-4451-4499-8e28-105b29da3373", + "metadata": {}, + "outputs": [], + "source": [ + "# stdlib\n", + "import os\n", + "\n", + "os.environ[\"SYFT_SEARCH_UNREGISTERED_CLASSES\"] = \"1\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "50d4a32c-d7c3-4abb-8814-1bb39eb557b2", + "metadata": {}, + "outputs": [], + "source": [ + "# stdlib\n", + "\n", + "# syft absolute\n", + "from syft.serde.recursive import SYFT_CLASSES_MISSING_CANONICAL_NAME\n", + "from syft.types.syft_object_registry import SyftObjectRegistry" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e4cfba28-f0c1-4289-aae4-a13ba4ce6004", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(True,\n", + " bytes>,\n", + " functools.partial(, ),\n", + " None,\n", + " [],\n", + " {},\n", + " [],\n", + " dict,\n", + " None,\n", + " 1)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "SyftObjectRegistry.__object_serialization_registry__[\"dict\"][1]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "51eca6cc-8d29-4148-8a85-f6ed23a016b3", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "existing_cnames = SyftObjectRegistry.__object_serialization_registry__.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ef1f89af-40c1-4a47-a003-ff1b9691d9d4", + "metadata": {}, + "outputs": [], + "source": [ + "# stdlib\n", + "import ast\n", + "import inspect\n", + "\n", + "\n", + "class DecoratorFinder(ast.NodeVisitor):\n", + " def __init__(self, class_name: str, decorator_name: str):\n", + " self.class_name = class_name\n", + " self.decorator_name = decorator_name\n", + " self.decorator: ast.Call | None = None\n", + "\n", + " def visit_ClassDef(self, node: ast.ClassDef) -> None:\n", + " if node.name == self.class_name:\n", + " for decorator in node.decorator_list:\n", + " if (\n", + " isinstance(decorator, ast.Call)\n", + " and getattr(decorator.func, \"id\", None) == self.decorator_name\n", + " ):\n", + " self.decorator = decorator\n", + " self.generic_visit(node)\n", + "\n", + "\n", + "def get_class_file_path(cls: type) -> str:\n", + " return inspect.getfile(cls)\n", + "\n", + "\n", + "def get_decorator_with_lines(\n", + " file_path: str, class_name: str, decorator_name: str\n", + ") -> tuple[ast.Call | None, int | None, int | None]:\n", + " with open(file_path) as source:\n", + " tree = ast.parse(source.read())\n", + "\n", + " finder = DecoratorFinder(class_name, decorator_name)\n", + " finder.visit(tree)\n", + "\n", + " if finder.decorator:\n", + " start_line = finder.decorator.lineno - 1\n", + " end_line = (\n", + " finder.decorator.end_lineno\n", + " if hasattr(finder.decorator, \"end_lineno\")\n", + " else finder.decorator.lineno\n", + " )\n", + " return finder.decorator, start_line, end_line\n", + " return None, None, None" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ef8eef16-c182-475d-b105-d1fe7778a2fd", + "metadata": {}, + "outputs": [], + "source": [ + "def add_canonical_name_version(decorator: ast.Call, class_name: str) -> ast.Call:\n", + " new_decorator = decorator\n", + "\n", + " canonical_name_exists = any(\n", + " kw.arg == \"canonical_name\" for kw in new_decorator.keywords\n", + " )\n", + " version_exists = any(kw.arg == \"version\" for kw in new_decorator.keywords)\n", + "\n", + " if not canonical_name_exists:\n", + " new_decorator.keywords.append(\n", + " ast.keyword(arg=\"canonical_name\", value=ast.Constant(value=class_name))\n", + " )\n", + " if not version_exists:\n", + " new_decorator.keywords.append(\n", + " ast.keyword(arg=\"version\", value=ast.Constant(value=1))\n", + " )\n", + "\n", + " return ast.copy_location(new_decorator, decorator)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "51ab50fe-37c6-41a4-b1c2-549036727f0d", + "metadata": {}, + "outputs": [], + "source": [ + "def update_decorator_for_cls(\n", + " cls: type, existing_canonical_names: list[str]\n", + ") -> str | None:\n", + " file_path = inspect.getfile(cls)\n", + " class_name = cls.__name__\n", + "\n", + " decorator, start_line, end_line = get_decorator_with_lines(\n", + " file_path, class_name, \"serializable\"\n", + " )\n", + "\n", + " if decorator is None:\n", + " print(\n", + " f\"{cls.__module__}: Could not find decorator for class {class_name}. Did not update canonical name.\"\n", + " )\n", + " return None\n", + " if start_line is None or end_line is None:\n", + " print(\n", + " f\"{cls.__module__}: No start/end lines for decorator in class {class_name}. Did not update canonical name.\"\n", + " )\n", + " return None\n", + "\n", + " if class_name in existing_canonical_names:\n", + " print(\n", + " f\"{cls.__module__}: {class_name} is already a registered canonical name. Did not update canonical name.\"\n", + " )\n", + " return None\n", + "\n", + " new_decorator = add_canonical_name_version(decorator, class_name)\n", + " new_decorator_code = ast.unparse(new_decorator).split(\"\\n\")\n", + " new_decorator_code[0] = \"@\" + new_decorator_code[0]\n", + "\n", + " with open(file_path) as file:\n", + " lines = file.readlines()\n", + "\n", + " lines[start_line:end_line] = [line + \"\\n\" for line in new_decorator_code]\n", + "\n", + " with open(file_path, \"w\") as file:\n", + " file.writelines(lines)\n", + "\n", + " print(f\"Updated {cls.__module__}.{cls.__name__}\")\n", + " return class_name" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "158c4044-6f79-49f1-abd3-cbf336883afc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Updated syft.service.network.utils.PeerHealthCheckTask\n" + ] + } + ], + "source": [ + "existing_cnames = list(existing_cnames)\n", + "\n", + "for cls in SYFT_CLASSES_MISSING_CANONICAL_NAME:\n", + " new_name = update_decorator_for_cls(cls, existing_cnames)\n", + " if new_name:\n", + " existing_cnames.append(new_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b383658c-63dc-401a-b8e5-4a051624b3b5", + "metadata": {}, + "outputs": [], + "source": [ + "os.environ[\"SYFT_SEARCH_UNREGISTERED_CLASSES\"] = \"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a0d4ada-50e1-4bab-a6da-bd38d82a7cdd", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index 77ede49f96b..289bd1c9cbd 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -49,7 +49,7 @@ def get_types(cls: type, keys: list[str] | None = None) -> list[type] | None: return types -def check_fqn_alias(cls: object | type) -> tuple | None: +def check_fqn_alias(cls: object | type) -> tuple[str, ...] | None: """Currently, typing.Any has different metaclasses in different versions of Python 🤦‍♂️. For Python <=3.10 Any is an instance of typing._SpecialForm @@ -207,7 +207,6 @@ def recursive_serde_register( attributes = set(attribute_list) if attribute_list else None attribute_types = get_types(cls, attributes) serde_overrides = getattr(cls, "__serde_overrides__", {}) - version = getattr(cls, "__version__", None) # without fqn duplicate class names overwrite serde_attributes = ( @@ -231,7 +230,7 @@ def recursive_serde_register( if isinstance(alias_fqn, tuple): for alias in alias_fqn: # TYPE_BANK[alias] = serde_attributes - alias_canonical_name = canonical_name + alias.__name__ + alias_canonical_name = canonical_name + f"_{alias}" SyftObjectRegistry.register_cls(alias_canonical_name, 1, serde_attributes) @@ -296,7 +295,9 @@ def rs_object2proto(self: Any, for_hashing: bool = False) -> _DynamicStructBuild if not SyftObjectRegistry.has_serde_class("", canonical_name, version): # third party - raise Exception(f"{canonical_name} version {version} not in SyftObjectRegistry") + raise Exception( + f"obj2proto: {canonical_name} version {version} not in SyftObjectRegistry" + ) msg.canonicalName = canonical_name msg.version = version @@ -418,7 +419,9 @@ def rs_proto2object(proto: _DynamicStructBuilder) -> Any: fqn = map_fqns_for_backward_compatibility(fqn) if not SyftObjectRegistry.has_serde_class(fqn, canonical_name, version): # third party - raise Exception(f"{canonical_name} version {version} not in SyftObjectRegistry") + raise Exception( + f"proto2obj: {canonical_name} version {version} not in SyftObjectRegistry" + ) # TODO: 🐉 sort this out, basically sometimes the syft.user classes are not in the # module name space in sub-processes or threads even though they are loaded on start diff --git a/packages/syft/src/syft/store/kv_document_store.py b/packages/syft/src/syft/store/kv_document_store.py index d0f5c22d7df..06a1f1cbc6e 100644 --- a/packages/syft/src/syft/store/kv_document_store.py +++ b/packages/syft/src/syft/store/kv_document_store.py @@ -137,6 +137,7 @@ def init_store(self) -> Result[Ok, Err]: if pk_key not in self.searchable_keys: self.searchable_keys[pk_key] = defaultdict(list) except BaseException as e: + raise e return Err(str(e)) return Ok(True) diff --git a/packages/syft/src/syft/types/syft_object_registry.py b/packages/syft/src/syft/types/syft_object_registry.py index 424c055fe0d..34c4adc2a80 100644 --- a/packages/syft/src/syft/types/syft_object_registry.py +++ b/packages/syft/src/syft/types/syft_object_registry.py @@ -4,7 +4,6 @@ from typing import TYPE_CHECKING # relative -from ..util.util import get_fully_qualified_name SYFT_086_PROTOCOL_VERSION = "4" @@ -19,6 +18,7 @@ class SyftObjectRegistry: __object_transform_registry__: dict[str, Callable] = {} __object_serialization_registry__: dict[str, dict[int, tuple]] = {} + __type_to_canonical_name__: dict[type, str] = {} @classmethod def register_cls( @@ -30,6 +30,8 @@ def register_cls( serde_attributes ) + cls.__type_to_canonical_name__[serde_attributes[7]] = canonical_name + @classmethod def get_versions(cls, canonical_name: str) -> list[int]: available_versions: dict = cls.__object_serialization_registry__.get( @@ -44,13 +46,16 @@ def get_canonical_name(cls, obj: Any) -> str: # # TODO: this is different for builtin types, make more generic # return "ModelMetaclass" is_type = isinstance(obj, type) + if not is_type: + obj = type(obj) res = getattr(obj, "__canonical_name__", None) if res is not None and not is_type: return res - else: - fqn = get_fully_qualified_name(obj) - return fqn + elif obj in cls.__type_to_canonical_name__: + return cls.__type_to_canonical_name__[obj] + + raise ValueError(f"Could not find canonical name for {obj}") @classmethod def get_serde_properties(cls, canonical_name: str, version: int) -> tuple: From c01fbccf98fa7eb8af7c190b8cf0f6354927afeb Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 10:05:03 +0200 Subject: [PATCH 072/117] fix get_cname(type) --- .../syft/src/syft/store/kv_document_store.py | 1 - .../src/syft/types/syft_object_registry.py | 39 ++++++++++++------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/syft/src/syft/store/kv_document_store.py b/packages/syft/src/syft/store/kv_document_store.py index 06a1f1cbc6e..d0f5c22d7df 100644 --- a/packages/syft/src/syft/store/kv_document_store.py +++ b/packages/syft/src/syft/store/kv_document_store.py @@ -137,7 +137,6 @@ def init_store(self) -> Result[Ok, Err]: if pk_key not in self.searchable_keys: self.searchable_keys[pk_key] = defaultdict(list) except BaseException as e: - raise e return Err(str(e)) return Ok(True) diff --git a/packages/syft/src/syft/types/syft_object_registry.py b/packages/syft/src/syft/types/syft_object_registry.py index 34c4adc2a80..1742cff3f79 100644 --- a/packages/syft/src/syft/types/syft_object_registry.py +++ b/packages/syft/src/syft/types/syft_object_registry.py @@ -3,8 +3,6 @@ from typing import Any from typing import TYPE_CHECKING -# relative - SYFT_086_PROTOCOL_VERSION = "4" # third party @@ -42,19 +40,30 @@ def get_versions(cls, canonical_name: str) -> list[int]: @classmethod def get_canonical_name(cls, obj: Any) -> str: - # if is_type: - # # TODO: this is different for builtin types, make more generic - # return "ModelMetaclass" - is_type = isinstance(obj, type) - if not is_type: - obj = type(obj) - - res = getattr(obj, "__canonical_name__", None) - if res is not None and not is_type: - return res - elif obj in cls.__type_to_canonical_name__: - return cls.__type_to_canonical_name__[obj] - + """ + Retrieves the canonical name for both objects and types. + + This function works for both objects and types, returning the canonical name + as a string. It handles various cases, including built-in types, instances of + classes, and enum members. + + If the object is not registered in the registry, a ValueError is raised. + + Examples: + get_canonical_name([1,2,3]) -> "list" + get_canonical_name(list) -> "type" + get_canonical_name(MyEnum.A) -> "MyEnum" + get_canonical_name(MyEnum) -> "EnumMeta" + + Args: + obj: The object or type for which to get the canonical name. + + Returns: + The canonical name as a string. + """ + obj_type = type(obj) + if obj_type in cls.__type_to_canonical_name__: + return cls.__type_to_canonical_name__[obj_type] raise ValueError(f"Could not find canonical name for {obj}") @classmethod From 9a3515635a39faf33035e765f94cc592747ddad3 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 11:11:30 +0200 Subject: [PATCH 073/117] fix tests --- notebooks/generate_canonical_names.ipynb | 48 +++++++ packages/syft/src/syft/serde/import os.py | 126 ++++++++++++++++++ packages/syft/src/syft/serde/recursive.py | 2 +- packages/syft/tests/syft/hash_test.py | 6 +- .../migrations/protocol_communication_test.py | 10 +- packages/syft/tests/syft/serializable_test.py | 67 ++++++++-- .../syft/tests/syft/stores/base_stash_test.py | 1 + .../tests/syft/stores/store_mocks_test.py | 5 +- scripts/generate_canonical_names.py | 126 ++++++++++++++++++ 9 files changed, 375 insertions(+), 16 deletions(-) create mode 100644 packages/syft/src/syft/serde/import os.py create mode 100644 scripts/generate_canonical_names.py diff --git a/notebooks/generate_canonical_names.ipynb b/notebooks/generate_canonical_names.ipynb index 9b35509662c..712dbe03004 100644 --- a/notebooks/generate_canonical_names.ipynb +++ b/notebooks/generate_canonical_names.ipynb @@ -1,5 +1,53 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": 11, + "id": "9c842cfb-1b10-4cbc-b17a-7f96fb021e51", + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "module 'importlib' has no attribute '__version__'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[11], line 5\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mimportlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmetadata\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Distribution\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mimportlib\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m \u001b[43mimportlib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__version__\u001b[49m\n", + "\u001b[0;31mAttributeError\u001b[0m: module 'importlib' has no attribute '__version__'" + ] + } + ], + "source": [ + "# stdlib\n", + "import importlib\n", + "from importlib.metadata import Distribution\n", + "\n", + "importlib.__version__" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "3a6dd59c-bf53-4d20-aefe-b7ae1b60cdb6", + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "type object 'Distribution' has no attribute 'origin'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[10], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mDistribution\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43morigin\u001b[49m\n", + "\u001b[0;31mAttributeError\u001b[0m: type object 'Distribution' has no attribute 'origin'" + ] + } + ], + "source": [ + "Distribution.origin" + ] + }, { "cell_type": "code", "execution_count": 1, diff --git a/packages/syft/src/syft/serde/import os.py b/packages/syft/src/syft/serde/import os.py new file mode 100644 index 00000000000..2b2a711e567 --- /dev/null +++ b/packages/syft/src/syft/serde/import os.py @@ -0,0 +1,126 @@ +# stdlib +import ast +import inspect +import os + +# If variable is set, search for all serializable classes without canonical names +os.environ["SYFT_SEARCH_MISSING_CANONICAL_NAME"] = "true" + +# syft absolute +# NOTE import has to happen after setting the environment variable + +# relative +from ..types.syft_object_registry import SyftObjectRegistry # noqa: E402 +from .recursive import SYFT_CLASSES_MISSING_CANONICAL_NAME # noqa: E402 + + +class DecoratorFinder(ast.NodeVisitor): + def __init__(self, class_name: str, decorator_name: str): + self.class_name = class_name + self.decorator_name = decorator_name + self.decorator: ast.Call | None = None + + def visit_ClassDef(self, node: ast.ClassDef) -> None: + if node.name == self.class_name: + for decorator in node.decorator_list: + if ( + isinstance(decorator, ast.Call) + and getattr(decorator.func, "id", None) == self.decorator_name + ): + self.decorator = decorator + self.generic_visit(node) + + +def get_class_file_path(cls: type) -> str: + return inspect.getfile(cls) + + +def get_decorator_with_lines( + file_path: str, class_name: str, decorator_name: str +) -> tuple[ast.Call | None, int | None, int | None]: + with open(file_path) as source: + tree = ast.parse(source.read()) + + finder = DecoratorFinder(class_name, decorator_name) + finder.visit(tree) + + if finder.decorator: + start_line = finder.decorator.lineno - 1 + end_line = ( + finder.decorator.end_lineno + if hasattr(finder.decorator, "end_lineno") + else finder.decorator.lineno + ) + return finder.decorator, start_line, end_line + return None, None, None + + +def add_canonical_name_version(decorator: ast.Call, class_name: str) -> ast.Call: + new_decorator = decorator + + canonical_name_exists = any( + kw.arg == "canonical_name" for kw in new_decorator.keywords + ) + version_exists = any(kw.arg == "version" for kw in new_decorator.keywords) + + if not canonical_name_exists: + new_decorator.keywords.append( + ast.keyword(arg="canonical_name", value=ast.Constant(value=class_name)) + ) + if not version_exists: + new_decorator.keywords.append( + ast.keyword(arg="version", value=ast.Constant(value=1)) + ) + + return ast.copy_location(new_decorator, decorator) + + +def update_decorator_for_cls( + cls: type, existing_canonical_names: list[str] +) -> str | None: + file_path = inspect.getfile(cls) + class_name = cls.__name__ + + decorator, start_line, end_line = get_decorator_with_lines( + file_path, class_name, "serializable" + ) + + if decorator is None: + print( + f"{cls.__module__}: Could not find decorator for class {class_name}. Did not update canonical name." + ) + return None + if start_line is None or end_line is None: + print( + f"{cls.__module__}: No start/end lines for decorator in class {class_name}. Did not update canonical name." + ) + return None + + if class_name in existing_canonical_names: + print( + f"{cls.__module__}: {class_name} is already a registered canonical name. Did not update canonical name." + ) + return None + + new_decorator = add_canonical_name_version(decorator, class_name) + new_decorator_code = ast.unparse(new_decorator).split("\n") + new_decorator_code[0] = "@" + new_decorator_code[0] + + with open(file_path) as file: + lines = file.readlines() + + lines[start_line:end_line] = [line + "\n" for line in new_decorator_code] + + with open(file_path, "w") as file: + file.writelines(lines) + + print(f"Updated {cls.__module__}.{cls.__name__}") + return class_name + + +if __name__ == "__main__": + existing_cnames = list(SyftObjectRegistry.__object_serialization_registry__.keys()) + for cls in SYFT_CLASSES_MISSING_CANONICAL_NAME: + new_name = update_decorator_for_cls(cls, existing_cnames) + if new_name: + existing_cnames.append(new_name) diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index 289bd1c9cbd..5102608254e 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -125,7 +125,7 @@ def skip_unregistered_class( """ search_unregistered_classes = ( - os.getenv("SYFT_SEARCH_UNREGISTERED_CLASSES", False) == "1" + os.getenv("SYFT_SEARCH_MISSING_CANONICAL_NAME", False) == "true" ) if not search_unregistered_classes: return False diff --git a/packages/syft/tests/syft/hash_test.py b/packages/syft/tests/syft/hash_test.py index df97de4a19e..2e8dbfecc86 100644 --- a/packages/syft/tests/syft/hash_test.py +++ b/packages/syft/tests/syft/hash_test.py @@ -8,7 +8,11 @@ from syft.types.syft_object import SyftHashableObject -@serializable(attrs=["key", "value", "flag"]) +@serializable( + attrs=["key", "value", "flag"], + canonical_name="MockObject", + version=1, +) class MockObject(SyftHashableObject): key: str value: str diff --git a/packages/syft/tests/syft/migrations/protocol_communication_test.py b/packages/syft/tests/syft/migrations/protocol_communication_test.py index d7b9bd3ad79..31103a88af1 100644 --- a/packages/syft/tests/syft/migrations/protocol_communication_test.py +++ b/packages/syft/tests/syft/migrations/protocol_communication_test.py @@ -75,7 +75,10 @@ def mock_v2_to_v1(): def get_stash_klass(syft_object: type[SyftBaseObject]): - @serializable() + @serializable( + canonical_name="SyftMockObjectStash", + version=1, + ) class SyftMockObjectStash(BaseStash): object_type = syft_object settings: PartitionSettings = PartitionSettings( @@ -92,7 +95,10 @@ def __init__(self, store: DocumentStore) -> None: def setup_service_method(syft_object): stash_klass: BaseStash = get_stash_klass(syft_object=syft_object) - @serializable() + @serializable( + canonical_name="SyftMockObjectService", + version=1, + ) class SyftMockObjectService(AbstractService): store: DocumentStore stash: stash_klass diff --git a/packages/syft/tests/syft/serializable_test.py b/packages/syft/tests/syft/serializable_test.py index 6f84f7afde1..154589c2190 100644 --- a/packages/syft/tests/syft/serializable_test.py +++ b/packages/syft/tests/syft/serializable_test.py @@ -21,7 +21,11 @@ class AbstractBase: uid: str -@serializable(attrs=["uid", "value"]) +@serializable( + attrs=["uid", "value"], + canonical_name="Base", + version=1, +) class Base(AbstractBase): """Serialize: uid, value""" @@ -32,7 +36,11 @@ def __init__(self, uid: str, value: int): self.value = value -@serializable(attrs=["status"]) +@serializable( + attrs=["status"], + canonical_name="Derived", + version=1, +) class Derived(Base): """Serialize: uid, value, status""" @@ -43,7 +51,12 @@ def __init__(self, uid: str, value: int, status: int) -> None: self.status = status -@serializable(attrs=["status"], without=["uid"]) +@serializable( + attrs=["status"], + without=["uid"], + canonical_name="DerivedWithoutAttrs", + version=1, +) class DerivedWithoutAttrs(Base): """Serialize: value, status""" @@ -54,7 +67,12 @@ def __init__(self, uid: str, value: int, status: int) -> None: self.status = status -@serializable(attrs=["status"], inherit=False) +@serializable( + attrs=["status"], + inherit=False, + canonical_name="DerivedNoInherit", + version=1, +) class DerivedNoInherit(Base): """Serialize: status""" @@ -65,7 +83,12 @@ def __init__(self, uid: str, value: int, status: int) -> None: self.status = status -@serializable(attrs=["uid", "value"], inheritable=False) +@serializable( + attrs=["uid", "value"], + inheritable=False, + canonical_name="BaseAttrsNonInheritable", + version=1, +) class BaseAttrsNonInheritable(AbstractBase): """Serialize: uid, value (Derived cannot inherit base attrs)""" @@ -76,7 +99,11 @@ def __init__(self, uid: str = None, value: int = None): self.value = value -@serializable(attrs=["status"]) +@serializable( + attrs=["status"], + canonical_name="DerivedWithoutBaseAttrs", + version=1, +) class DerivedWithoutBaseAttrs(BaseAttrsNonInheritable): """Serialize: status (Dervied cannot inherit base attrs)""" @@ -168,7 +195,10 @@ def test_derived_without_base_attrs(): # ------------------------------ Pydantic classes ------------------------------ -@serializable() +@serializable( + canonical_name="PydBase", + version=1, +) class PydBase(BaseModel): """Serialize: uid, value, flag""" @@ -177,7 +207,10 @@ class PydBase(BaseModel): flag: bool | None = None -@serializable() +@serializable( + canonical_name="PydDerived", + version=1, +) class PydDerived(PydBase): """Serialize: uid, value, flag, source, target""" @@ -185,7 +218,11 @@ class PydDerived(PydBase): target: str -@serializable(without=["uid"]) +@serializable( + without=["uid"], + canonical_name="PydDerivedWithoutAttr", + version=1, +) class PydDerivedWithoutAttr(PydBase): """ Serialize: value, flag, source, target @@ -196,7 +233,11 @@ class PydDerivedWithoutAttr(PydBase): target: str -@serializable(without=["uid", "flag", "config"]) +@serializable( + without=["uid", "flag", "config"], + canonical_name="PydDerivedWithoutAttrs", + version=1, +) class PydDerivedWithoutAttrs(PydBase): """ Serialize: value, source, target @@ -208,7 +249,11 @@ class PydDerivedWithoutAttrs(PydBase): config: dict | None = None -@serializable(attrs=["source", "target"]) +@serializable( + attrs=["source", "target"], + canonical_name="PydDerivedOnly", + version=1, +) class PydDerivedOnly(PydBase): """ Serialize: source, target diff --git a/packages/syft/tests/syft/stores/base_stash_test.py b/packages/syft/tests/syft/stores/base_stash_test.py index 2dd5e443080..ba4975305a1 100644 --- a/packages/syft/tests/syft/stores/base_stash_test.py +++ b/packages/syft/tests/syft/stores/base_stash_test.py @@ -27,6 +27,7 @@ @serializable() class MockObject(SyftObject): __canonical_name__ = "base_stash_mock_object_type" + __version__ = 1 id: UID name: str desc: str diff --git a/packages/syft/tests/syft/stores/store_mocks_test.py b/packages/syft/tests/syft/stores/store_mocks_test.py index 9ab6a71cb57..8dc8f4e43bc 100644 --- a/packages/syft/tests/syft/stores/store_mocks_test.py +++ b/packages/syft/tests/syft/stores/store_mocks_test.py @@ -12,7 +12,10 @@ from syft.types.uid import UID -@serializable() +@serializable( + canonical_name="MockKeyValueBackingStore", + version=1, +) class MockKeyValueBackingStore(dict, KeyValueBackingStore): def __init__( self, diff --git a/scripts/generate_canonical_names.py b/scripts/generate_canonical_names.py new file mode 100644 index 00000000000..1744c67db15 --- /dev/null +++ b/scripts/generate_canonical_names.py @@ -0,0 +1,126 @@ +# stdlib +import ast +import inspect +import os + +# If variable is set, search for all serializable classes without canonical names +os.environ["SYFT_SEARCH_MISSING_CANONICAL_NAME"] = "true" + +# syft absolute +# NOTE import has to happen after setting the environment variable + +# relative +from ..serde.recursive import SYFT_CLASSES_MISSING_CANONICAL_NAME # noqa: E402 +from ..types.syft_object_registry import SyftObjectRegistry # noqa: E402 + + +class DecoratorFinder(ast.NodeVisitor): + def __init__(self, class_name: str, decorator_name: str): + self.class_name = class_name + self.decorator_name = decorator_name + self.decorator: ast.Call | None = None + + def visit_ClassDef(self, node: ast.ClassDef) -> None: + if node.name == self.class_name: + for decorator in node.decorator_list: + if ( + isinstance(decorator, ast.Call) + and getattr(decorator.func, "id", None) == self.decorator_name + ): + self.decorator = decorator + self.generic_visit(node) + + +def get_class_file_path(cls: type) -> str: + return inspect.getfile(cls) + + +def get_decorator_with_lines( + file_path: str, class_name: str, decorator_name: str +) -> tuple[ast.Call | None, int | None, int | None]: + with open(file_path) as source: + tree = ast.parse(source.read()) + + finder = DecoratorFinder(class_name, decorator_name) + finder.visit(tree) + + if finder.decorator: + start_line = finder.decorator.lineno - 1 + end_line = ( + finder.decorator.end_lineno + if hasattr(finder.decorator, "end_lineno") + else finder.decorator.lineno + ) + return finder.decorator, start_line, end_line + return None, None, None + + +def add_canonical_name_version(decorator: ast.Call, class_name: str) -> ast.Call: + new_decorator = decorator + + canonical_name_exists = any( + kw.arg == "canonical_name" for kw in new_decorator.keywords + ) + version_exists = any(kw.arg == "version" for kw in new_decorator.keywords) + + if not canonical_name_exists: + new_decorator.keywords.append( + ast.keyword(arg="canonical_name", value=ast.Constant(value=class_name)) + ) + if not version_exists: + new_decorator.keywords.append( + ast.keyword(arg="version", value=ast.Constant(value=1)) + ) + + return ast.copy_location(new_decorator, decorator) + + +def update_decorator_for_cls( + cls: type, existing_canonical_names: list[str] +) -> str | None: + file_path = inspect.getfile(cls) + class_name = cls.__name__ + + decorator, start_line, end_line = get_decorator_with_lines( + file_path, class_name, "serializable" + ) + + if decorator is None: + print( + f"{cls.__module__}: Could not find decorator for class {class_name}. Did not update canonical name." + ) + return None + if start_line is None or end_line is None: + print( + f"{cls.__module__}: No start/end lines for decorator in class {class_name}. Did not update canonical name." + ) + return None + + if class_name in existing_canonical_names: + print( + f"{cls.__module__}: {class_name} is already a registered canonical name. Did not update canonical name." + ) + return None + + new_decorator = add_canonical_name_version(decorator, class_name) + new_decorator_code = ast.unparse(new_decorator).split("\n") + new_decorator_code[0] = "@" + new_decorator_code[0] + + with open(file_path) as file: + lines = file.readlines() + + lines[start_line:end_line] = [line + "\n" for line in new_decorator_code] + + with open(file_path, "w") as file: + file.writelines(lines) + + print(f"Updated {cls.__module__}.{cls.__name__}") + return class_name + + +def update_canonical_names(): + existing_cnames = list(SyftObjectRegistry.__object_serialization_registry__.keys()) + for cls in SYFT_CLASSES_MISSING_CANONICAL_NAME: + new_name = update_decorator_for_cls(cls, existing_cnames) + if new_name: + existing_cnames.append(new_name) From 3cb730b713a1bfbed1a3d4445c0edc56080eeafb Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 11:15:03 +0200 Subject: [PATCH 074/117] remove notebook --- notebooks/generate_canonical_names.ipynb | 315 ----------------------- 1 file changed, 315 deletions(-) delete mode 100644 notebooks/generate_canonical_names.ipynb diff --git a/notebooks/generate_canonical_names.ipynb b/notebooks/generate_canonical_names.ipynb deleted file mode 100644 index 712dbe03004..00000000000 --- a/notebooks/generate_canonical_names.ipynb +++ /dev/null @@ -1,315 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 11, - "id": "9c842cfb-1b10-4cbc-b17a-7f96fb021e51", - "metadata": {}, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "module 'importlib' has no attribute '__version__'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[11], line 5\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mimportlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmetadata\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Distribution\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mimportlib\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m \u001b[43mimportlib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__version__\u001b[49m\n", - "\u001b[0;31mAttributeError\u001b[0m: module 'importlib' has no attribute '__version__'" - ] - } - ], - "source": [ - "# stdlib\n", - "import importlib\n", - "from importlib.metadata import Distribution\n", - "\n", - "importlib.__version__" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "3a6dd59c-bf53-4d20-aefe-b7ae1b60cdb6", - "metadata": {}, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "type object 'Distribution' has no attribute 'origin'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[10], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mDistribution\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43morigin\u001b[49m\n", - "\u001b[0;31mAttributeError\u001b[0m: type object 'Distribution' has no attribute 'origin'" - ] - } - ], - "source": [ - "Distribution.origin" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "107f1473-4451-4499-8e28-105b29da3373", - "metadata": {}, - "outputs": [], - "source": [ - "# stdlib\n", - "import os\n", - "\n", - "os.environ[\"SYFT_SEARCH_UNREGISTERED_CLASSES\"] = \"1\"" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "50d4a32c-d7c3-4abb-8814-1bb39eb557b2", - "metadata": {}, - "outputs": [], - "source": [ - "# stdlib\n", - "\n", - "# syft absolute\n", - "from syft.serde.recursive import SYFT_CLASSES_MISSING_CANONICAL_NAME\n", - "from syft.types.syft_object_registry import SyftObjectRegistry" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "e4cfba28-f0c1-4289-aae4-a13ba4ce6004", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(True,\n", - " bytes>,\n", - " functools.partial(, ),\n", - " None,\n", - " [],\n", - " {},\n", - " [],\n", - " dict,\n", - " None,\n", - " 1)" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "SyftObjectRegistry.__object_serialization_registry__[\"dict\"][1]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "51eca6cc-8d29-4148-8a85-f6ed23a016b3", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "existing_cnames = SyftObjectRegistry.__object_serialization_registry__.keys()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "ef1f89af-40c1-4a47-a003-ff1b9691d9d4", - "metadata": {}, - "outputs": [], - "source": [ - "# stdlib\n", - "import ast\n", - "import inspect\n", - "\n", - "\n", - "class DecoratorFinder(ast.NodeVisitor):\n", - " def __init__(self, class_name: str, decorator_name: str):\n", - " self.class_name = class_name\n", - " self.decorator_name = decorator_name\n", - " self.decorator: ast.Call | None = None\n", - "\n", - " def visit_ClassDef(self, node: ast.ClassDef) -> None:\n", - " if node.name == self.class_name:\n", - " for decorator in node.decorator_list:\n", - " if (\n", - " isinstance(decorator, ast.Call)\n", - " and getattr(decorator.func, \"id\", None) == self.decorator_name\n", - " ):\n", - " self.decorator = decorator\n", - " self.generic_visit(node)\n", - "\n", - "\n", - "def get_class_file_path(cls: type) -> str:\n", - " return inspect.getfile(cls)\n", - "\n", - "\n", - "def get_decorator_with_lines(\n", - " file_path: str, class_name: str, decorator_name: str\n", - ") -> tuple[ast.Call | None, int | None, int | None]:\n", - " with open(file_path) as source:\n", - " tree = ast.parse(source.read())\n", - "\n", - " finder = DecoratorFinder(class_name, decorator_name)\n", - " finder.visit(tree)\n", - "\n", - " if finder.decorator:\n", - " start_line = finder.decorator.lineno - 1\n", - " end_line = (\n", - " finder.decorator.end_lineno\n", - " if hasattr(finder.decorator, \"end_lineno\")\n", - " else finder.decorator.lineno\n", - " )\n", - " return finder.decorator, start_line, end_line\n", - " return None, None, None" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "ef8eef16-c182-475d-b105-d1fe7778a2fd", - "metadata": {}, - "outputs": [], - "source": [ - "def add_canonical_name_version(decorator: ast.Call, class_name: str) -> ast.Call:\n", - " new_decorator = decorator\n", - "\n", - " canonical_name_exists = any(\n", - " kw.arg == \"canonical_name\" for kw in new_decorator.keywords\n", - " )\n", - " version_exists = any(kw.arg == \"version\" for kw in new_decorator.keywords)\n", - "\n", - " if not canonical_name_exists:\n", - " new_decorator.keywords.append(\n", - " ast.keyword(arg=\"canonical_name\", value=ast.Constant(value=class_name))\n", - " )\n", - " if not version_exists:\n", - " new_decorator.keywords.append(\n", - " ast.keyword(arg=\"version\", value=ast.Constant(value=1))\n", - " )\n", - "\n", - " return ast.copy_location(new_decorator, decorator)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "51ab50fe-37c6-41a4-b1c2-549036727f0d", - "metadata": {}, - "outputs": [], - "source": [ - "def update_decorator_for_cls(\n", - " cls: type, existing_canonical_names: list[str]\n", - ") -> str | None:\n", - " file_path = inspect.getfile(cls)\n", - " class_name = cls.__name__\n", - "\n", - " decorator, start_line, end_line = get_decorator_with_lines(\n", - " file_path, class_name, \"serializable\"\n", - " )\n", - "\n", - " if decorator is None:\n", - " print(\n", - " f\"{cls.__module__}: Could not find decorator for class {class_name}. Did not update canonical name.\"\n", - " )\n", - " return None\n", - " if start_line is None or end_line is None:\n", - " print(\n", - " f\"{cls.__module__}: No start/end lines for decorator in class {class_name}. Did not update canonical name.\"\n", - " )\n", - " return None\n", - "\n", - " if class_name in existing_canonical_names:\n", - " print(\n", - " f\"{cls.__module__}: {class_name} is already a registered canonical name. Did not update canonical name.\"\n", - " )\n", - " return None\n", - "\n", - " new_decorator = add_canonical_name_version(decorator, class_name)\n", - " new_decorator_code = ast.unparse(new_decorator).split(\"\\n\")\n", - " new_decorator_code[0] = \"@\" + new_decorator_code[0]\n", - "\n", - " with open(file_path) as file:\n", - " lines = file.readlines()\n", - "\n", - " lines[start_line:end_line] = [line + \"\\n\" for line in new_decorator_code]\n", - "\n", - " with open(file_path, \"w\") as file:\n", - " file.writelines(lines)\n", - "\n", - " print(f\"Updated {cls.__module__}.{cls.__name__}\")\n", - " return class_name" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "158c4044-6f79-49f1-abd3-cbf336883afc", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Updated syft.service.network.utils.PeerHealthCheckTask\n" - ] - } - ], - "source": [ - "existing_cnames = list(existing_cnames)\n", - "\n", - "for cls in SYFT_CLASSES_MISSING_CANONICAL_NAME:\n", - " new_name = update_decorator_for_cls(cls, existing_cnames)\n", - " if new_name:\n", - " existing_cnames.append(new_name)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "b383658c-63dc-401a-b8e5-4a051624b3b5", - "metadata": {}, - "outputs": [], - "source": [ - "os.environ[\"SYFT_SEARCH_UNREGISTERED_CLASSES\"] = \"\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1a0d4ada-50e1-4bab-a6da-bd38d82a7cdd", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 9d0df9f2e21d59ef934a04a7fcc66851f6f3a1c3 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 11:20:37 +0200 Subject: [PATCH 075/117] delete file --- packages/syft/src/syft/serde/import os.py | 126 ---------------------- 1 file changed, 126 deletions(-) delete mode 100644 packages/syft/src/syft/serde/import os.py diff --git a/packages/syft/src/syft/serde/import os.py b/packages/syft/src/syft/serde/import os.py deleted file mode 100644 index 2b2a711e567..00000000000 --- a/packages/syft/src/syft/serde/import os.py +++ /dev/null @@ -1,126 +0,0 @@ -# stdlib -import ast -import inspect -import os - -# If variable is set, search for all serializable classes without canonical names -os.environ["SYFT_SEARCH_MISSING_CANONICAL_NAME"] = "true" - -# syft absolute -# NOTE import has to happen after setting the environment variable - -# relative -from ..types.syft_object_registry import SyftObjectRegistry # noqa: E402 -from .recursive import SYFT_CLASSES_MISSING_CANONICAL_NAME # noqa: E402 - - -class DecoratorFinder(ast.NodeVisitor): - def __init__(self, class_name: str, decorator_name: str): - self.class_name = class_name - self.decorator_name = decorator_name - self.decorator: ast.Call | None = None - - def visit_ClassDef(self, node: ast.ClassDef) -> None: - if node.name == self.class_name: - for decorator in node.decorator_list: - if ( - isinstance(decorator, ast.Call) - and getattr(decorator.func, "id", None) == self.decorator_name - ): - self.decorator = decorator - self.generic_visit(node) - - -def get_class_file_path(cls: type) -> str: - return inspect.getfile(cls) - - -def get_decorator_with_lines( - file_path: str, class_name: str, decorator_name: str -) -> tuple[ast.Call | None, int | None, int | None]: - with open(file_path) as source: - tree = ast.parse(source.read()) - - finder = DecoratorFinder(class_name, decorator_name) - finder.visit(tree) - - if finder.decorator: - start_line = finder.decorator.lineno - 1 - end_line = ( - finder.decorator.end_lineno - if hasattr(finder.decorator, "end_lineno") - else finder.decorator.lineno - ) - return finder.decorator, start_line, end_line - return None, None, None - - -def add_canonical_name_version(decorator: ast.Call, class_name: str) -> ast.Call: - new_decorator = decorator - - canonical_name_exists = any( - kw.arg == "canonical_name" for kw in new_decorator.keywords - ) - version_exists = any(kw.arg == "version" for kw in new_decorator.keywords) - - if not canonical_name_exists: - new_decorator.keywords.append( - ast.keyword(arg="canonical_name", value=ast.Constant(value=class_name)) - ) - if not version_exists: - new_decorator.keywords.append( - ast.keyword(arg="version", value=ast.Constant(value=1)) - ) - - return ast.copy_location(new_decorator, decorator) - - -def update_decorator_for_cls( - cls: type, existing_canonical_names: list[str] -) -> str | None: - file_path = inspect.getfile(cls) - class_name = cls.__name__ - - decorator, start_line, end_line = get_decorator_with_lines( - file_path, class_name, "serializable" - ) - - if decorator is None: - print( - f"{cls.__module__}: Could not find decorator for class {class_name}. Did not update canonical name." - ) - return None - if start_line is None or end_line is None: - print( - f"{cls.__module__}: No start/end lines for decorator in class {class_name}. Did not update canonical name." - ) - return None - - if class_name in existing_canonical_names: - print( - f"{cls.__module__}: {class_name} is already a registered canonical name. Did not update canonical name." - ) - return None - - new_decorator = add_canonical_name_version(decorator, class_name) - new_decorator_code = ast.unparse(new_decorator).split("\n") - new_decorator_code[0] = "@" + new_decorator_code[0] - - with open(file_path) as file: - lines = file.readlines() - - lines[start_line:end_line] = [line + "\n" for line in new_decorator_code] - - with open(file_path, "w") as file: - file.writelines(lines) - - print(f"Updated {cls.__module__}.{cls.__name__}") - return class_name - - -if __name__ == "__main__": - existing_cnames = list(SyftObjectRegistry.__object_serialization_registry__.keys()) - for cls in SYFT_CLASSES_MISSING_CANONICAL_NAME: - new_name = update_decorator_for_cls(cls, existing_cnames) - if new_name: - existing_cnames.append(new_name) From 10ccf1df2153d2781f6b2dbdfe6896208b308cde Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 11:27:13 +0200 Subject: [PATCH 076/117] remove comments --- packages/syft/src/syft/serde/recursive.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index 5102608254e..c9d1dcf592f 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -152,7 +152,6 @@ def recursive_serde_register( attribute_list: set[str] = set() cls = type(cls) if not isinstance(cls, type) else cls - # fqn = f"{cls.__module__}.{cls.__name__}" if skip_unregistered_class(cls, canonical_name, version): return @@ -222,14 +221,11 @@ def recursive_serde_register( version, ) - # TYPE_BANK[fqn] = serde_attributes - SyftObjectRegistry.register_cls(canonical_name, version, serde_attributes) alias_fqn = check_fqn_alias(cls) if isinstance(alias_fqn, tuple): for alias in alias_fqn: - # TYPE_BANK[alias] = serde_attributes alias_canonical_name = canonical_name + f"_{alias}" SyftObjectRegistry.register_cls(alias_canonical_name, 1, serde_attributes) From d3394603f953616e91d588db2730523994939794 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 11:41:25 +0200 Subject: [PATCH 077/117] fix result serde --- packages/syft/src/syft/serde/third_party.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/syft/src/syft/serde/third_party.py b/packages/syft/src/syft/serde/third_party.py index 90d84103360..6a46f789c26 100644 --- a/packages/syft/src/syft/serde/third_party.py +++ b/packages/syft/src/syft/serde/third_party.py @@ -21,7 +21,6 @@ from pymongo.collection import Collection from result import Err from result import Ok -from result import Result # relative from ..types.dicttuple import DictTuple @@ -63,9 +62,6 @@ recursive_serde_register( Err, serialize_attrs=["_value"], canonical_name="result_Err", version=1 ) -recursive_serde_register( - Result, serialize_attrs=["_value"], canonical_name="result_Result", version=1 -) # exceptions recursive_serde_register(cls=TypeError, canonical_name="TypeError", version=1) From d0892a64a908f2ebb28cb47cf6c8c1b29a03c57c Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 12:22:47 +0200 Subject: [PATCH 078/117] add version to get_cname --- packages/syft/src/syft/serde/recursive.py | 6 +----- .../syft/src/syft/types/syft_object_registry.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index c9d1dcf592f..19ede3d0040 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -283,11 +283,7 @@ def rs_object2proto(self: Any, for_hashing: bool = False) -> _DynamicStructBuild msg = recursive_scheme.new_message() # todo: rewrite and make sure every object has a canonical name and version - canonical_name = SyftObjectRegistry.get_canonical_name(self) - if is_type: - version = 1 - else: - version = getattr(self, "__version__", 1) + canonical_name, version = SyftObjectRegistry.get_canonical_name_version(self) if not SyftObjectRegistry.has_serde_class("", canonical_name, version): # third party diff --git a/packages/syft/src/syft/types/syft_object_registry.py b/packages/syft/src/syft/types/syft_object_registry.py index 1742cff3f79..7d93fa44207 100644 --- a/packages/syft/src/syft/types/syft_object_registry.py +++ b/packages/syft/src/syft/types/syft_object_registry.py @@ -16,7 +16,7 @@ class SyftObjectRegistry: __object_transform_registry__: dict[str, Callable] = {} __object_serialization_registry__: dict[str, dict[int, tuple]] = {} - __type_to_canonical_name__: dict[type, str] = {} + __type_to_canonical_name__: dict[type, tuple[str, int]] = {} @classmethod def register_cls( @@ -28,7 +28,7 @@ def register_cls( serde_attributes ) - cls.__type_to_canonical_name__[serde_attributes[7]] = canonical_name + cls.__type_to_canonical_name__[serde_attributes[7]] = (canonical_name, version) @classmethod def get_versions(cls, canonical_name: str) -> list[int]: @@ -39,7 +39,7 @@ def get_versions(cls, canonical_name: str) -> list[int]: return list(available_versions.keys()) @classmethod - def get_canonical_name(cls, obj: Any) -> str: + def get_canonical_name_version(cls, obj: Any) -> tuple[str, int]: """ Retrieves the canonical name for both objects and types. @@ -50,16 +50,16 @@ def get_canonical_name(cls, obj: Any) -> str: If the object is not registered in the registry, a ValueError is raised. Examples: - get_canonical_name([1,2,3]) -> "list" - get_canonical_name(list) -> "type" - get_canonical_name(MyEnum.A) -> "MyEnum" - get_canonical_name(MyEnum) -> "EnumMeta" + get_canonical_name_version([1,2,3]) -> "list" + get_canonical_name_version(list) -> "type" + get_canonical_name_version(MyEnum.A) -> "MyEnum" + get_canonical_name_version(MyEnum) -> "EnumMeta" Args: obj: The object or type for which to get the canonical name. Returns: - The canonical name as a string. + The canonical name and version of the object or type. """ obj_type = type(obj) if obj_type in cls.__type_to_canonical_name__: From b5633fadac6e501edf5306674d2803ee80a8cc04 Mon Sep 17 00:00:00 2001 From: eelcovdw Date: Tue, 16 Jul 2024 12:49:57 +0200 Subject: [PATCH 079/117] remove metaclass from serde --- packages/syft/src/syft/types/syft_object_registry.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/syft/src/syft/types/syft_object_registry.py b/packages/syft/src/syft/types/syft_object_registry.py index 7d93fa44207..7226e6a246f 100644 --- a/packages/syft/src/syft/types/syft_object_registry.py +++ b/packages/syft/src/syft/types/syft_object_registry.py @@ -61,6 +61,12 @@ def get_canonical_name_version(cls, obj: Any) -> tuple[str, int]: Returns: The canonical name and version of the object or type. """ + + # NOTE the metaclass of the object is not needed during serde + # so we can safely ignore it + if isinstance(obj, type): + return cls.__type_to_canonical_name__[type] + obj_type = type(obj) if obj_type in cls.__type_to_canonical_name__: return cls.__type_to_canonical_name__[obj_type] From 095fb4e72d59787d704af5330dcae5d2e8fc1148 Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Tue, 16 Jul 2024 23:03:03 +0200 Subject: [PATCH 080/117] make serialization of type vars less dynamic --- packages/syft/src/syft/client/api.py | 1 + .../syft/src/syft/custom_worker/config.py | 1 + .../src/syft/protocol/protocol_version.json | 14 +++++ .../src/syft/serde/recursive_primitives.py | 53 ++++++++++++++----- .../src/syft/service/action/action_object.py | 1 + .../syft/src/syft/service/network/routes.py | 1 + .../src/syft/service/notifier/notifier.py | 1 + .../syft/src/syft/service/project/project.py | 1 + packages/syft/src/syft/types/syft_object.py | 1 + .../src/syft/types/syft_object_registry.py | 13 +++-- 10 files changed, 72 insertions(+), 15 deletions(-) diff --git a/packages/syft/src/syft/client/api.py b/packages/syft/src/syft/client/api.py index 6f7253076c4..55c38a3d207 100644 --- a/packages/syft/src/syft/client/api.py +++ b/packages/syft/src/syft/client/api.py @@ -1401,6 +1401,7 @@ def validate_callable_args_and_kwargs( pass else: _type_str = getattr(t, "__name__", str(t)) + raise msg = f"Arg is `{arg}`. \nIt must be of type `{_type_str}`, not `{type(arg).__name__}`" if msg: diff --git a/packages/syft/src/syft/custom_worker/config.py b/packages/syft/src/syft/custom_worker/config.py index 254d64b702e..f01266221bd 100644 --- a/packages/syft/src/syft/custom_worker/config.py +++ b/packages/syft/src/syft/custom_worker/config.py @@ -79,6 +79,7 @@ def merged_custom_cmds(self, sep: str = ";") -> str: return sep.join(self.custom_cmds) +@serializable(canonical_name="WorkerConfig", version=1) class WorkerConfig(SyftBaseModel): pass diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index 6602155d200..c500d823f3a 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -1190,6 +1190,20 @@ "hash": "ae07a6345762b8ebe9d2a100776e2405fd17516c9d224913a3358c96480ba889", "action": "add" } + }, + "SyftObject": { + "2": { + "version": 2, + "hash": "26efd140219eb651d18467b0430b9dbde17c57670f050e300823075f6e44d3e5", + "action": "add" + } + }, + "ProjectEvent": { + "2": { + "version": 2, + "hash": "cbe61714b816b769a856fe7b47c3001e6da716883b2845e03485e3e7b0a02b91", + "action": "add" + } } } } diff --git a/packages/syft/src/syft/serde/recursive_primitives.py b/packages/syft/src/syft/serde/recursive_primitives.py index 9385219b8e0..8808979c45c 100644 --- a/packages/syft/src/syft/serde/recursive_primitives.py +++ b/packages/syft/src/syft/serde/recursive_primitives.py @@ -8,6 +8,7 @@ from enum import Enum from enum import EnumMeta import functools +import inspect import pathlib from pathlib import PurePath import sys @@ -24,8 +25,12 @@ from typing import _SpecialGenericAlias from typing import _UnionGenericAlias from typing import cast +import typing import weakref +from result import Result +from syft.types.syft_object_registry import SyftObjectRegistry + # relative from .capnp import get_capnp_schema from .recursive import chunk_bytes @@ -169,22 +174,29 @@ def deserialize_enum(enum_type: type, enum_buf: bytes) -> Enum: return enum_type(enum_value) -def serialize_type(serialized_type: type) -> bytes: +def serialize_type(_type_to_serialize: type) -> bytes: # relative - from ..util.util import full_name_with_qualname + type_to_serialize = typing.get_origin(_type_to_serialize) or _type_to_serialize + canonical_name, version = SyftObjectRegistry.get_identifier_for_type(type_to_serialize) + return f"{canonical_name}:{version}".encode() - fqn = full_name_with_qualname(klass=serialized_type) - module_parts = fqn.split(".") - return ".".join(module_parts).encode() + # from ..util.util import full_name_with_qualname + + # fqn = full_name_with_qualname(klass=serialized_type) + # module_parts = fqn.split(".") + # return ".".join(module_parts).encode() def deserialize_type(type_blob: bytes) -> type: deserialized_type = type_blob.decode() - module_parts = deserialized_type.split(".") - klass = module_parts.pop() - klass = "None" if klass == "NoneType" else klass - exception_type = getattr(sys.modules[".".join(module_parts)], klass) - return exception_type + canonical_name, version = deserialized_type.split(":", 1) + return SyftObjectRegistry.get_serde_class(canonical_name, int(version)) + + # module_parts = deserialized_type.split(".") + # klass = module_parts.pop() + # klass = "None" if klass == "NoneType" else klass + # exception_type = getattr(sys.modules[".".join(module_parts)], klass) + # return exception_type TPath = TypeVar("TPath", bound=PurePath) @@ -470,6 +482,19 @@ def deserialize_union_type(type_blob: bytes) -> type: args = _deserialize(type_blob, from_bytes=True) return functools.reduce(lambda x, y: x | y, args) +def serialize_union(serialized_type: UnionType) -> bytes: + return b'' + +def deserialize_union(type_blob: bytes) -> type: + return Union + +def serialize_typevar(serialized_type: TypeVar) -> bytes: + return f'{serialized_type.__name__}'.encode() + +def deserialize_typevar(type_blob: bytes) -> type: + name = type_blob.decode() + return TypeVar(name=name) # type: ignore + recursive_serde_register( UnionType, @@ -481,8 +506,8 @@ def deserialize_union_type(type_blob: bytes) -> type: recursive_serde_register_type(_SpecialForm, canonical_name="_SpecialForm", version=1) recursive_serde_register_type(_GenericAlias, canonical_name="_GenericAlias", version=1) -recursive_serde_register_type(Union, canonical_name="Union", version=1) -recursive_serde_register_type(TypeVar, canonical_name="TypeVar", version=1) +recursive_serde_register(Union, canonical_name="Union", serialize=serialize_union, deserialize=deserialize_union, version=1) +recursive_serde_register(TypeVar, canonical_name="TypeVar", serialize=serialize_typevar, deserialize=deserialize_typevar, version=1) recursive_serde_register_type( _UnionGenericAlias, @@ -507,3 +532,7 @@ def deserialize_union_type(type_blob: bytes) -> type: recursive_serde_register_type(EnumMeta, canonical_name="EnumMeta", version=1) recursive_serde_register_type(ABCMeta, canonical_name="ABCMeta", version=1) + +recursive_serde_register_type(inspect._empty, canonical_name="inspect_empty", version=1) + + diff --git a/packages/syft/src/syft/service/action/action_object.py b/packages/syft/src/syft/service/action/action_object.py index ca277149620..3ef0c9fc414 100644 --- a/packages/syft/src/syft/service/action/action_object.py +++ b/packages/syft/src/syft/service/action/action_object.py @@ -235,6 +235,7 @@ def repr_uid(_id: LineageID) -> str: ) +@serializable(canonical_name="ActionObjectPointer", version=1) class ActionObjectPointer: pass diff --git a/packages/syft/src/syft/service/network/routes.py b/packages/syft/src/syft/service/network/routes.py index e64c63ac77a..372ceaa915c 100644 --- a/packages/syft/src/syft/service/network/routes.py +++ b/packages/syft/src/syft/service/network/routes.py @@ -31,6 +31,7 @@ from .server_peer import ServerPeer +@serializable(canonical_name="ServerRoute", version=1) class ServerRoute: def client_with_context( self, context: ServerServiceContext diff --git a/packages/syft/src/syft/service/notifier/notifier.py b/packages/syft/src/syft/service/notifier/notifier.py index 01a601d0da9..26dafe34e44 100644 --- a/packages/syft/src/syft/service/notifier/notifier.py +++ b/packages/syft/src/syft/service/notifier/notifier.py @@ -31,6 +31,7 @@ def send( TBaseNotifier = TypeVar("TBaseNotifier", bound=BaseNotifier) +@serializable(canonical_name="EmailNotifier", version=1) class EmailNotifier(BaseNotifier): smtp_client: SMTPClient sender = "" diff --git a/packages/syft/src/syft/service/project/project.py b/packages/syft/src/syft/service/project/project.py index e3a3d292951..d81f9e8ea07 100644 --- a/packages/syft/src/syft/service/project/project.py +++ b/packages/syft/src/syft/service/project/project.py @@ -65,6 +65,7 @@ def metadata_to_server_identity() -> list[Callable]: return [rename("id", "server_id"), rename("name", "server_name")] +@serializable() class ProjectEvent(SyftObject): __canonical_name__ = "ProjectEvent" __version__ = SYFT_OBJECT_VERSION_2 diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 4e4218cb07b..64625b45bbb 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -305,6 +305,7 @@ def get_migration_for_version( ] +@serializable() class SyftObject(SyftBaseObject, SyftMigrationRegistry): __canonical_name__ = "SyftObject" __version__ = SYFT_OBJECT_VERSION_2 diff --git a/packages/syft/src/syft/types/syft_object_registry.py b/packages/syft/src/syft/types/syft_object_registry.py index 7226e6a246f..d3dc9219a3b 100644 --- a/packages/syft/src/syft/types/syft_object_registry.py +++ b/packages/syft/src/syft/types/syft_object_registry.py @@ -38,6 +38,14 @@ def get_versions(cls, canonical_name: str) -> list[int]: ) return list(available_versions.keys()) + + @classmethod + def get_identifier_for_type(cls, obj: Any) -> tuple[str, int]: + """ + This is to create the string in nonrecursiveBlob + """ + return cls.__type_to_canonical_name__[obj] + @classmethod def get_canonical_name_version(cls, obj: Any) -> tuple[str, int]: """ @@ -53,7 +61,7 @@ def get_canonical_name_version(cls, obj: Any) -> tuple[str, int]: get_canonical_name_version([1,2,3]) -> "list" get_canonical_name_version(list) -> "type" get_canonical_name_version(MyEnum.A) -> "MyEnum" - get_canonical_name_version(MyEnum) -> "EnumMeta" + get_canonical_name_version(MyEnum) -> "type" Args: obj: The object or type for which to get the canonical name. @@ -62,8 +70,7 @@ def get_canonical_name_version(cls, obj: Any) -> tuple[str, int]: The canonical name and version of the object or type. """ - # NOTE the metaclass of the object is not needed during serde - # so we can safely ignore it + # for types we return "type" if isinstance(obj, type): return cls.__type_to_canonical_name__[type] From 911b4eab57e2ce476bc58bf2afc2b57a4e9bb567 Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Wed, 17 Jul 2024 10:58:30 +0200 Subject: [PATCH 081/117] add serialization to a few classes --- .../src/syft/serde/recursive_primitives.py | 44 ++++++++++++------- .../service/notification/email_templates.py | 4 ++ packages/syft/src/syft/types/blob_storage.py | 2 + 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/packages/syft/src/syft/serde/recursive_primitives.py b/packages/syft/src/syft/serde/recursive_primitives.py index 8808979c45c..e1036eb4f94 100644 --- a/packages/syft/src/syft/serde/recursive_primitives.py +++ b/packages/syft/src/syft/serde/recursive_primitives.py @@ -15,6 +15,7 @@ import tempfile from types import MappingProxyType from types import UnionType +import typing from typing import Any from typing import GenericAlias from typing import Optional @@ -25,13 +26,10 @@ from typing import _SpecialGenericAlias from typing import _UnionGenericAlias from typing import cast -import typing import weakref -from result import Result -from syft.types.syft_object_registry import SyftObjectRegistry - # relative +from ..types.syft_object_registry import SyftObjectRegistry from .capnp import get_capnp_schema from .recursive import chunk_bytes from .recursive import combine_bytes @@ -176,8 +174,10 @@ def deserialize_enum(enum_type: type, enum_buf: bytes) -> Enum: def serialize_type(_type_to_serialize: type) -> bytes: # relative - type_to_serialize = typing.get_origin(_type_to_serialize) or _type_to_serialize - canonical_name, version = SyftObjectRegistry.get_identifier_for_type(type_to_serialize) + type_to_serialize = typing.get_origin(_type_to_serialize) or _type_to_serialize + canonical_name, version = SyftObjectRegistry.get_identifier_for_type( + type_to_serialize + ) return f"{canonical_name}:{version}".encode() # from ..util.util import full_name_with_qualname @@ -482,18 +482,22 @@ def deserialize_union_type(type_blob: bytes) -> type: args = _deserialize(type_blob, from_bytes=True) return functools.reduce(lambda x, y: x | y, args) + def serialize_union(serialized_type: UnionType) -> bytes: - return b'' + return b"" + + +def deserialize_union(type_blob: bytes) -> type: # type: ignore + return Union # type: ignore -def deserialize_union(type_blob: bytes) -> type: - return Union def serialize_typevar(serialized_type: TypeVar) -> bytes: - return f'{serialized_type.__name__}'.encode() + return f"{serialized_type.__name__}".encode() + def deserialize_typevar(type_blob: bytes) -> type: name = type_blob.decode() - return TypeVar(name=name) # type: ignore + return TypeVar(name=name) # type: ignore recursive_serde_register( @@ -506,8 +510,20 @@ def deserialize_typevar(type_blob: bytes) -> type: recursive_serde_register_type(_SpecialForm, canonical_name="_SpecialForm", version=1) recursive_serde_register_type(_GenericAlias, canonical_name="_GenericAlias", version=1) -recursive_serde_register(Union, canonical_name="Union", serialize=serialize_union, deserialize=deserialize_union, version=1) -recursive_serde_register(TypeVar, canonical_name="TypeVar", serialize=serialize_typevar, deserialize=deserialize_typevar, version=1) +recursive_serde_register( + Union, + canonical_name="Union", + serialize=serialize_union, + deserialize=deserialize_union, + version=1, +) +recursive_serde_register( + TypeVar, + canonical_name="TypeVar", + serialize=serialize_typevar, + deserialize=deserialize_typevar, + version=1, +) recursive_serde_register_type( _UnionGenericAlias, @@ -534,5 +550,3 @@ def deserialize_typevar(type_blob: bytes) -> type: recursive_serde_register_type(ABCMeta, canonical_name="ABCMeta", version=1) recursive_serde_register_type(inspect._empty, canonical_name="inspect_empty", version=1) - - diff --git a/packages/syft/src/syft/service/notification/email_templates.py b/packages/syft/src/syft/service/notification/email_templates.py index 1a6965365dc..f8baceee38a 100644 --- a/packages/syft/src/syft/service/notification/email_templates.py +++ b/packages/syft/src/syft/service/notification/email_templates.py @@ -3,6 +3,7 @@ from typing import cast # relative +from ...serde.serializable import serializable from ...store.linked_obj import LinkedObject from ..context import AuthedServiceContext @@ -21,6 +22,7 @@ def email_body(notification: "Notification", context: AuthedServiceContext) -> s return "" +@serializable(canonical_name="OnboardEmailTemplate", version=1) class OnBoardEmailTemplate(EmailTemplate): @staticmethod def email_title(notification: "Notification", context: AuthedServiceContext) -> str: @@ -107,6 +109,7 @@ def email_body(notification: "Notification", context: AuthedServiceContext) -> s return f"""{head} {body}""" +@serializable(canonical_name="RequestEmailTemplate", version=1) class RequestEmailTemplate(EmailTemplate): @staticmethod def email_title(notification: "Notification", context: AuthedServiceContext) -> str: @@ -254,6 +257,7 @@ def email_body(notification: "Notification", context: AuthedServiceContext) -> s return f"""{head} {body}""" +@serializable(canonical_name="RequestUpdateEmailTemplate", version=1) class RequestUpdateEmailTemplate(EmailTemplate): @staticmethod def email_title(notification: "Notification", context: AuthedServiceContext) -> str: diff --git a/packages/syft/src/syft/types/blob_storage.py b/packages/syft/src/syft/types/blob_storage.py index 364a3428b0b..247cf94b365 100644 --- a/packages/syft/src/syft/types/blob_storage.py +++ b/packages/syft/src/syft/types/blob_storage.py @@ -187,10 +187,12 @@ def _coll_repr_(self) -> dict[str, str]: return {"file_name": self.file_name} +@serializable(canonical_name="BlobFileType", version=1) class BlobFileType(type): pass +@serializable(canonical_name="BlobFileObjectPointer", version=1) class BlobFileObjectPointer(ActionObjectPointer): pass From 9cedc5122346761fe557c6a61286d7541a498b9b Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Wed, 17 Jul 2024 11:05:08 +0200 Subject: [PATCH 082/117] lint lint lint --- packages/syft/src/syft/client/api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/syft/src/syft/client/api.py b/packages/syft/src/syft/client/api.py index 55c38a3d207..6f7253076c4 100644 --- a/packages/syft/src/syft/client/api.py +++ b/packages/syft/src/syft/client/api.py @@ -1401,7 +1401,6 @@ def validate_callable_args_and_kwargs( pass else: _type_str = getattr(t, "__name__", str(t)) - raise msg = f"Arg is `{arg}`. \nIt must be of type `{_type_str}`, not `{type(arg).__name__}`" if msg: From 29f5a17661aa1729680a93a3ba21800c867340b1 Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Wed, 17 Jul 2024 11:10:08 +0200 Subject: [PATCH 083/117] lint lint lint --- packages/syft/src/syft/types/syft_object_registry.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/syft/src/syft/types/syft_object_registry.py b/packages/syft/src/syft/types/syft_object_registry.py index d3dc9219a3b..68952b5874b 100644 --- a/packages/syft/src/syft/types/syft_object_registry.py +++ b/packages/syft/src/syft/types/syft_object_registry.py @@ -38,7 +38,6 @@ def get_versions(cls, canonical_name: str) -> list[int]: ) return list(available_versions.keys()) - @classmethod def get_identifier_for_type(cls, obj: Any) -> tuple[str, int]: """ From 5ea3cbd6230573e21ef35ca14ff76f41334de206 Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Wed, 17 Jul 2024 11:36:34 +0200 Subject: [PATCH 084/117] fix numpy test --- packages/syft/src/syft/serde/array.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/syft/src/syft/serde/array.py b/packages/syft/src/syft/serde/array.py index fa1ed27e74b..3f19e575b97 100644 --- a/packages/syft/src/syft/serde/array.py +++ b/packages/syft/src/syft/serde/array.py @@ -162,6 +162,14 @@ version=SYFT_OBJECT_VERSION_1, ) +recursive_serde_register( + np.number, + serialize=lambda x: x.tobytes(), + deserialize=lambda buffer: frombuffer(buffer, dtype=np.number)[0], + canonical_name="numpy_number", + version=SYFT_OBJECT_VERSION_1, +) + # TODO: There is an incorrect mapping in looping,which makes it not work. # numpy_scalar_types = [ # np.bool_, From aff9d2bab00a47fe8acfec9c55df3ef5e024028c Mon Sep 17 00:00:00 2001 From: teo Date: Wed, 17 Jul 2024 13:43:03 +0300 Subject: [PATCH 085/117] reset protocol version --- .../src/syft/protocol/protocol_version.json | 1082 +++++++---------- .../syft/src/syft/server/worker_settings.py | 4 +- .../src/syft/service/action/action_object.py | 84 +- .../syft/src/syft/service/action/numpy.py | 72 +- .../syft/src/syft/service/action/pandas.py | 51 +- .../syft/src/syft/service/code/user_code.py | 35 - .../syft/service/code_history/code_history.py | 1 + .../syft/src/syft/service/dataset/dataset.py | 92 +- .../syft/src/syft/service/job/job_stash.py | 43 - packages/syft/src/syft/service/log/log.py | 33 - .../syft/service/metadata/server_metadata.py | 31 +- .../migration/object_migration_state.py | 3 +- .../src/syft/service/network/server_peer.py | 21 +- .../src/syft/service/output/output_service.py | 45 - .../syft/src/syft/service/request/request.py | 40 - .../src/syft/service/settings/settings.py | 41 +- .../syft/src/syft/service/sync/diff_state.py | 2 +- .../syft/src/syft/service/sync/sync_state.py | 18 - .../src/syft/store/blob_storage/__init__.py | 18 - .../src/syft/store/blob_storage/seaweedfs.py | 2 +- .../src/syft/store/mongo_document_store.py | 4 +- packages/syft/src/syft/types/blob_storage.py | 30 +- packages/syft/src/syft/types/syft_object.py | 2 +- 23 files changed, 497 insertions(+), 1257 deletions(-) diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index 6602155d200..4b64e99064c 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -1,1193 +1,1053 @@ { "dev": { "object_versions": { + "BaseDateTime": { + "1": { + "version": 1, + "hash": "614db484b1950be729902b1861bd3a7b33899176507c61cef11dc0d44611cfd3", + "action": "add" + } + }, "PartialSyftObject": { - "2": { - "version": 2, - "hash": "a32dc097345cffb073caa322281fd8de5f89f0072e9244d093a8bf32ce260642", + "1": { + "version": 1, + "hash": "19a995fcc2833f4fab24584fd99b71a80c2ef1f13c06f83af79e4482846b1656", "action": "add" } }, "ServerMetadata": { - "4": { - "version": 4, - "hash": "e5e0c2d926bf1fea0696126c9cd2ea5308c198f9412de1732a509082cb738e35", - "action": "add" - }, - "5": { - "version": 5, - "hash": "13bfe668b20779b2ab04227dc6b92d545b9ea83baaf0002cad5bcc450f34d246", + "1": { + "version": 1, + "hash": "1691c7667eca86b20c4189e90ce4e643dd41fd3682cdb69c6308878f2a6f135c", "action": "add" } }, "StoreConfig": { - "2": { - "version": 2, - "hash": "af833ac27e16cd3dd93061e4870847df37e480893d867966a0ae8dcca57b9abb", + "1": { + "version": 1, + "hash": "a9997fce6a8a0ed2884c58b8eb9382f8554bdd18fff61f8bf0451945bcff12c7", "action": "add" } }, "MongoDict": { - "2": { - "version": 2, - "hash": "2ab3c12b81326108badd66307d4c4fefb1d60e76d5be2c67e70bb607b4992e93", + "1": { + "version": 1, + "hash": "57e36f57eed75e62b29e2bac1295035a9bf2c0e3c56719dac24cb6cc685be00b", "action": "add" } }, "MongoStoreConfig": { - "2": { - "version": 2, - "hash": "89f75ccf2d640d2dc47aa68bdbd766e4b83433a98653ade174724a631f47fd4d", + "1": { + "version": 1, + "hash": "53342b27d34165b7e2699f8e7ad70d13d125875e6a75e8fa18f5796428f41036", "action": "add" } }, "LinkedObject": { - "2": { - "version": 2, - "hash": "d9c00f99c5385cbcdd11173dfd30b532ddcbc4e8c37f6121a01061cf71b91b5e", + "1": { + "version": 1, + "hash": "d80f5ac7f51a9383be1a3cb334d56ae50e49733ed3199f3b6b5d6febd9de410b", "action": "add" } }, "BaseConfig": { - "2": { - "version": 2, - "hash": "09bb3e3ba91f6c2604d4a057a7be48afa8fb4720b683ac4019569323900acdc9", + "1": { + "version": 1, + "hash": "10bd7566041d0f0a3aa295367785fdcc2c5bbf0ded984ac9230754f37496a6a7", "action": "add" } }, "ServiceConfig": { - "2": { - "version": 2, - "hash": "df15d8e09dedcbee2e07292ad71a8fd42cf0d52ac4ffdaaa27ef87b7f2629a8a", + "1": { + "version": 1, + "hash": "28af8a296f5ff63de50438277eaa1f4380682e6aca9f2ca28320d7a444825e88", "action": "add" } }, "LibConfig": { - "2": { - "version": 2, - "hash": "6453cb794e0a89c8a0f4529d2f81e4f04b141a0d313760c38f41f2dd42258941", + "1": { + "version": 1, + "hash": "ee8f0e3f6aae81948d72e30226645e8eb5d312a6770411a1edca748168c467c0", "action": "add" } }, "APIEndpoint": { - "2": { - "version": 2, - "hash": "695974643dbc32a1a653218a9b2fedfdd341bdd687584cf80035bb51e7ed9be1", + "1": { + "version": 1, + "hash": "cfa6f314481a5bf3c448c33bf2312a9c33cbcf03cdc96864ad9a108f62b09346", "action": "add" } }, "LibEndpoint": { - "2": { - "version": 2, - "hash": "acc9924f09471081899ed21d2d4da3e4ed307edd5e703ee0041a41827e26ccde", + "1": { + "version": 1, + "hash": "a585c83a33a019d363ae5a0c6d4197193654307c19a4829dfbf8a8cfd2c1842a", "action": "add" } }, "SignedSyftAPICall": { - "2": { - "version": 2, - "hash": "4dfc0709ab211d55250d2be8f6ec60be1f9517d98a73c98d2a360d92e49822ff", + "1": { + "version": 1, + "hash": "2f959455f7130f4e59360b8aa58f19785b76eaa0f8a5a9188a6cbf32b31311ca", "action": "add" } }, "SyftAPICall": { - "2": { - "version": 2, - "hash": "b457a48a7f0ddc67525d91faf660667adcb80f7a478999a35396a2e4bc22c562", + "1": { + "version": 1, + "hash": "59e89e7b9ea30deaed64d1ffd9bc0769b999d3082b305428432c1f5be36c6343", "action": "add" } }, "SyftAPIData": { - "2": { - "version": 2, - "hash": "46b073b98cfb3a4a0f5dc6c55885278f263bc208d3704821849568e246101aa8", + "1": { + "version": 1, + "hash": "820b279c581cafd9bb5009702d4e3db22ec3a3156676426304b9038dad260a24", "action": "add" } }, "SyftAPI": { - "2": { - "version": 2, - "hash": "03ec5999de8f43ce83da079d836aec737d1142ec11265c0f3ca89da3139fad36", - "action": "add" - }, - "3": { - "version": 3, - "hash": "b82f04c734e7cc3a14bf5cf88173e2ed41a09ddd332b0b4a79747c333ca8db1e", + "1": { + "version": 1, + "hash": "cc13ab058ee36748c14b0d4bd9b9e894c7566fff09cfa4170b3eece520169f15", "action": "add" } }, "User": { - "3": { - "version": 3, - "hash": "cdd25c47e32ac79e177bd26b8d3231847f4722247543954fc967686159ac17a2", + "1": { + "version": 1, + "hash": "2df4b68182c558dba5485a8a6867acf2a5c341b249ad67373a504098aa8c4343", "action": "add" } }, "UserUpdate": { - "3": { - "version": 3, - "hash": "01c3a470b326229bc892bea96b425c059edfde3bca57b0af83491a4fecbd0402", + "1": { + "version": 1, + "hash": "1bf6707c69b809c804fb939c7c37d787c2f6889508a4bec37d24221af2eb777a", "action": "add" } }, "UserCreate": { - "3": { - "version": 3, - "hash": "cb2d9872cba80c960c748b232547556fa69901c108d84ab46f177cb47f0dd3fc", + "1": { + "version": 1, + "hash": "49d6087e2309ba59987f3126e286e74b3a66492a08ad82fa507ea17d52ce78e3", "action": "add" } }, "UserSearch": { - "2": { - "version": 2, - "hash": "c2676b012142f68ae64a11f3807e35430a046f51b7cac6682aa453c0345a9a32", + "1": { + "version": 1, + "hash": "9ac946338cca68d00d1696a57943442f062628ec3daf53077d0bdd3f72cd9fa0", "action": "add" } }, "UserView": { - "3": { - "version": 3, - "hash": "a07bebf2362391b915fb2554e61c98e35cb4f945ba8c3c3299dd059dc6f0e137", + "1": { + "version": 1, + "hash": "0b52d758e31d5889c9cd88afb467aae4a74e34a5276924e07012243c34d300fe", "action": "add" } }, "UserViewPage": { - "2": { - "version": 2, - "hash": "9ccdbff62daac91fc9951a62c7d54d35418035a0ad4fd979bd1f7262c2cdabc9", + "1": { + "version": 1, + "hash": "1cd6528d02ec180f080d5c35f0da760d8a59af9da7baaa9c17c1c7cedcc858fa", "action": "add" } }, "UserPrivateKey": { - "2": { - "version": 2, - "hash": "3e7a37177e86a5a0c54a6e6cc87eb2c3a266e5e65cb8dd33f6b0c3fccc7b584d", + "1": { + "version": 1, + "hash": "4817d8147aba94373f320dcd90e65f097cf6e5a2ef353aa8520e23128d522b5d", "action": "add" } }, "DateTime": { - "2": { - "version": 2, - "hash": "298922f94fc06eb8ce080cd19bc124929943729ea83bf15b463b37fe959141cb", + "1": { + "version": 1, + "hash": "394abb554114ead4d63c36e3fe83ac018dead4b21a8465174009577c46d54c58", "action": "add" } }, "ReplyNotification": { - "2": { - "version": 2, - "hash": "0420ed6a014e3a16bcf063208cfdc393a02f4ec0ddbd0635dc15308b5deafc92", + "1": { + "version": 1, + "hash": "84102dfc59d711b03c2f3d3a6ecaca000b6835f1bbdd9af801057f7aacb5f1d0", "action": "add" } }, "Notification": { - "2": { - "version": 2, - "hash": "38defc169bf225474e0b8037aedf66dee78f5e0aef3af75ab24d1e8f5d55f23a", + "1": { + "version": 1, + "hash": "af4cb232bff390c431e399975f048b34da7e940ace8b23b940a3b398c91c5326", "action": "add" } }, "CreateNotification": { - "2": { - "version": 2, - "hash": "079523cd89527b90003bef1ab4f985e374550bfb1f7921f8906702a9f6938205", + "1": { + "version": 1, + "hash": "7e426c946b7d5db6f9427960ec16042f3018091d835ca5966f3568c324a2ab53", "action": "add" } }, "NotificationPreferences": { "1": { "version": 1, - "hash": "499e02b45defab561decaef6bdcf0ec1a6bbda834bd7d25a465982159b8c2909", + "hash": "a42f06b367e7c6cbabcbf3cfcc84d1ca0873e457d972ebd060e87c9d6185f62b", "action": "add" } }, "NotifierSettings": { "1": { "version": 1, - "hash": "8edcbf73f2098f6a20d393f09c5805493da5346e8f7070f841c36ac7b777edb1", + "hash": "65c8ab814d35fac32f68d3000756692592cc59940f30e3af3dcdfa2328755b9d", "action": "add" } }, "SyftImageRegistry": { - "2": { - "version": 2, - "hash": "2495c6836c6f0ba991637766657ccd04e992d367102d336a04c608d95cbf9895", + "1": { + "version": 1, + "hash": "67e18903e41cba1afe136adf29d404b63ec04fea6e928abb2533ec4fa52b246b", "action": "add" } }, "SyftWorkerImage": { - "2": { - "version": 2, - "hash": "dcd40e107f930c0efcd525694e89eedea1546fdc31d44373fce7e9d4ac2bbc2e", + "1": { + "version": 1, + "hash": "44da7badfbe573d5403d3ab78c077f17dbefc560b81fdf927b671815be047441", "action": "add" } }, "SyftWorker": { - "2": { - "version": 2, - "hash": "6dbf5487cfb6fceea8a57d1cbb1320107f4a4116fb0269f151082e15f9d150b5", - "action": "add" - }, - "3": { - "version": 3, - "hash": "905b97e80b2a9d509a5d37ae248ed6ddc1e028e851330c836ee5ce26444fac88", + "1": { + "version": 1, + "hash": "9d897f6039eabe48dfa8e8d5c5cdcb283b0375b4c64571b457777eaaf3fb1920", "action": "add" } }, "WorkerPool": { - "2": { - "version": 2, - "hash": "d2205590c821af416ba8f13f3e2b834fa3bb561f08dca060eb2bd86f7eca89e2", + "1": { + "version": 1, + "hash": "16efc5dd2596ae744fd611c8f46af9eaec1bd5729eb20e85e9fd2f31df402564", "action": "add" } }, "MarkdownDescription": { - "2": { - "version": 2, - "hash": "d8f5ec42e69d55eabe044a417bfbf6d57b867eadcc975377e1fc8a499a9f90f3", + "1": { + "version": 1, + "hash": "31a73f8824cad1636a55d14b6a1074cdb071d0d4e16e86baaa3d4f63a7e80134", "action": "add" } }, "HTMLObject": { "1": { "version": 1, - "hash": "4127056b8f9f904f2dcb225de2952ad7b57c4b2874ac76800afa234c826d6702", + "hash": "97f2e93f5ceaa88015047186f66a17ff13df2a6b7925b41331f9e19d5a515a9f", "action": "add" } }, "ServerSettingsUpdate": { - "4": { - "version": 4, - "hash": "09b96c7c25e9261144ffe3409ac47e943abe5cf433759f68c03a321d21d69c1b", - "action": "add" - }, - "5": { - "version": 5, - "hash": "81a9e2930fe91f7744a5a495f73eb9f7c04145ebe1848257ea52b537fed4b3d7", + "1": { + "version": 1, + "hash": "1e4260ad879ae80728c3ffae2cd1d48759abd51f9d0960d4b25855cdbb4c506b", "action": "add" } }, "ServerSettings": { - "3": { - "version": 3, - "hash": "6b2240b92099684b0e431d27c0be2a22daad234b890c95eb607f0cc9e73c9f0d", - "action": "add" - }, - "5": { - "version": 5, - "hash": "522690efe97c50dff81936640e95207861406e480d7e1d87587e558dbd7a506c", - "action": "add" - }, - "6": { - "version": 6, - "hash": "be6d6402a5ccf0b93847ebcde75f4ea357f3b45003a1a7c01426e9e34ea3b5e1", + "1": { + "version": 1, + "hash": "5a1e7470cbeaaae5b80ac9beecb743734f7e4e42d429a09ea8defa569a5ddff1", "action": "add" } }, "HTTPConnection": { - "3": { - "version": 3, - "hash": "2e567111a679e9f01b84eafc96d5e14e52b12fea991957e547f2edcbc0ede34c", + "1": { + "version": 1, + "hash": "bf10f81646c71069c76292b1237b4a3de1e507264392c5c591d067636ce6fb46", "action": "add" } }, "PythonConnection": { - "3": { - "version": 3, - "hash": "854a2ffc94e21fdcc4878ddc16f60bef8e7bf8ddc72dec63c9cb182ad7e4bbb7", + "1": { + "version": 1, + "hash": "28010778b5e3463ff6960a0e2224818de00bc7b5e6f892192e02e399ccbe18b5", "action": "add" } }, "ActionDataEmpty": { - "2": { - "version": 2, - "hash": "76445c74c9636f33524ed1ec60796caabfda2dcf85a950387ee9526b2659efe4", + "1": { + "version": 1, + "hash": "e0e4a5cf18d05b6b747addc048515c6f2a5f35f0766ebaee96d898cb971e1c5b", "action": "add" } }, "ObjectNotReady": { - "2": { - "version": 2, - "hash": "09e8e20e1f96189b96ddda19d1cffafed98dfa8fd80b286ea91b814c7aa0aa5b", + "1": { + "version": 1, + "hash": "8cf471e205cd0893d6aae5f0227d14db7df1c9698da08a3ab991f59132d17fe9", "action": "add" } }, "ActionDataLink": { - "2": { - "version": 2, - "hash": "45f82b2a0124f7adadc515c40f71551a37ea4b04fdc2caa220e39988e8d83675", + "1": { + "version": 1, + "hash": "3469478343439e411b761c270eec63eb3d533e459ad72d0965158c3a6cdf3b9a", "action": "add" } }, "Action": { - "3": { - "version": 3, - "hash": "9baeef92e1199d9686ad27bcaf55ad0621233560dd70377fc964ccc4ab21bcb4", + "1": { + "version": 1, + "hash": "021826d7c6f69bd0283d025d40661f3ffbeba8810ca94de01344f6afbdae62cd", "action": "add" } }, "ActionObject": { - "3": { - "version": 3, - "hash": "e13cca90723c27b17529295e1050ba4736aa42e548511f922ab4d10a78e9c558", - "action": "add" - }, - "4": { - "version": 4, - "hash": "da069dc83b2c583d5624f86541ed95d9c8a85774a1fb64e37fdd87e490e06300", + "1": { + "version": 1, + "hash": "0a5f4bc343cb114a251f06686ecdbb59d74bfb3d29a098b176699deb35a1e683", "action": "add" } }, "AnyActionObject": { - "3": { - "version": 3, - "hash": "8b6a450bbc40f381cb3404ea6ff86024651debcdebe785db0819ab1ffd6535b0", - "action": "add" - }, - "4": { - "version": 4, - "hash": "a944e6db84aa6cda0d4cb278cc836df1ce64882896a9d3da798148e1e9bb5c42", - "action": "add" - } - }, - "BlobFile": { - "4": { - "version": 4, - "hash": "6d59e20f3a9bf16cf199deddb0d246b100d5ab616a4811e96b682df58546b869", - "action": "add" - } - }, - "BlobFileOBject": { - "2": { - "version": 2, - "hash": "af3c2e435c20258b94377716fb6babb0bfb8ea684c88a93aff968f95fb1497f6", - "action": "add" - }, - "3": { - "version": 3, - "hash": "417f4eb6f978a273c3b7cad93fc80caab122bebdf21923520dbfcadcc5160baf", + "1": { + "version": 1, + "hash": "b3c44c7788c59c03fa1baeec656c2ca6e633f4cbd4b23ff7ece6ee94c38449f0", "action": "add" } }, - "SecureFilePathLocation": { - "2": { - "version": 2, - "hash": "1680c4c2f81f3e93fe126c5888288577b32e76546f16be3ffe5c3fdcce1aac3f", + "CustomEndpointActionObject": { + "1": { + "version": 1, + "hash": "c7addbaf2777707f3e91e5c1e092343476cd22efc4ec8617f39ccf76e61a5a14", "action": "add" } }, - "SeaweedSecureFilePathLocation": { - "3": { - "version": 3, - "hash": "0d34e64267f3c870a5ce5307802a23fcfbb796cf48b979c2d1d4c0ef772f8131", + "DataSubject": { + "1": { + "version": 1, + "hash": "582cdf9e82b5d6915b7f09f7c0d5f08328b11a2ce9b0198e5083f1672c2e2bf5", "action": "add" } }, - "AzureSecureFilePathLocation": { - "2": { - "version": 2, - "hash": "a97c52808be5afceaea7f9b3ac6c00d4256d7f9a8c7f2200acf8f82451018319", + "DataSubjectCreate": { + "1": { + "version": 1, + "hash": "5a8423c2690d55f425bfeecc87cd4a797a75d88ebb5fbda754d4f269b62d2ceb", "action": "add" } }, - "BlobStorageEntry": { - "3": { - "version": 3, - "hash": "6ff74feabd8a58ae0e1881c03f3ffbb70c95944bef507f8c5b1493bfb6594ea5", + "DataSubjectMemberRelationship": { + "1": { + "version": 1, + "hash": "0810483ea76ea10c8f286c6035dc0b2085291f345183be50c179f3a05a577110", "action": "add" } }, - "BlobStorageMetadata": { - "3": { - "version": 3, - "hash": "738daa84b6824841254ba7a651a433dd0ff1c44961ed142920786cbc60329ffa", + "Contributor": { + "1": { + "version": 1, + "hash": "30c32bd44098f00e0b15496be441763b6e50af8b12d3d2bef33aca6287193876", "action": "add" } }, - "CreateBlobStorageEntry": { - "2": { - "version": 2, - "hash": "9c0069727e5b845a004717dc28abcf1486f5581cba4ec0526fdb3553d40ecd7a", + "Asset": { + "1": { + "version": 1, + "hash": "000abc78719611c106295cf12b1690b7e5411dc1bb9db9d4afd22956da90d1f4", "action": "add" } }, - "BlobRetrieval": { - "3": { - "version": 3, - "hash": "3b7be2fa9b5821c03808ae2dd244feb04817f5b1f1f821cd861f111fdc8692f9", + "CreateAsset": { + "1": { + "version": 1, + "hash": "357d52576cb12b24fb3980342bb49a562b065c0e4419e87d34176340628c7309", "action": "add" } }, - "SyftObjectRetrieval": { - "4": { - "version": 4, - "hash": "4d6a3175fd8753919ceed4d7b19a6a25baa47013da8f9d2e4eae3afd2c72f246", + "Dataset": { + "1": { + "version": 1, + "hash": "3be049e4f3d423699ba5d7c2d1f60b2b11c0c6691b505e1c6100a743a7398665", "action": "add" } }, - "BlobRetrievalByURL": { - "4": { - "version": 4, - "hash": "6a77259a8c83f85e83e89cee4c7ea7b1d57ccac4f70ecfb86b6c5db21c62ee79", - "action": "add" - }, - "5": { - "version": 5, - "hash": "e9c5e16f14e5bd45209f44ebf6c758a8c4a315b2d335a33bc529606506037890", + "DatasetPageView": { + "1": { + "version": 1, + "hash": "aa0dd69637281b80d5523b4409a2c7e89db114c9fe79c858063c6dadff8977d1", "action": "add" } }, - "BlobDeposit": { - "2": { - "version": 2, - "hash": "cf27595f05e3f60c825ef3b547ab72f04cc983688b12ef9233785b05b5a24551", + "CreateDataset": { + "1": { + "version": 1, + "hash": "3f9cdbf797ca0ed7b1c95ffb50cb696b1127ac8b80438dbb517561c5992a6ba9", "action": "add" } }, - "WorkerSettings": { - "3": { - "version": 3, - "hash": "982d68aca23fdecd9d8986f6ac95a2812ddac784c5a30655367df5356c9778f1", + "SyftLog": { + "1": { + "version": 1, + "hash": "1bcd71e5bf3f0db3bba0996f33b6b2bde3489b9c71f11e6b30c3495c76a8f53f", "action": "add" } }, - "HTTPServerRoute": { - "3": { - "version": 3, - "hash": "530fec14b476cf67afeef8667fd5397a2bca51744869e41828f4328bed647f72", + "JobItem": { + "1": { + "version": 1, + "hash": "0b32277b7d3b9bdc14a2a51cc9005f8254e7f7b6ec059ddcccbcd681a807afb6", "action": "add" } }, - "PythonServerRoute": { - "3": { - "version": 3, - "hash": "f9f52b5764f2a5c3bd2b628f793e2ab9d0e5163f0bf4a469d4b3ee804ee27eeb", + "ExecutionOutput": { + "1": { + "version": 1, + "hash": "e36c71685edf5276a3427cb6749550486d3a177c1dcf73dd337ab2a73c0ce6b5", "action": "add" } }, - "VeilidServerRoute": { + "TwinObject": { "1": { "version": 1, - "hash": "0924cb1d76957bdc7f39ccb54e2944ce07bc83c0bf37ccf5f89d7328c0088eeb", + "hash": "4f31243fb348dbb083579afd6f638d75af010cb53d19bfba59b74afff41ccbbb", "action": "add" } }, - "EnclaveMetadata": { - "3": { - "version": 3, - "hash": "94998d8fad3c2ca1f371a08641873e24504065bfe785548aba72dfaf9687c409", + "PolicyRule": { + "1": { + "version": 1, + "hash": "44d1ca1db97be46f66558aa1a729ff31bf8e113c6a913b11aedf9d6b6ad5b7b5", "action": "add" } }, - "CustomEndpointActionObject": { + "CreatePolicyRule": { "1": { "version": 1, - "hash": "aba8c35a83b81f602ae19393e9bd1813ca1d191d055272499c63543961089b86", + "hash": "342bb723526d445151a0435f57d251f4c1219f8ae7cca3e8e9fce52e2ee1b8b1", "action": "add" } }, - "DataSubject": { - "2": { - "version": 2, - "hash": "24329941dbb93f9382527b9b2e70da58369aefa65ae6934a4f55725487259515", + "CreatePolicyRuleConstant": { + "1": { + "version": 1, + "hash": "78b54832cb0468a87013bc36bc11d4759874ca1b5065a1b711f1e5ef5d94c2df", "action": "add" } }, - "DataSubjectCreate": { - "2": { - "version": 2, - "hash": "1584dc6cbd2df80118d46aa9cf4788c96be420ce3a1d3ff041664fb265626871", + "Matches": { + "1": { + "version": 1, + "hash": "dd6d91ddb2ec5eaf60be2b0899ecfdb9a15f7904aa39d2f4d9bb2d7b793040e6", "action": "add" } }, - "DataSubjectMemberRelationship": { - "2": { - "version": 2, - "hash": "26876c004bb080c06af331965466e66d454ccb6b6a03d12aec0d44032302412b", + "PreFill": { + "1": { + "version": 1, + "hash": "c7aefb11dc4c4569dcd1e6988371047a32a8be1b32ad46d12adba419a19769ad", "action": "add" } }, - "Contributor": { - "2": { - "version": 2, - "hash": "281a88bcfd8840b3f92780d31075bfa369b2ff0e5d4044ebbc269bebca451b47", + "UserOwned": { + "1": { + "version": 1, + "hash": "c8738dc3d8c2a5ef461b85a0467c3dff53dab16b54a4d12b44b1477906aef51d", "action": "add" } }, - "Asset": { - "2": { - "version": 2, - "hash": "84f33e07c0a4a627808ada7ae092b9e11305a2a6a9d4f264f62ed906a834663d", + "MixedInputPolicy": { + "1": { + "version": 1, + "hash": "37bb12d950518d9579c8ec7c4cc22ac731ea82caf8c1370dd0b0a82b46462dde", "action": "add" } }, - "CreateAsset": { - "2": { - "version": 2, - "hash": "0fbe735bdf6acd91f5589369188c02d25d014b7112afbcde8b04d52aca2abb65", + "ExactMatch": { + "1": { + "version": 1, + "hash": "5eb37edbf5e451d942e599247f3eaed923c1fe9d91eefdba02bf06503f6cc08d", "action": "add" } }, - "Dataset": { - "2": { - "version": 2, - "hash": "e9df341cf5128d9ce09fb137e6413745842818675c9dfbbf824e521cb0196dd0", - "action": "add" - }, - "3": { - "version": 3, - "hash": "acc25456a60ccef861de65eea1feef612ef9fa1ed6e986b466450c4adf73906b", + "OutputHistory": { + "1": { + "version": 1, + "hash": "9366db79d131f8c65e5a4ff12c90e2aa0c11e302debe06e46eeb93b26e2aaf61", "action": "add" } }, - "DatasetPageView": { - "2": { - "version": 2, - "hash": "0e336a3afd446aa58fc6ec6950691baa36b76a0649b9da31bbecb4db1b0587cf", + "OutputPolicyExecuteCount": { + "1": { + "version": 1, + "hash": "2a77e5ed5c7b0391147562651ad4061e20b11745c191fbc34cb549da37ba72dd", "action": "add" } }, - "CreateDataset": { - "2": { - "version": 2, - "hash": "3e4983b35c6513a64198cf5346aec23017192045aad562e85deb7e212be78784", - "action": "add" - }, - "3": { - "version": 3, - "hash": "7ecb8d62a8c12e385ff45ed700106bb1463926237fbdde3e84a83f38419d54de", + "OutputPolicyExecuteOnce": { + "1": { + "version": 1, + "hash": "5589c00d127d9eb1f5ccf3a16def8219737784d57bb3bf9be5cb6d83325ef436", "action": "add" } }, - "SyftLog": { - "3": { - "version": 3, - "hash": "c2ee3f4c34dc7af3af533865dc07384403fb757e7959272c9d6d08110623a216", - "action": "add" - }, - "4": { - "version": 4, - "hash": "3b90dcb66359a1d03345291b47dcb8b5c166b1e0344dbe84d9c1f3a8e57f99eb", + "EmptyInputPolicy": { + "1": { + "version": 1, + "hash": "7ef81cfd223be0064600e1503f8b04bafc16385e27730e9319466e68a077c68b", "action": "add" } }, - "JobItem": { - "4": { - "version": 4, - "hash": "3e2eaae1b2c367b5bc52cbc4eb3390b1f5a6a6f8cae69523bbfc8e071c314bf8", - "action": "add" - }, - "6": { - "version": 6, - "hash": "b633f770c9c47a849b75fe6b93c573c94eadab23c689aa812a8671cec9543650", + "UserPolicy": { + "1": { + "version": 1, + "hash": "74373bb71a334f4dcf77623ae10ff5b1c7e5b3006f65f2051ffb1e01f422f982", "action": "add" } }, - "ExecutionOutput": { + "SubmitUserPolicy": { "1": { "version": 1, - "hash": "c6cb71d6ae689e71c31685c29a7ecd44d1c0c5b31fd19991b535cb597db7b44a", - "action": "add" - }, - "2": { - "version": 2, - "hash": "1b045334d8049f3970e655da11f3f62bc8a9f78e562fd75ed517c97fc95bb1c3", + "hash": "ec4e808eb39613bcdbbbf9ffb3267612084a9d99880a2f3bee3ef32d46329c02", "action": "add" } }, - "TwinObject": { - "2": { - "version": 2, - "hash": "c1f81d875b96cec303af7d869e5a70f7b619f0f4849ad6a8987e75cf6e2f4538", + "UserCodeStatusCollection": { + "1": { + "version": 1, + "hash": "735ecf2d4abb1e7d19b2e751d880f32b01ce267ba10e417ef1b440be3d94d8f1", "action": "add" } }, - "PolicyRule": { + "UserCode": { "1": { "version": 1, - "hash": "b92557f8bd715caadb4eba68793f167493d36f29972006c2bd59b0ec8e829ba7", + "hash": "3bcd14413b9c4fbde7c5612c2ed713518340280b5cff89cf2aaaf1c77c4037a8", "action": "add" } }, - "CreatePolicyRule": { + "SubmitUserCode": { "1": { "version": 1, - "hash": "2962b14b70451ea8e13746ebadff62d927f62111d3d5610787ecb3b9cefcc897", + "hash": "d2bb8cfe12f070b4adafded78ce01900c5409bd83f055f94b1e285745ef65a76", "action": "add" } }, - "CreatePolicyRuleConstant": { + "UserCodeExecutionResult": { "1": { "version": 1, - "hash": "3807c5bf87bd1a58ecae8a97083e636f0471d4604121fb1f61182bd7dbbc1c47", + "hash": "1f4cbc62caac4dd193f427306405dc7a099ae744bea5830cf57149ce71c1e589", "action": "add" } }, - "Matches": { + "UserCodeExecutionOutput": { "1": { "version": 1, - "hash": "20dd67c0d60cd0047267dc83a767568d90fc418e84a05186eaba6f6a0279c50b", + "hash": "c1d53300a39dbbb437d7d5a1257bd175a067b1065f4099a0938fac7540035258", "action": "add" } }, - "PreFill": { + "CodeHistory": { "1": { "version": 1, - "hash": "557185e0437884ea9da718b449d0c6b38bc6c107e29d5f36ab6e34b8509a884d", + "hash": "e3ef5346f108257828f364d22b12d9311812c9cf843200afef5dc4d9302f9b21", "action": "add" } }, - "UserOwned": { + "CodeHistoryView": { "1": { "version": 1, - "hash": "50de8777b4027f394d910f5304d3d27c48cc58abdd9882c0e1cddc10b69f85c5", + "hash": "8b8b97d334b51d1ce0a9efab722411ff25caa3f12be319105954497e0a306eb2", "action": "add" } }, - "MixedInputPolicy": { + "CodeHistoriesDict": { "1": { "version": 1, - "hash": "b4d6b42c04a8b64a1ec065e700af67347c44a180cdfdb8f4e9b3bc030cf3bfe4", + "hash": "01d7dcd4b21525a06e4484d8699a4a34a5c84f1f6026ec55e32eb30412742601", "action": "add" } }, - "ExactMatch": { - "2": { - "version": 2, - "hash": "7fcc80c7ec005a0e1484b9d44fe9892ad886fda82044a9a96b0c33fbffc63d4f", + "UsersCodeHistoriesDict": { + "1": { + "version": 1, + "hash": "4ed8b83973258ea19a1f91feb2590ff73b801be86f4296cc3db48f6929ff784c", "action": "add" } }, - "OutputHistory": { - "2": { - "version": 2, - "hash": "e9844cc602cb57168e3062263961ad5d22a1e93a5bb3765ee364637813c9daca", + "BlobFile": { + "1": { + "version": 1, + "hash": "d99239100f1cb0b73c69b2ad7cab01a06909cc3a4976ba2b3b67cf6fe5e2f516", "action": "add" } }, - "OutputPolicyExecuteCount": { - "2": { - "version": 2, - "hash": "82a309e0616864a3505600a88fcfb772c2d5f781e286a285953e495f93a2b3e2", + "BlobFileOBject": { + "1": { + "version": 1, + "hash": "6c40dab2c8d2220d4fff7cc653d76cc026a856db7e2b5713b6341e255adc7ea2", "action": "add" } }, - "OutputPolicyExecuteOnce": { - "2": { - "version": 2, - "hash": "0b0baa12dd349997fb67887005c5c76f559d02d1a5570700af31d17a39016e72", + "SecureFilePathLocation": { + "1": { + "version": 1, + "hash": "ea5978b98d7773d221665b450454c9130c103a5c850669a0acd620607cd614b7", "action": "add" } }, - "EmptyInputPolicy": { - "2": { - "version": 2, - "hash": "f1724dfc2f8f1f33db2a9c9f0a18bed8c763539592e8cbadd586df7af90b66fe", + "SeaweedSecureFilePathLocation": { + "1": { + "version": 1, + "hash": "3fc9bfc8c1b1cf660c9747e8c1fe3eb2220e78d4e3b5d6b5c5f29a07a77ebf3e", "action": "add" } }, - "UserPolicy": { - "2": { - "version": 2, - "hash": "4b2396d083ad1200f66f83610a16c98fcf2fe9cbe918dfe1f2a893d3b700b6eb", + "AzureSecureFilePathLocation": { + "1": { + "version": 1, + "hash": "090a9e962eeb655586ee966c5651d8996363969818a38f9a486fd64d33047e05", "action": "add" } }, - "SubmitUserPolicy": { - "2": { - "version": 2, - "hash": "91594efc92f7d6115c148930f02f90a06728fb8e1ed567c2c03cdae1967b62e3", + "BlobStorageEntry": { + "1": { + "version": 1, + "hash": "afdc6a1d8a24b1ee1ed9d3e79f5bac64b4f0d9d36800f07f10be0b896470345f", "action": "add" } }, - "UserCodeStatusCollection": { + "BlobStorageMetadata": { "1": { "version": 1, - "hash": "96bea86ece8bd4cb2948deba4fbdc1aa95a54b6f5ef03dbf8c805f1b3cc36db1", + "hash": "9d4b61ac4ea1910c2f7c767a50a6a52544a24663548f069e79bd906f11b538e4", "action": "add" } }, - "UserCode": { - "4": { - "version": 4, - "hash": "60ee9415e8692ad6c0fe9e5e65961d3b7e4247fbc765abcd871f612f546155f9", - "action": "add" - }, - "5": { - "version": 5, - "hash": "c3845ff8d7e006525f208dc19f93e0f0757a15b63b3e3664fabfa789dbe5fd2e", + "CreateBlobStorageEntry": { + "1": { + "version": 1, + "hash": "ffc3cbfeade67d074dc5bf7d655a1eb8c83630076028a72b3cc4548f3b413e14", "action": "add" } }, - "SubmitUserCode": { - "4": { - "version": 4, - "hash": "330b62d200c304e12b47e5b288fe7f419dcdb22f0aad2e31aa978a0a5993dbcb", - "action": "add" - }, - "5": { - "version": 5, - "hash": "ca0d501801f3aac1ad53f1e7844520dc7733c64f3fa012abb9fd95940c170d6e", + "SyftObjectMigrationState": { + "1": { + "version": 1, + "hash": "ee83315828551f18904bab18e0cac48896493620561215b04cc448e6ce5834af", "action": "add" } }, - "UserCodeExecutionResult": { - "2": { - "version": 2, - "hash": "72aed37d1b165f36aeeba41e13c9ac570b17b35ced11a53b70d289e95d5d0c5e", + "StoreMetadata": { + "1": { + "version": 1, + "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", "action": "add" } }, - "UserCodeExecutionOutput": { + "MigrationData": { "1": { "version": 1, - "hash": "d180eb86a0baa95c0df100beda459586793af07259e21c1a559bcf961661cffd", + "hash": "cb96b8c8413609e1224341d1b0dd1efb08387c0ff7b0ff65eba36c0b104c9ed1", "action": "add" } }, - "CodeHistory": { - "2": { - "version": 2, - "hash": "7740375395772ee76a693b592f8ca72b954b75478d9b77eb38a2efbd0e3f53cb", - "action": "add" - }, - "3": { - "version": 3, - "hash": "7bede78c55f99d0e0294b0555ab2bace37f78fc5f58f423bba485b88ae190dc3", + "BlobRetrieval": { + "1": { + "version": 1, + "hash": "c422c74b89a9349742acaa848566fe18bfef1a83333458b858c074baed37a859", "action": "add" } }, - "CodeHistoryView": { - "2": { - "version": 2, - "hash": "c289d9a50f718966d7edb647025c1bcfb71b38e11f4d0d2a18d24c6a7b6d9bbf", + "SyftObjectRetrieval": { + "1": { + "version": 1, + "hash": "b2b62447445adc4cd0b77ab59d6fa56624dd316fb50281e570daad07556b6db2", "action": "add" } }, - "CodeHistoriesDict": { - "2": { - "version": 2, - "hash": "25f10dd11e5d360760b253ca76a38a1399cbbb6a209dad884bebff563acf0d58", + "BlobRetrievalByURL": { + "1": { + "version": 1, + "hash": "4db0e3b7a6334d3835356d8393866711e243e360af25a95f3cc4066f032404b5", "action": "add" } }, - "UsersCodeHistoriesDict": { - "2": { - "version": 2, - "hash": "5c5840b39300d5540c8dbeab673dc925e8187d8589f36a84063af822437ebe88", + "BlobDeposit": { + "1": { + "version": 1, + "hash": "6eb5cc57dc763126bfc6ec5a2b79d02e77eadf9d9efb1888a5c366b7799c1c24", "action": "add" } }, "OnDiskBlobDeposit": { - "2": { - "version": 2, - "hash": "83d6ec5c1c0c67627ad117b287201a75d9d91eb043921992bc761cf08b9526f0", + "1": { + "version": 1, + "hash": "817bf1bee4a35bfa1cd25d6779a10d8d180b1b3f1e837952f81f48b9411d1970", "action": "add" } }, "RemoteConfig": { - "2": { - "version": 2, - "hash": "9ec87d036c109dd408ed2ab8042a735f0150358799c4acc8af582148605373fc", + "1": { + "version": 1, + "hash": "179d067099a178d748c6d9a0477e8de7c3b55577439669eca7150258f2409567", "action": "add" } }, "AzureRemoteConfig": { - "2": { - "version": 2, - "hash": "4f5f6f4d0b52788c2ae484c5da6346f1c8b25ae064d865da69e6dffb32275852", + "1": { + "version": 1, + "hash": "a143811fec0da5fd881e927643ef667c91c78a2c90519cf88da7da20738bd187", "action": "add" } }, "SeaweedFSBlobDeposit": { - "4": { - "version": 4, - "hash": "d5c268e0ccbb00149319679b95eb43134ae80ae43814d7f991732530c79399a1", + "1": { + "version": 1, + "hash": "febeb2a2ce81aa2c512e4c6b611b582984042aafa0541403d4584662273a166c", "action": "add" } }, "DictStoreConfig": { - "2": { - "version": 2, - "hash": "4f7084ac3353fb7c16b010b654150096c08de108fbdaf6e8837654aa38a32466", + "1": { + "version": 1, + "hash": "2e1365c5535fa51c22eef79f67dd6444789bc829c27881367e3050e06e2ffbfe", "action": "add" } }, "NumpyArrayObject": { - "3": { - "version": 3, - "hash": "9e43f7bea261b729e7f6fa523ed050ba148fc1caf973ac996f9501af61b6ae8a", - "action": "add" - }, - "4": { - "version": 4, - "hash": "939a577d5929ac8a9c421b1d07acba1c33db63143e6614d533624e4548bf614b", + "1": { + "version": 1, + "hash": "05dd2917b7692b3daf4e7ad083a46fa7ec7a2be8faac8d4a654809189c986443", "action": "add" } }, "NumpyScalarObject": { - "3": { - "version": 3, - "hash": "5f6698e55cfb7105e279e9c28a3c30e759db143d2aa673abef448b78a2a39f69", - "action": "add" - }, - "4": { - "version": 4, - "hash": "5a4e86b712a242037958a3af68d2ab276dc7438db9b9551797323f051ca1a98a", + "1": { + "version": 1, + "hash": "8753e5c78270a5cacbf0439447724772f4765351a4a8b58b0a5c416a6b2c8b6e", "action": "add" } }, "NumpyBoolObject": { - "3": { - "version": 3, - "hash": "3c8db86e9ea1b6c1ee457610b05831c242fb0d375fcc8176bb64f9ae08a5eb00", - "action": "add" - }, - "4": { - "version": 4, - "hash": "b783d03c5d1fe9c4c8d346e2902c1e4ac7faac563c145ee4388c9c2c960963e2", + "1": { + "version": 1, + "hash": "331c44f8fa3d0a077f1aaad7313bae2c43b386d04def7b8bedae9fdf7690134d", "action": "add" } }, "PandasDataframeObject": { - "3": { - "version": 3, - "hash": "a130e7c5f88b4dbbef3030dd5b6b4bf7db3b4f60585f68b920bc250cee46022e", - "action": "add" - }, - "4": { - "version": 4, - "hash": "8b9a0b2c6652c60381c818d327d109404c735e62ad4e827fcd9042ec86325422", + "1": { + "version": 1, + "hash": "5e8018364cea31d5f185a901da4ab89846b02153ee7d041ee8a6d305ece31f90", "action": "add" } }, "PandasSeriesObject": { - "3": { - "version": 3, - "hash": "c36e22ffea7633813ac0d53fd2075de0606abe240acd72d206830c424f62bbc8", - "action": "add" - }, - "4": { - "version": 4, - "hash": "3286a2085b84d6499c97df36a78eca1a0d701e265a43f733cdf5e20ac78ab32d", + "1": { + "version": 1, + "hash": "b8bd482bf16fc7177e9778292cd42f8835b6ced2ce8dc88908b4b8e6d7c7528f", "action": "add" } }, "Change": { - "2": { - "version": 2, - "hash": "26073bb329dd19c65714ed0e2eb5a53aa4454adc02d7f1a22d6f4890149babcf", + "1": { + "version": 1, + "hash": "75fb9a5cd4e76b189ebe130a421d3921a0c251947a48bbb92a2ef1c315dc3c16", "action": "add" } }, "ChangeStatus": { - "2": { - "version": 2, - "hash": "260b340ed0b44c82a17e0d5662914a0cbf5ca02e62e36be2cc5e0dba0fc7ef01", + "1": { + "version": 1, + "hash": "c914a6f7637b555a51b71e8e197e591f7a2e28121e29b5dd586f87e0383d179d", "action": "add" } }, "ActionStoreChange": { - "2": { - "version": 2, - "hash": "98ae17d2677c72d5820ea6824a4f5fa1a5441fa4064d0fef9f6597056dfbcfcd", + "1": { + "version": 1, + "hash": "1a803bb08924b49f3114fd46e0e132f819d4d56be5e03a27e9fe90947ca26e85", "action": "add" } }, "CreateCustomImageChange": { - "2": { - "version": 2, - "hash": "4b4c9312ab44c7b7c1c68ba9548da80e2454f6b8ea99f7652e546c635fd7f37b", - "action": "add" - }, - "3": { - "version": 3, - "hash": "c6c74ecacd2be69c6d494e25c6ccc5df92f28a26273316424aa9daf0936d00d6", + "1": { + "version": 1, + "hash": "c3dbea3f49979fdcc517c0d13cd02739ca2fe86b370c42496a224f142ae31562", "action": "add" } }, "CreateCustomWorkerPoolChange": { - "2": { - "version": 2, - "hash": "cafeea65a74c11caf6dae2ebe47175d6d0947e35ca7b832240513eaab3fd63d8", - "action": "add" - }, - "3": { - "version": 3, - "hash": "3a96efb85ffaba05479c16963de853e7d4a77bd36db5341dbcb9426fb28fee7e", + "1": { + "version": 1, + "hash": "0355793dd58b364dcb84fff29714b6a26446bead3ba95c6d75e3200008e580f4", "action": "add" } }, "Request": { - "2": { - "version": 2, - "hash": "fad2e98b71d28b0039a631af4714858c495559ccbc93ccc2b1beed463f6d9452", - "action": "add" - }, - "3": { - "version": 3, - "hash": "25602e25c595d36f3755a8e8e16fc94ce9e832af36e8670f88406a0b180fcc51", + "1": { + "version": 1, + "hash": "1d69f5f0074114f99aa29c5ee77cb20b9151e5b50e77b026f11c3632a12efadf", "action": "add" } }, "RequestInfo": { - "2": { - "version": 2, - "hash": "65d41c5f3bc80202993c2167d42c030217956bd7932b92179f20016f47ab00b1", + "1": { + "version": 1, + "hash": "779562547744ebed64548f8021647292604fdf4256bf79685dfa14a1e56cc27b", "action": "add" } }, "RequestInfoFilter": { - "2": { - "version": 2, - "hash": "dea1b2af70f35864698027ca79eac4e1a23f03eb2faa26109259353a92afa960", + "1": { + "version": 1, + "hash": "bb881a003032f4676321218d7cd09580f4d64fccaa1cf9e118fdcd5c73c3d3a8", "action": "add" } }, "SubmitRequest": { - "2": { - "version": 2, - "hash": "76819df6cbf6288428a1fe523e88f53fdd6e7399ba8196140b96bcd891e67517", + "1": { + "version": 1, + "hash": "6c38b6ffd0a6f7442746e68b9ace7b21cb1dca7d2031929db5f9a302a280403f", "action": "add" } }, "ObjectMutation": { - "2": { - "version": 2, - "hash": "215cd56d33a58c8f5f725ad5ff32f62aa0b11330328ea952dc4df040983babbd", + "1": { + "version": 1, + "hash": "ce88096760ce9334599c8194ec97b0a1470651ad680d9d21b8826a0df0af2a36", "action": "add" } }, "EnumMutation": { - "2": { - "version": 2, - "hash": "9c3b684b8a0c165eee84a58fb0955b85c3f8c34d7bd34a31dd07a7e24ef82be2", + "1": { + "version": 1, + "hash": "5173fda73df17a344eb663b7692cca48bd46bf1773455439836b852cd165448c", "action": "add" } }, "UserCodeStatusChange": { - "3": { - "version": 3, - "hash": "f9243a74da84b4e5a8ea63bc73a027e385e8e0e90658cac161d9c35bbfbb981d", + "1": { + "version": 1, + "hash": "89aaf7f1368c782e3a1b9e79988877f6eaa05ab84365f7d321b757fde7fe86e7", "action": "add" } }, "SyncedUserCodeStatusChange": { - "3": { - "version": 3, - "hash": "133db7a12c8b883d8c7ce73a7c5b79e93400c7baeacbe9a32bd42c8188ed5252", + "1": { + "version": 1, + "hash": "d9ad2d341eb645bd50d06330cd30fd4c266f93e37b9f5391d58b78365fc440e6", "action": "add" } }, "TwinAPIContextView": { "1": { "version": 1, - "hash": "1a2836ba7832013912a649c4d73ed85ef5e3323af8f75f7d1bc9e7db4c483a60", + "hash": "e099eef32cb3a8a806cbdc54cc7fca96bed3d60344bd571163ec049db407938b", "action": "add" } }, "CustomAPIView": { "1": { "version": 1, - "hash": "4defa7437482a8499ffeb84705f74dd24ca44e03379040d7324c8f2eaeb9fe82", + "hash": "769e96bebd05736ab860591670fb6da19406239b0104ddc71bd092a134335146", "action": "add" } }, "CustomApiEndpoint": { "1": { "version": 1, - "hash": "1651e640f1b9fb3e39d86336ce7bbcd6539fb44344382d02342474b2f01e2464", + "hash": "ec4a217585336d1b59c93c18570443a63f4fbb24d2c088fbacf80bcf389d23e8", "action": "add" } }, "PrivateAPIEndpoint": { "1": { "version": 1, - "hash": "c703dfc895ad585d15b2b79b7641555dbacaad80016842dc1c10fa46297a2691", + "hash": "6d7d143432c2811c520ab6dade005ba40173b590e5c676be04f5921b970ef938", "action": "add" } }, "PublicAPIEndpoint": { "1": { "version": 1, - "hash": "3586329beedf63913954d811d46bda3fcf8f1f25669f27b0c35e624a4cdf1370", + "hash": "3bf51fc33aa8feb1abc9d0ef792e8889da31a57050430e0bd8e17f2065ff8734", "action": "add" } }, "UpdateTwinAPIEndpoint": { "1": { "version": 1, - "hash": "92aeddf7a8cb90a542c600c0daeca0c236888cadcc5274ec81ea99516fe3199b", + "hash": "851e59412716e73c7f70a696619e0b375ce136b43f6fe2ea784747091caba5d8", "action": "add" } }, "CreateTwinAPIEndpoint": { "1": { "version": 1, - "hash": "5efa208b4003c5e6580a567dd1677bb298e9a08c3c5c8e4291e3c68b9a5865f2", + "hash": "3d0b84dae95ebcc6647b5aabe54e65b3c6bf957665fde57d8037806a4aac13be", "action": "add" } }, "TwinAPIEndpoint": { "1": { "version": 1, - "hash": "ca4925c40e21464f49ecb0b9c2067328a7fa95242be91ca02f705b7b2230fa6e", + "hash": "d1947b8f9c80d6c9b443e5a9f0758afa8849a5f12b9a511feefd7e4f82c374f4", "action": "add" } }, "SyncState": { - "2": { - "version": 2, - "hash": "22b70f9e51f667204ab4653cef18363831d50175e8962b62ac830b1f11ee1857", + "1": { + "version": 1, + "hash": "9a3f0bb973858b55bc766c9770c4d9abcc817898f797d94a89938650c0c67868", "action": "add" - }, - "3": { - "version": 3, - "hash": "a06fb5e7826b4a33bc738280b661a2384fd4d4757551945b9302d01a1abaff85", + } + }, + "WorkerSettings": { + "1": { + "version": 1, + "hash": "b8ddbe75a95b0312a64b5f25e0fc415aeac5c391975d02b515db8c848482f737", "action": "add" } }, - "ServerPeer": { - "2": { - "version": 2, - "hash": "daf8c5226dfa253ad13719aed78625c9d982b17a8927ffb818ab7cb56c255153", + "HTTPServerRoute": { + "1": { + "version": 1, + "hash": "938245604a9c7e50001299afff5b669b2548364e356fed22a22780497831bf81", + "action": "add" + } + }, + "PythonServerRoute": { + "1": { + "version": 1, + "hash": "a068d8f942d55ecb6d45af88a27c6ebf208584275bf589cbc308df3f774ab9a9", + "action": "add" + } + }, + "VeilidServerRoute": { + "1": { + "version": 1, + "hash": "e676bc165601d2ede69707a4b6168ed4674f3f98887026d098a2dd4da4dfd097", "action": "add" - }, - "3": { - "version": 3, - "hash": "eee060523d89db3abc29fd6e6997f9a8210d221923f768e4a672521e8fb1fb31", + } + }, + "ServerPeer": { + "1": { + "version": 1, + "hash": "0d5f252018e324ea0d2dcb5c2ad8bd15707220565fce4f14de7f63a8f9e4391b", "action": "add" } }, "ServerPeerUpdate": { "1": { "version": 1, - "hash": "38a171ff362dd1da6d2eb34d51aea753496b2860d6b25adc595e6241ca5bf63c", + "hash": "0b854b57db7a18118c1fd8f31495b2ba4eeb9fbe4f24c631ff112418a94570d3", "action": "add" } }, "AssociationRequestChange": { "1": { "version": 1, - "hash": "2102685cc30aec0d5a2b1f62f38b475745dc129599fce6c57e2bb92d13f1179d", + "hash": "0134ac0002879c85fc9ddb06bed6306a8905c8434b0a40d3a96ce24a7bd4da90", "action": "add" } }, "QueueItem": { - "4": { - "version": 4, - "hash": "aa04c1a0807164b9307a18d250e09eaf27f74efef61bec9392cd386eb43aa5e6", + "1": { + "version": 1, + "hash": "1db212c46b6c56ccc5579cfe2141b693f0cd9286e2ede71210393e8455379bf1", "action": "add" } }, "ActionQueueItem": { - "3": { - "version": 3, - "hash": "df2399704de2c69a8a10524133bdb062bee6c48ad18b713d7d7f23fab1819bf7", + "1": { + "version": 1, + "hash": "396d579dfc2e2b36b9fbed2f204bffcca1bea7ee2db7175045dd3328ebf08718", "action": "add" } }, "APIEndpointQueueItem": { "1": { "version": 1, - "hash": "d94c0bc1efc18f0217b7342ac49a3ddd4d26df9ffa678a706e84643f7cd3df00", + "hash": "f04b3990a8d29c116d301e70df54d58f188895307a411dc13a666ff764ffd8dd", "action": "add" } }, - "SyftObjectMigrationState": { - "2": { - "version": 2, - "hash": "51f416fbce4ff408903b96aafa924fc3adde33b19172122b06acd04a1651c7ab", + "ZMQClientConfig": { + "1": { + "version": 1, + "hash": "36ee8f75067d5144f0ed062cdc79466caae16b7a128231d89b6b430174843bde", + "action": "add" + } + }, + "SQLiteStoreConfig": { + "1": { + "version": 1, + "hash": "ad062a5f863ae84683867d2a6a5e1d4420c010a64b88bc7b392106e33d71ac03", "action": "add" } }, "ProjectThreadMessage": { - "2": { - "version": 2, - "hash": "506b292e24486632a2e7d816c48a3051b23527c8a3a35f726ffd7249222b15bb", + "1": { + "version": 1, + "hash": "99256d7592577d1e37df94a06eabc0a287f2d79e144c51fd719315e278edb46d", "action": "add" } }, "ProjectMessage": { - "2": { - "version": 2, - "hash": "1fabc4acc439749ba2f62f1cf01b56c91a31d59d908bfe206822f88552d3ce71", + "1": { + "version": 1, + "hash": "b5004b6354f71b19c81dd5f4b20bf446e0b959f5608a22707e96b944dd8175b0", "action": "add" } }, "ProjectRequestResponse": { - "2": { - "version": 2, - "hash": "7b08ce278d58b8ee96d7bc594079c808ec06fd148f14aedc638aba4075d05a1e", + "1": { + "version": 1, + "hash": "52162a8a779a4a301d8755691bf4cf994c86b9f650f9e8c8a923b44e635b1bc0", "action": "add" } }, "ProjectRequest": { - "2": { - "version": 2, - "hash": "ceb9fc7a258dc1574ced311051466f2686f29b1bd65828810f2c87d2022c8533", + "1": { + "version": 1, + "hash": "dc684135d5a5a48e5fc7988598c1e6e0de76cf1c5995f1c283fcf63d0eb4d24f", "action": "add" } }, "AnswerProjectPoll": { - "2": { - "version": 2, - "hash": "b9bd5e61af04a96b93fd9f2e2d8548f8defc391258014c4fbbe4dc80f47c9705", + "1": { + "version": 1, + "hash": "c83d83a5ba6cc034d5061df200b3f1d029aa770b1e13dbef959bb1790323dc6e", "action": "add" } }, "ProjectPoll": { - "2": { - "version": 2, - "hash": "0dcad5d725714cd023f6d7d40139bb6657a9f39a027ee67442b970c43006623a", + "1": { + "version": 1, + "hash": "ecf69b3b324e0bee9c82295796d44c4e8f796496cdc9db6d4302c2f160566466", "action": "add" } }, "Project": { - "2": { - "version": 2, - "hash": "2088e56054a45f13600d63cb44f00674dfa43e79e63639c912c0e58302526e3c", + "1": { + "version": 1, + "hash": "de86a1163ddbcd1cc3cc2b1b5dfcb85a8ad9f9d4bbc759c2b1f92a0d0a2ff184", "action": "add" } }, "ProjectSubmit": { - "2": { - "version": 2, - "hash": "5341778735a00699b085a0d99afca630cbff8d25aa0f2205a09f74e93263c5e0", - "action": "add" - } - }, - "ZMQClientConfig": { - "4": { - "version": 4, - "hash": "f54c62694a0b058ebf41d48b783b70423894a0609f50bc3d347b7b135d142674", - "action": "add" - } - }, - "SQLiteStoreConfig": { - "2": { - "version": 2, - "hash": "b6d391bd7884886daef88b08734cf41b4d278b474c22cfc3574b9e7ec140c9e3", - "action": "add" - } - }, - "Plan": { - "2": { - "version": 2, - "hash": "eec308b8fd9437fc74a65f0cf70dff586130b35866d1e1512de49d45e7896981", - "action": "add" - } - }, - "StoreMetadata": { "1": { "version": 1, - "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", + "hash": "7555ba11ee5a814dcd9c45647300020f7359efc1081559940990cbd745936cac", "action": "add" } }, - "MigrationData": { + "Plan": { "1": { "version": 1, - "hash": "ae07a6345762b8ebe9d2a100776e2405fd17516c9d224913a3358c96480ba889", + "hash": "ed05cb87aec832098fc464ac36cd6bceaab705463d0d2fa1b2d8e1ccc510018c", "action": "add" } } diff --git a/packages/syft/src/syft/server/worker_settings.py b/packages/syft/src/syft/server/worker_settings.py index c9c8bd5eebd..b1ea8a7389f 100644 --- a/packages/syft/src/syft/server/worker_settings.py +++ b/packages/syft/src/syft/server/worker_settings.py @@ -13,7 +13,7 @@ from ..service.queue.base_queue import QueueConfig from ..store.blob_storage import BlobStorageConfig from ..store.document_store import StoreConfig -from ..types.syft_object import SYFT_OBJECT_VERSION_3 +from ..types.syft_object import SYFT_OBJECT_VERSION_1 from ..types.syft_object import SyftObject from ..types.uid import UID @@ -21,7 +21,7 @@ @serializable() class WorkerSettings(SyftObject): __canonical_name__ = "WorkerSettings" - __version__ = SYFT_OBJECT_VERSION_3 + __version__ = SYFT_OBJECT_VERSION_1 id: UID name: str diff --git a/packages/syft/src/syft/service/action/action_object.py b/packages/syft/src/syft/service/action/action_object.py index 06630ffafed..ae2e0d6e66c 100644 --- a/packages/syft/src/syft/service/action/action_object.py +++ b/packages/syft/src/syft/service/action/action_object.py @@ -44,15 +44,9 @@ from ...types.base import SyftBaseModel from ...types.datetime import DateTime from ...types.syft_object import SYFT_OBJECT_VERSION_1 -from ...types.syft_migration import migrate -from ...types.syft_object import SYFT_OBJECT_VERSION_2 -from ...types.syft_object import SYFT_OBJECT_VERSION_3 -from ...types.syft_object import SYFT_OBJECT_VERSION_4 from ...types.syft_object import SyftBaseObject from ...types.syft_object import SyftObject from ...types.syncable_object import SyncableSyftObject -from ...types.transforms import drop -from ...types.transforms import make_set_default from ...types.uid import LineageID from ...types.uid import UID from ...util.util import prompt_warning_message @@ -678,50 +672,12 @@ def truncate_str(string: str, length: int = 100) -> str: return string -@serializable(without=["syft_pre_hooks__", "syft_post_hooks__"]) -class ActionObjectV3(SyncableSyftObject): - """Action object for remote execution.""" - - __canonical_name__ = "ActionObject" - __version__ = SYFT_OBJECT_VERSION_1 - __private_sync_attr_mocks__: ClassVar[dict[str, Any]] = { - "syft_action_data_cache": None, - "syft_blob_storage_entry_id": None, - } - - __attr_searchable__: list[str] = [] # type: ignore[misc] - syft_action_data_cache: Any | None = None - syft_blob_storage_entry_id: UID | None = None - syft_pointer_type: ClassVar[type[ActionObjectPointer]] - - # Help with calculating history hash for code verification - syft_parent_hashes: int | list[int] | None = None - syft_parent_op: str | None = None - syft_parent_args: Any | None = None - syft_parent_kwargs: Any | None = None - syft_history_hash: int | None = None - syft_internal_type: ClassVar[type[Any]] - syft_server_uid: UID | None = None - syft_pre_hooks__: dict[str, list] = {} - syft_post_hooks__: dict[str, list] = {} - syft_twin_type: TwinMode = TwinMode.NONE - syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS - syft_action_data_type: type | None = None - syft_action_data_repr_: str | None = None - syft_action_data_str_: str | None = None - syft_has_bool_attr: bool | None = None - syft_resolve_data: bool | None = None - syft_created_at: DateTime | None = None - syft_resolved: bool = True - syft_action_data_server_id: UID | None = None - - @serializable(without=["syft_pre_hooks__", "syft_post_hooks__"]) class ActionObject(SyncableSyftObject): """Action object for remote execution.""" __canonical_name__ = "ActionObject" - __version__ = SYFT_OBJECT_VERSION_4 + __version__ = SYFT_OBJECT_VERSION_1 __private_sync_attr_mocks__: ClassVar[dict[str, Any]] = { "syft_action_data_cache": None, "syft_blob_storage_entry_id": None, @@ -2237,22 +2193,6 @@ def __rrshift__(self, other: Any) -> Any: return self._syft_output_action_object(self.__rrshift__(other)) -@serializable() -class AnyActionObjectV3(ActionObjectV3): - """ - This is a catch-all class for all objects that are not - defined in the `action_types` dictionary. - """ - - __canonical_name__ = "AnyActionObject" - __version__ = SYFT_OBJECT_VERSION_1 - - syft_internal_type: ClassVar[type[Any]] = NoneType # type: ignore - # syft_passthrough_attrs: List[str] = [] - syft_dont_wrap_attrs: list[str] = ["__str__", "__repr__", "syft_action_data_str_"] - syft_action_data_str_: str = "" - - @serializable() class AnyActionObject(ActionObject): """ @@ -2261,7 +2201,7 @@ class AnyActionObject(ActionObject): """ __canonical_name__ = "AnyActionObject" - __version__ = SYFT_OBJECT_VERSION_4 + __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[type[Any]] = NoneType # type: ignore # syft_passthrough_attrs: List[str] = [] @@ -2303,23 +2243,3 @@ def has_action_data_empty(args: Any, kwargs: Any) -> bool: if is_action_data_empty(a): return True return False - - -@migrate(ActionObjectV3, ActionObject) -def upgrade_action_object() -> list[Callable]: - return [make_set_default("syft_action_saved_to_blob_store", True)] - - -@migrate(ActionObject, ActionObjectV3) -def downgrade_action_object() -> list[Callable]: - return [drop("syft_action_saved_to_blob_store")] - - -@migrate(AnyActionObjectV3, AnyActionObject) -def upgrade_anyaction_object() -> list[Callable]: - return [make_set_default("syft_action_saved_to_blob_store", True)] - - -@migrate(AnyActionObject, AnyActionObjectV3) -def downgrade_anyaction_object() -> list[Callable]: - return [drop("syft_action_saved_to_blob_store")] diff --git a/packages/syft/src/syft/service/action/numpy.py b/packages/syft/src/syft/service/action/numpy.py index b481819cc3b..1949eeb0575 100644 --- a/packages/syft/src/syft/service/action/numpy.py +++ b/packages/syft/src/syft/service/action/numpy.py @@ -1,5 +1,4 @@ # stdlib -from collections.abc import Callable from typing import Any from typing import ClassVar @@ -10,14 +9,8 @@ # relative from ...serde.serializable import serializable from ...types.syft_object import SYFT_OBJECT_VERSION_1 -from ...types.syft_migration import migrate -from ...types.syft_object import SYFT_OBJECT_VERSION_3 -from ...types.syft_object import SYFT_OBJECT_VERSION_4 -from ...types.transforms import drop -from ...types.transforms import make_set_default from .action_object import ActionObject from .action_object import ActionObjectPointer -from .action_object import ActionObjectV3 from .action_object import BASE_PASSTHROUGH_ATTRS from .action_types import action_types @@ -47,21 +40,12 @@ def numpy_like_eq(left: Any, right: Any) -> bool: # 🔵 TODO 7: Map TPActionObjects and their 3rd Party types like numpy type to these # classes for bi-directional lookup. -@serializable() -class NumpyArrayObjectV3(ActionObjectV3, np.lib.mixins.NDArrayOperatorsMixin): - __canonical_name__ = "NumpyArrayObject" - __version__ = SYFT_OBJECT_VERSION_1 - - syft_internal_type: ClassVar[type[Any]] = np.ndarray - syft_pointer_type: ClassVar[type[ActionObjectPointer]] = NumpyArrayObjectPointer - syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs: list[str] = ["dtype", "shape"] @serializable() class NumpyArrayObject(ActionObject, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyArrayObject" - __version__ = SYFT_OBJECT_VERSION_4 + __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[type[Any]] = np.ndarray syft_pointer_type: ClassVar[type[ActionObjectPointer]] = NumpyArrayObjectPointer @@ -101,20 +85,10 @@ def __array_ufunc__( ) -@serializable() -class NumpyScalarObjectV3(ActionObjectV3, np.lib.mixins.NDArrayOperatorsMixin): - __canonical_name__ = "NumpyScalarObject" - __version__ = SYFT_OBJECT_VERSION_1 - - syft_internal_type: ClassVar[type] = np.number - syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs: list[str] = ["dtype", "shape"] - - @serializable() class NumpyScalarObject(ActionObject, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyScalarObject" - __version__ = SYFT_OBJECT_VERSION_4 + __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[type] = np.number syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS @@ -124,20 +98,10 @@ def __float__(self) -> float: return float(self.syft_action_data) -@serializable() -class NumpyBoolObjectV3(ActionObjectV3, np.lib.mixins.NDArrayOperatorsMixin): - __canonical_name__ = "NumpyBoolObject" - __version__ = SYFT_OBJECT_VERSION_1 - - syft_internal_type: ClassVar[type] = np.bool_ - syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs: list[str] = ["dtype", "shape"] - - @serializable() class NumpyBoolObject(ActionObject, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyBoolObject" - __version__ = SYFT_OBJECT_VERSION_4 + __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[type] = np.bool_ syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS @@ -173,33 +137,3 @@ class NumpyBoolObject(ActionObject, np.lib.mixins.NDArrayOperatorsMixin): for scalar_type in SUPPORTED_INT_TYPES + SUPPORTED_FLOAT_TYPES: # type: ignore action_types[scalar_type] = NumpyScalarObject - - -@migrate(NumpyArrayObjectV3, NumpyArrayObject) -def upgrade_numpyarray_object() -> list[Callable]: - return [make_set_default("syft_action_saved_to_blob_store", True)] - - -@migrate(NumpyArrayObject, NumpyArrayObjectV3) -def downgrade_numpyarray_object() -> list[Callable]: - return [drop("syft_action_saved_to_blob_store")] - - -@migrate(NumpyBoolObjectV3, NumpyBoolObject) -def upgrade_numpybool_object() -> list[Callable]: - return [make_set_default("syft_action_saved_to_blob_store", True)] - - -@migrate(NumpyBoolObject, NumpyBoolObjectV3) -def downgrade_numpybool_object() -> list[Callable]: - return [drop("syft_action_saved_to_blob_store")] - - -@migrate(NumpyScalarObjectV3, NumpyScalarObject) -def upgrade_numpyscalar_object() -> list[Callable]: - return [make_set_default("syft_action_saved_to_blob_store", True)] - - -@migrate(NumpyScalarObject, NumpyScalarObjectV3) -def downgrade_numpyscalar_object() -> list[Callable]: - return [drop("syft_action_saved_to_blob_store")] diff --git a/packages/syft/src/syft/service/action/pandas.py b/packages/syft/src/syft/service/action/pandas.py index 0eeec3b281e..9de480ddd0f 100644 --- a/packages/syft/src/syft/service/action/pandas.py +++ b/packages/syft/src/syft/service/action/pandas.py @@ -1,5 +1,4 @@ # stdlib -from collections.abc import Callable from typing import Any from typing import ClassVar @@ -10,32 +9,15 @@ # relative from ...serde.serializable import serializable from ...types.syft_object import SYFT_OBJECT_VERSION_1 -from ...types.syft_migration import migrate -from ...types.syft_object import SYFT_OBJECT_VERSION_3 -from ...types.syft_object import SYFT_OBJECT_VERSION_4 -from ...types.transforms import drop -from ...types.transforms import make_set_default from .action_object import ActionObject -from .action_object import ActionObjectV3 from .action_object import BASE_PASSTHROUGH_ATTRS from .action_types import action_types -@serializable() -class PandasDataFrameObjectV3(ActionObjectV3): - __canonical_name__ = "PandasDataframeObject" - __version__ = SYFT_OBJECT_VERSION_1 - - syft_internal_type: ClassVar[type] = DataFrame - syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS - # this is added for instance checks for dataframes - # syft_dont_wrap_attrs = ["shape"] - - @serializable() class PandasDataFrameObject(ActionObject): __canonical_name__ = "PandasDataframeObject" - __version__ = SYFT_OBJECT_VERSION_4 + __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[type] = DataFrame syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS @@ -63,19 +45,10 @@ def __bool__(self) -> bool: return bool(self.syft_action_data_cache.empty) -@serializable() -class PandasSeriesObjectV3(ActionObjectV3): - __canonical_name__ = "PandasSeriesObject" - __version__ = SYFT_OBJECT_VERSION_1 - - syft_internal_type = Series - syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS - - @serializable() class PandasSeriesObject(ActionObject): __canonical_name__ = "PandasSeriesObject" - __version__ = SYFT_OBJECT_VERSION_4 + __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type = Series syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS @@ -100,23 +73,3 @@ def syft_is_property(self, obj: Any, method: str) -> bool: action_types[DataFrame] = PandasDataFrameObject action_types[Series] = PandasSeriesObject - - -@migrate(PandasSeriesObjectV3, PandasSeriesObject) -def upgrade_pandasseries_object() -> list[Callable]: - return [make_set_default("syft_action_saved_to_blob_store", True)] - - -@migrate(PandasSeriesObject, PandasSeriesObjectV3) -def downgrade_pandasseries_object() -> list[Callable]: - return [drop("syft_action_saved_to_blob_store")] - - -@migrate(PandasDataFrameObjectV3, PandasDataFrameObject) -def upgrade_pandasdataframe_object() -> list[Callable]: - return [make_set_default("syft_action_saved_to_blob_store", True)] - - -@migrate(PandasDataFrameObject, PandasDataFrameObjectV3) -def downgrade_pandasdataframe_object() -> list[Callable]: - return [drop("syft_action_saved_to_blob_store")] diff --git a/packages/syft/src/syft/service/code/user_code.py b/packages/syft/src/syft/service/code/user_code.py index 2474556c10c..4b8c1c8e7ae 100644 --- a/packages/syft/src/syft/service/code/user_code.py +++ b/packages/syft/src/syft/service/code/user_code.py @@ -42,7 +42,6 @@ from ...client.api import APIRegistry from ...client.api import ServerIdentity from ...client.api import generate_remote_function -from ...client.enclave_client import EnclaveMetadata from ...serde.deserialize import _deserialize from ...serde.serializable import serializable from ...serde.serialize import _serialize @@ -58,9 +57,7 @@ from ...types.syft_object import SyftObject from ...types.syncable_object import SyncableSyftObject from ...types.transforms import TransformContext -from ...types.transforms import add_node_uid_for_key from ...types.transforms import add_server_uid_for_key -from ...types.transforms import drop from ...types.transforms import generate_id from ...types.transforms import transform from ...types.uid import UID @@ -275,38 +272,6 @@ def get_sync_dependencies(self, context: AuthedServiceContext) -> list[UID]: return [self.user_code_link.object_uid] -@serializable() -class UserCodeV4(SyncableSyftObject): - # version - __canonical_name__ = "UserCode" - __version__ = SYFT_OBJECT_VERSION_4 - - id: UID - server_uid: UID | None = None - user_verify_key: SyftVerifyKey - raw_code: str - input_policy_type: type[InputPolicy] | UserPolicy - input_policy_init_kwargs: dict[Any, Any] | None = None - input_policy_state: bytes = b"" - output_policy_type: type[OutputPolicy] | UserPolicy - output_policy_init_kwargs: dict[Any, Any] | None = None - output_policy_state: bytes = b"" - parsed_code: str - service_func_name: str - unique_func_name: str - user_unique_func_name: str - code_hash: str - signature: inspect.Signature - status_link: LinkedObject - input_kwargs: list[str] - enclave_metadata: EnclaveMetadata | None = None - submit_time: DateTime | None = None - # tracks if the code calls datasite.something, variable is set during parsing - uses_datasite: bool = False - nested_codes: dict[str, tuple[LinkedObject, dict]] | None = {} - worker_pool_name: str | None = None - - @serializable() class UserCode(SyncableSyftObject): # version diff --git a/packages/syft/src/syft/service/code_history/code_history.py b/packages/syft/src/syft/service/code_history/code_history.py index 197e3630a45..db1464c4add 100644 --- a/packages/syft/src/syft/service/code_history/code_history.py +++ b/packages/syft/src/syft/service/code_history/code_history.py @@ -17,6 +17,7 @@ from ..code.user_code import UserCode from ..response import SyftError + @serializable() class CodeHistory(SyftObject): # version diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index b8e344d99ec..623e8d9f763 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -25,14 +25,9 @@ from ...types.datetime import DateTime from ...types.dicttuple import DictTuple from ...types.syft_object import SYFT_OBJECT_VERSION_1 -from ...types.syft_migration import migrate -from ...types.syft_object import SYFT_OBJECT_VERSION_2 -from ...types.syft_object import SYFT_OBJECT_VERSION_3 from ...types.syft_object import SyftObject from ...types.transforms import TransformContext -from ...types.transforms import drop from ...types.transforms import generate_id -from ...types.transforms import make_set_default from ...types.transforms import transform from ...types.transforms import validate_url from ...types.uid import UID @@ -456,44 +451,11 @@ def get_shape_or_len(obj: Any) -> tuple[int, ...] | int | None: return None -@serializable() -class DatasetV2(SyftObject): - # version - __canonical_name__: str = "Dataset" - __version__ = SYFT_OBJECT_VERSION_1 - - id: UID - name: str - server_uid: UID | None = None - asset_list: list[Asset] = [] - contributors: set[Contributor] = set() - citation: str | None = None - url: str | None = None - description: MarkdownDescription | None = None - updated_at: str | None = None - requests: int | None = 0 - mb_size: float | None = None - created_at: DateTime = DateTime.now() - uploader: Contributor - - __attr_searchable__ = [ - "name", - "citation", - "url", - "description", - "action_ids", - "summary", - ] - __attr_unique__ = ["name"] - __repr_attrs__ = ["name", "url", "created_at"] - __table_sort_attr__ = "Created at" - - @serializable() class Dataset(SyftObject): # version __canonical_name__: str = "Dataset" - __version__ = SYFT_OBJECT_VERSION_3 + __version__ = SYFT_OBJECT_VERSION_1 id: UID name: str @@ -662,25 +624,11 @@ class DatasetPageView(SyftObject): total: int -@serializable() -class CreateDatasetV2(DatasetV2): - # version - __canonical_name__ = "CreateDataset" - __version__ = SYFT_OBJECT_VERSION_1 - asset_list: list[CreateAsset] = [] - - __repr_attrs__ = ["name", "url"] - - id: UID | None = None # type: ignore[assignment] - created_at: DateTime | None = None # type: ignore[assignment] - uploader: Contributor | None = None # type: ignore[assignment] - - @serializable() class CreateDataset(Dataset): # version __canonical_name__ = "CreateDataset" - __version__ = SYFT_OBJECT_VERSION_3 + __version__ = SYFT_OBJECT_VERSION_1 asset_list: list[CreateAsset] = [] __repr_attrs__ = ["name", "summary", "url"] @@ -931,41 +879,5 @@ def createdataset_to_dataset() -> list[Callable]: ] -@migrate(DatasetV2, Dataset) -def migrate_dataset_v2_to_v3() -> list[Callable]: - return [ - make_set_default("summary", None), - drop("__repr_attrs__"), - make_set_default("__repr_attrs__", ["name", "summary", "url", "created_at"]), - ] - - -@migrate(Dataset, DatasetV2) -def migrate_dataset_v3_to_v2() -> list[Callable]: - return [ - drop("summary"), - drop("__repr_attrs__"), - make_set_default("__repr_attrs__", ["name", "url", "created_at"]), - ] - - -@migrate(CreateDatasetV2, CreateDataset) -def migrate_create_dataset_v2_to_v3() -> list[Callable]: - return [ - make_set_default("summary", None), - drop("__repr_attrs__"), - make_set_default("__repr_attrs__", ["name", "summary", "url"]), - ] - - -@migrate(CreateDataset, CreateDatasetV2) -def migrate_create_dataset_v3_to_v2() -> list[Callable]: - return [ - drop("summary"), - drop("__repr_attrs__"), - make_set_default("__repr_attrs__", ["name", "url"]), - ] - - class DatasetUpdate: pass diff --git a/packages/syft/src/syft/service/job/job_stash.py b/packages/syft/src/syft/service/job/job_stash.py index b7e13732eaa..86762799402 100644 --- a/packages/syft/src/syft/service/job/job_stash.py +++ b/packages/syft/src/syft/service/job/job_stash.py @@ -1,5 +1,4 @@ # stdlib -from collections.abc import Callable from datetime import datetime from datetime import timedelta from datetime import timezone @@ -33,14 +32,8 @@ from ...types.datetime import DateTime from ...types.datetime import format_timedelta from ...types.syft_object import SYFT_OBJECT_VERSION_1 -from ...types.syft_migration import migrate -from ...types.syft_object import SYFT_OBJECT_VERSION_2 -from ...types.syft_object import SYFT_OBJECT_VERSION_4 -from ...types.syft_object import SYFT_OBJECT_VERSION_6 from ...types.syft_object import SyftObject from ...types.syncable_object import SyncableSyftObject -from ...types.transforms import drop -from ...types.transforms import make_set_default from ...types.uid import UID from ...util import options from ...util.colors import SURFACE @@ -83,32 +76,6 @@ def center_content(text: Any) -> str: return center_div -@serializable() -class JobV4(SyncableSyftObject): - __canonical_name__ = "JobItem" - __version__ = SYFT_OBJECT_VERSION_4 - - id: UID - server_uid: UID - result: Any | None = None - resolved: bool = False - status: JobStatus = JobStatus.CREATED - log_id: UID | None = None - parent_job_id: UID | None = None - n_iters: int | None = 0 - current_iter: int | None = None - creation_time: str | None = None - action: Action | None = None - job_pid: int | None = None - job_worker_id: UID | None = None - updated_at: DateTime | None = None - user_code_id: UID | None = None - - __attr_searchable__ = ["parent_job_id", "job_worker_id", "status", "user_code_id"] - __repr_attrs__ = ["id", "result", "resolved", "progress", "creation_time"] - __exclude_sync_diff_attrs__ = ["action"] - - @serializable(canonical_name="JobType", version=1) class JobType(str, Enum): JOB = "job" @@ -773,16 +740,6 @@ def get_sync_dependencies(self, context: AuthedServiceContext) -> list[UID]: # return dependencies -@migrate(Job, JobV4) -def upgrade_job() -> list[Callable]: - return [make_set_default("requested_by", UID())] - - -@migrate(JobV4, Job) -def downgrade_job() -> list[Callable]: - return [drop("requested_by")] - - class JobInfo(SyftObject): __canonical_name__ = "JobInfo" __version__ = SYFT_OBJECT_VERSION_1 diff --git a/packages/syft/src/syft/service/log/log.py b/packages/syft/src/syft/service/log/log.py index a5e27ffdfb4..204409b0079 100644 --- a/packages/syft/src/syft/service/log/log.py +++ b/packages/syft/src/syft/service/log/log.py @@ -1,5 +1,4 @@ # stdlib -from collections.abc import Callable from typing import Any from typing import ClassVar @@ -7,31 +6,10 @@ from ...serde.serializable import serializable from ...service.context import AuthedServiceContext from ...types.syft_object import SYFT_OBJECT_VERSION_1 -from ...types.syft_migration import migrate -from ...types.syft_object import SYFT_OBJECT_VERSION_3 -from ...types.syft_object import SYFT_OBJECT_VERSION_4 from ...types.syncable_object import SyncableSyftObject -from ...types.transforms import drop -from ...types.transforms import make_set_default from ...types.uid import UID -@serializable() -class SyftLogV3(SyncableSyftObject): - __canonical_name__ = "SyftLog" - __version__ = SYFT_OBJECT_VERSION_3 - - __repr_attrs__ = ["stdout", "stderr"] - __exclude_sync_diff_attrs__: list[str] = [] - __private_sync_attr_mocks__: ClassVar[dict[str, Any]] = { - "stderr": "", - "stdout": "", - } - - stdout: str = "" - stderr: str = "" - - @serializable() class SyftLog(SyncableSyftObject): __canonical_name__ = "SyftLog" @@ -62,14 +40,3 @@ def get_sync_dependencies( self, context: AuthedServiceContext, **kwargs: dict ) -> list[UID]: # type: ignore return [self.job_id] - - -@migrate(SyftLogV3, SyftLog) -def upgrade_syftlog() -> list[Callable]: - # TODO: FIX - return [make_set_default("job_id", UID())] - - -@migrate(SyftLog, SyftLogV3) -def downgrade_syftlog() -> list[Callable]: - return [drop("job_id")] diff --git a/packages/syft/src/syft/service/metadata/server_metadata.py b/packages/syft/src/syft/service/metadata/server_metadata.py index db727d08b74..c56eb8a49ae 100644 --- a/packages/syft/src/syft/service/metadata/server_metadata.py +++ b/packages/syft/src/syft/service/metadata/server_metadata.py @@ -13,10 +13,8 @@ from ...abstract_server import ServerType from ...protocol.data_protocol import get_data_protocol from ...serde.serializable import serializable -from ...types.syft_object import SYFT_OBJECT_VERSION_1 from ...server.credentials import SyftVerifyKey -from ...types.syft_object import SYFT_OBJECT_VERSION_4 -from ...types.syft_object import SYFT_OBJECT_VERSION_5 +from ...types.syft_object import SYFT_OBJECT_VERSION_1 from ...types.syft_object import StorableObjectType from ...types.syft_object import SyftObject from ...types.transforms import convert_types @@ -47,7 +45,7 @@ def check_version( @serializable() class ServerMetadata(SyftObject): __canonical_name__ = "ServerMetadata" - __version__ = SYFT_OBJECT_VERSION_5 + __version__ = SYFT_OBJECT_VERSION_1 name: str id: UID @@ -71,31 +69,6 @@ def check_version(self, client_version: str) -> bool: ) -@serializable() -class ServerMetadataV4(SyftObject): - __canonical_name__ = "ServerMetadata" - __version__ = SYFT_OBJECT_VERSION_4 - - name: str - id: UID - verify_key: SyftVerifyKey - highest_version: int - lowest_version: int - syft_version: str - server_type: ServerType = ServerType.DATASITE - organization: str = "OpenMined" - description: str = "Text" - server_side_type: str - show_warnings: bool - - def check_version(self, client_version: str) -> bool: - return check_version( - client_version=client_version, - server_version=self.syft_version, - server_name=self.name, - ) - - @serializable(canonical_name="ServerMetadataJSON", version=1) class ServerMetadataJSON(BaseModel, StorableObjectType): metadata_version: int diff --git a/packages/syft/src/syft/service/migration/object_migration_state.py b/packages/syft/src/syft/service/migration/object_migration_state.py index bb15c9faafa..815bda81c83 100644 --- a/packages/syft/src/syft/service/migration/object_migration_state.py +++ b/packages/syft/src/syft/service/migration/object_migration_state.py @@ -23,7 +23,6 @@ from ...types.blob_storage import CreateBlobStorageEntry from ...types.syft_object import Context from ...types.syft_object import SYFT_OBJECT_VERSION_1 -from ...types.syft_object import SYFT_OBJECT_VERSION_2 from ...types.syft_object import SyftBaseObject from ...types.syft_object import SyftObject from ...types.syft_object_registry import SyftObjectRegistry @@ -37,7 +36,7 @@ @serializable() class SyftObjectMigrationState(SyftObject): __canonical_name__ = "SyftObjectMigrationState" - __version__ = SYFT_OBJECT_VERSION_2 + __version__ = SYFT_OBJECT_VERSION_1 __attr_unique__ = ["canonical_name"] diff --git a/packages/syft/src/syft/service/network/server_peer.py b/packages/syft/src/syft/service/network/server_peer.py index 208fad29bdc..941396820d5 100644 --- a/packages/syft/src/syft/service/network/server_peer.py +++ b/packages/syft/src/syft/service/network/server_peer.py @@ -28,7 +28,6 @@ from .routes import PythonServerRoute from .routes import ServerRoute from .routes import ServerRouteType -from .routes import ServerRouteTypeV1 from .routes import VeilidServerRoute from .routes import connection_to_route from .routes import route_to_connection @@ -43,29 +42,11 @@ class ServerPeerConnectionStatus(Enum): TIMEOUT = "TIMEOUT" -@serializable() -class ServerPeerV2(SyftObject): - # version - __canonical_name__ = "ServerPeer" - __version__ = SYFT_OBJECT_VERSION_1 - - __attr_searchable__ = ["name", "server_type"] - __attr_unique__ = ["verify_key"] - __repr_attrs__ = ["name", "server_type", "admin_email"] - - id: UID | None = None # type: ignore[assignment] - name: str - verify_key: SyftVerifyKey - server_routes: list[ServerRouteTypeV1] = [] - server_type: ServerType - admin_email: str - - @serializable() class ServerPeer(SyftObject): # version __canonical_name__ = "ServerPeer" - __version__ = SYFT_OBJECT_VERSION_3 + __version__ = SYFT_OBJECT_VERSION_1 __attr_searchable__ = ["name", "server_type"] __attr_unique__ = ["verify_key"] diff --git a/packages/syft/src/syft/service/output/output_service.py b/packages/syft/src/syft/service/output/output_service.py index cb0bd1d71ea..386aaa926a9 100644 --- a/packages/syft/src/syft/service/output/output_service.py +++ b/packages/syft/src/syft/service/output/output_service.py @@ -1,5 +1,4 @@ # stdlib -from collections.abc import Callable from typing import ClassVar # third party @@ -19,12 +18,8 @@ from ...store.document_store import QueryKeys from ...store.linked_obj import LinkedObject from ...types.datetime import DateTime -from ...types.syft_migration import migrate from ...types.syft_object import SYFT_OBJECT_VERSION_1 -from ...types.syft_object import SYFT_OBJECT_VERSION_2 from ...types.syncable_object import SyncableSyftObject -from ...types.transforms import drop -from ...types.transforms import make_set_default from ...types.uid import UID from ...util.telemetry import instrument from ..action.action_object import ActionObject @@ -43,36 +38,6 @@ OutputPolicyIdPartitionKey = PartitionKey(key="output_policy_id", type_=UID) -@serializable() -class ExecutionOutputV1(SyncableSyftObject): - __canonical_name__ = "ExecutionOutput" - __version__ = SYFT_OBJECT_VERSION_1 - - executing_user_verify_key: SyftVerifyKey - user_code_link: LinkedObject - output_ids: list[UID] | dict[str, UID] | None = None - job_link: LinkedObject | None = None - created_at: DateTime = DateTime.now() - input_ids: dict[str, UID] | None = None - - # Required for __attr_searchable__, set by model_validator - user_code_id: UID - - # Output policy is not a linked object because its saved on the usercode - output_policy_id: UID | None = None - - __attr_searchable__: ClassVar[list[str]] = [ - "user_code_id", - "created_at", - "output_policy_id", - ] - __repr_attrs__: ClassVar[list[str]] = [ - "created_at", - "user_code_id", - "output_ids", - ] - - @serializable() class ExecutionOutput(SyncableSyftObject): __canonical_name__ = "ExecutionOutput" @@ -279,16 +244,6 @@ def get_by_output_policy_id( ) -@migrate(ExecutionOutputV1, ExecutionOutput) -def upgrade_execution_output() -> list[Callable]: - return [make_set_default("job_id", None)] - - -@migrate(ExecutionOutput, ExecutionOutputV1) -def downgrade_execution_output() -> list[Callable]: - return [drop("job_id")] - - @instrument @serializable(canonical_name="OutputService", version=1) class OutputService(AbstractService): diff --git a/packages/syft/src/syft/service/request/request.py b/packages/syft/src/syft/service/request/request.py index aeee75fb2de..3ec7c5ef184 100644 --- a/packages/syft/src/syft/service/request/request.py +++ b/packages/syft/src/syft/service/request/request.py @@ -30,7 +30,6 @@ from ...types.syncable_object import SyncableSyftObject from ...types.transforms import TransformContext from ...types.transforms import add_server_uid_for_key -from ...types.transforms import drop from ...types.transforms import generate_id from ...types.transforms import transform from ...types.twin_object import TwinObject @@ -372,45 +371,6 @@ def __repr_syft_nested__(self) -> str: return ( f"Create Worker Pool '{self.pool_name}' for Image with id {self.image_uid}" ) -@serializable() -class RequestV2(SyncableSyftObject): - __canonical_name__ = "Request" - __version__ = SYFT_OBJECT_VERSION_1 - - requesting_user_verify_key: SyftVerifyKey - requesting_user_name: str = "" - requesting_user_email: str | None = "" - requesting_user_institution: str | None = "" - approving_user_verify_key: SyftVerifyKey | None = None - request_time: DateTime - updated_at: DateTime | None = None - server_uid: UID - request_hash: str - changes: list[Change] - history: list[ChangeStatus] = [] - __table_coll_widths__ = [ - "min-content", - "auto", - "auto", - "auto", - "auto", - "auto", - ] - - __attr_searchable__ = [ - "requesting_user_verify_key", - "approving_user_verify_key", - ] - __attr_unique__ = ["request_hash"] - __repr_attrs__ = [ - "request_time", - "updated_at", - "status", - "changes", - "requesting_user_verify_key", - ] - __exclude_sync_diff_attrs__ = ["server_uid", "changes", "history"] - __table_sort_attr__ = "Request time" @serializable() diff --git a/packages/syft/src/syft/service/settings/settings.py b/packages/syft/src/syft/service/settings/settings.py index 18a28381ff5..4c710e354a6 100644 --- a/packages/syft/src/syft/service/settings/settings.py +++ b/packages/syft/src/syft/service/settings/settings.py @@ -11,57 +11,20 @@ from ...types.syft_object import PartialSyftObject from ...types.syft_object import SYFT_OBJECT_VERSION_1 from ...types.syft_object import SyftObject -from ...types.syft_object import SYFT_OBJECT_VERSION_3 -from ...types.syft_object import SYFT_OBJECT_VERSION_4 -from ...types.syft_object import SYFT_OBJECT_VERSION_5 -from ...types.syft_object import SYFT_OBJECT_VERSION_6 -from ...types.syft_object import SyftObject -from ...types.transforms import make_set_default from ...types.uid import UID from ...util import options from ...util.colors import SURFACE from ...util.misc_objs import HTMLObject from ...util.misc_objs import MarkdownDescription from ...util.schema import DEFAULT_WELCOME_MSG -from ...util.util import get_env -from ..response import SyftInfo logger = logging.getLogger(__name__) -@serializable() -class ServerSettingsUpdateV4(PartialSyftObject): - __canonical_name__ = "ServerSettingsUpdate" - __version__ = SYFT_OBJECT_VERSION_4 - id: UID - name: str - organization: str - description: str - on_board: bool - signup_enabled: bool - admin_email: str - association_request_auto_approval: bool - welcome_markdown: HTMLObject | MarkdownDescription - server_side_type: str - - @field_validator("server_side_type", check_fields=False) - @classmethod - def validate_server_side_type(cls, v: str) -> type[Empty]: - msg = f"You cannot update 'server_side_type' through ServerSettingsUpdate. \ -Please use client.set_server_side_type_dangerous(server_side_type={v}). \ -Be aware if you have private data on the server and you want to change it to the Low Side, \ -as information might be leaked." - try: - display(SyftInfo(message=msg)) - except Exception as e: - logger.error(msg, exc_info=e) - return Empty - - @serializable() class ServerSettingsUpdate(PartialSyftObject): __canonical_name__ = "ServerSettingsUpdate" - __version__ = SYFT_OBJECT_VERSION_5 + __version__ = SYFT_OBJECT_VERSION_1 id: UID name: str organization: str @@ -77,7 +40,7 @@ class ServerSettingsUpdate(PartialSyftObject): @serializable() class ServerSettings(SyftObject): __canonical_name__ = "ServerSettings" - __version__ = SYFT_OBJECT_VERSION_6 + __version__ = SYFT_OBJECT_VERSION_1 __repr_attrs__ = [ "name", "organization", diff --git a/packages/syft/src/syft/service/sync/diff_state.py b/packages/syft/src/syft/service/sync/diff_state.py index ee96b418170..9465f6f10f9 100644 --- a/packages/syft/src/syft/service/sync/diff_state.py +++ b/packages/syft/src/syft/service/sync/diff_state.py @@ -1126,7 +1126,7 @@ def __call__(self, batch: ObjectDiffBatch) -> bool: class ServerDiff(SyftObject): __canonical_name__ = "ServerDiff" - __version__ = SYFT_OBJECT_VERSION_2 + __version__ = SYFT_OBJECT_VERSION_1 low_server_uid: UID high_server_uid: UID diff --git a/packages/syft/src/syft/service/sync/sync_state.py b/packages/syft/src/syft/service/sync/sync_state.py index aea0540cf2a..8cdb13b4ec6 100644 --- a/packages/syft/src/syft/service/sync/sync_state.py +++ b/packages/syft/src/syft/service/sync/sync_state.py @@ -114,24 +114,6 @@ def td_format(td_object: timedelta) -> str: return ", ".join(strings) -@serializable() -class SyncStateV2(SyftObject): - __canonical_name__ = "SyncState" - __version__ = SYFT_OBJECT_VERSION_2 - - server_uid: UID - server_name: str - server_side_type: ServerSideType - objects: dict[UID, SyncableSyftObject] = {} - dependencies: dict[UID, list[UID]] = {} - created_at: DateTime = Field(default_factory=DateTime.now) - previous_state_link: LinkedObject | None = None - permissions: dict[UID, set[str]] = {} - storage_permissions: dict[UID, set[UID]] = {} - ignored_batches: dict[UID, int] = {} - object_sync_dates: dict[UID, DateTime] = {} - - @serializable() class SyncState(SyftObject): __canonical_name__ = "SyncState" diff --git a/packages/syft/src/syft/store/blob_storage/__init__.py b/packages/syft/src/syft/store/blob_storage/__init__.py index 856a821193e..50f3329ecc0 100644 --- a/packages/syft/src/syft/store/blob_storage/__init__.py +++ b/packages/syft/src/syft/store/blob_storage/__init__.py @@ -146,14 +146,6 @@ def syft_iter_content( raise -@serializable() -class BlobRetrievalByURLV4(BlobRetrieval): - __canonical_name__ = "BlobRetrievalByURL" - __version__ = SYFT_OBJECT_VERSION_4 - - url: ServerURL | str - - @serializable() class BlobRetrievalByURL(BlobRetrieval): __canonical_name__ = "BlobRetrievalByURL" @@ -273,13 +265,3 @@ class BlobStorageConfig(SyftBaseModel): client_type: type[BlobStorageClient] client_config: BlobStorageClientConfig min_blob_size: int = 0 # in MB - - -@migrate(BlobRetrievalByURLV4, BlobRetrievalByURL) -def upgrade_blob_retrieval_by_url() -> list[Callable]: - return [make_set_default("proxy_server_uid", None)] - - -@migrate(BlobRetrievalByURL, BlobRetrievalByURLV4) -def downgrade_blob_retrieval_by_url() -> list[Callable]: - return [drop(["proxy_server_uid"])] diff --git a/packages/syft/src/syft/store/blob_storage/seaweedfs.py b/packages/syft/src/syft/store/blob_storage/seaweedfs.py index 37df0f2c67e..f3215938559 100644 --- a/packages/syft/src/syft/store/blob_storage/seaweedfs.py +++ b/packages/syft/src/syft/store/blob_storage/seaweedfs.py @@ -38,7 +38,7 @@ from ...types.blob_storage import SeaweedSecureFilePathLocation from ...types.blob_storage import SecureFilePathLocation from ...types.server_url import ServerURL -from ...types.syft_object import SYFT_OBJECT_VERSION_4 +from ...types.syft_object import SYFT_OBJECT_VERSION_1 from ...types.uid import UID from ...util.constants import DEFAULT_TIMEOUT diff --git a/packages/syft/src/syft/store/mongo_document_store.py b/packages/syft/src/syft/store/mongo_document_store.py index d12c46e2745..070a738faae 100644 --- a/packages/syft/src/syft/store/mongo_document_store.py +++ b/packages/syft/src/syft/store/mongo_document_store.py @@ -700,7 +700,9 @@ def _get_storage_permissions_for_uid(self, uid: UID) -> Result[Set[UID], str]: return Ok(set(storage_permissions["server_uids"])) - def get_all_storage_permissions(self) -> Result[dict[UID, Set[UID]], str]: # noqa: UP006 + def get_all_storage_permissions( + self, + ) -> Result[dict[UID, Set[UID]], str]: # noqa: UP006 # Returns a dictionary of all storage permissions {object_uid: {*server_uids}} storage_permissions_or_err = self.storage_permissions if storage_permissions_or_err.is_err(): diff --git a/packages/syft/src/syft/types/blob_storage.py b/packages/syft/src/syft/types/blob_storage.py index a1522a4437e..4612ec5a416 100644 --- a/packages/syft/src/syft/types/blob_storage.py +++ b/packages/syft/src/syft/types/blob_storage.py @@ -27,22 +27,16 @@ from ..server.credentials import SyftVerifyKey from ..service.action.action_object import ActionObject from ..service.action.action_object import ActionObjectPointer -from ..service.action.action_object import ActionObjectV3 from ..service.action.action_object import BASE_PASSTHROUGH_ATTRS from ..service.action.action_types import action_types from ..service.response import SyftError from ..service.response import SyftException from ..service.service import from_api_or_context from ..types.server_url import ServerURL -from ..types.transforms import drop from ..types.transforms import keep -from ..types.transforms import make_set_default from ..types.transforms import transform from .datetime import DateTime -from .syft_migration import migrate -from .syft_object import SYFT_OBJECT_VERSION_2 -from .syft_object import SYFT_OBJECT_VERSION_3 -from .syft_object import SYFT_OBJECT_VERSION_4 +from .syft_object import SYFT_OBJECT_VERSION_1 from .syft_object import SyftObject from .uid import UID @@ -195,20 +189,10 @@ class BlobFileObjectPointer(ActionObjectPointer): pass -@serializable() -class BlobFileObjectV3(ActionObjectV3): - __canonical_name__ = "BlobFileOBject" - __version__ = SYFT_OBJECT_VERSION_1 - - syft_internal_type: ClassVar[type[Any]] = BlobFile - syft_pointer_type: ClassVar[type[ActionObjectPointer]] = BlobFileObjectPointer - syft_passthrough_attrs: list[str] = BASE_PASSTHROUGH_ATTRS - - @serializable() class BlobFileObject(ActionObject): __canonical_name__ = "BlobFileOBject" - __version__ = SYFT_OBJECT_VERSION_3 + __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[type[Any]] = BlobFile syft_pointer_type: ClassVar[type[ActionObjectPointer]] = BlobFileObjectPointer @@ -396,13 +380,3 @@ def storage_entry_to_metadata() -> list[Callable]: action_types[BlobFile] = BlobFileObject - - -@migrate(BlobFileObjectV3, BlobFileObject) -def upgrade_blobfile_object() -> list[Callable]: - return [make_set_default("syft_action_saved_to_blob_store", True)] - - -@migrate(BlobFileObject, BlobFileObjectV3) -def downgrade_blobfile_object() -> list[Callable]: - return [drop("syft_action_saved_to_blob_store")] diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 4c534d52ae3..33a86aa5df8 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -39,7 +39,6 @@ from typing_extensions import Self # relative -from ..serde.recursive_primitives import recursive_serde_register_type from ..serde.serializable import serializable from ..serde.serialize import _serialize as serialize from ..server.credentials import SyftVerifyKey @@ -52,6 +51,7 @@ from ..util.util import get_qualname_for from .syft_metaclass import Empty from .syft_metaclass import PartialModelMetaclass +from .syft_object_registry import SyftObjectRegistry from .uid import UID logger = logging.getLogger(__name__) From 0d0f7f85be1fa78046a3bfcece2aa29c727186ab Mon Sep 17 00:00:00 2001 From: teo Date: Wed, 17 Jul 2024 15:13:30 +0300 Subject: [PATCH 086/117] fix some tests --- packages/syft/src/syft/service/user/user_service.py | 3 +-- packages/syft/src/syft/store/document_store.py | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/syft/src/syft/service/user/user_service.py b/packages/syft/src/syft/service/user/user_service.py index fd468703190..3017b9a3892 100644 --- a/packages/syft/src/syft/service/user/user_service.py +++ b/packages/syft/src/syft/service/user/user_service.py @@ -321,9 +321,8 @@ def update( edits_non_role_attrs = any( getattr(user_update, attr) is not Empty for attr in user_update.to_dict() - if attr != "role" + if attr not in ["role", "created_date", "updated_date", "deleted_date"] ) - if ( edits_non_role_attrs and user.verify_key != context.credentials diff --git a/packages/syft/src/syft/store/document_store.py b/packages/syft/src/syft/store/document_store.py index 05dc8746add..c754c8062df 100644 --- a/packages/syft/src/syft/store/document_store.py +++ b/packages/syft/src/syft/store/document_store.py @@ -377,6 +377,8 @@ def set( add_storage_permission: bool = True, ignore_duplicates: bool = False, ) -> Result[SyftObject, str]: + if obj.created_date is None: + obj.created_date = BaseDateTime.now() return self._thread_safe_cbk( self._set, credentials=credentials, @@ -693,8 +695,6 @@ def set( # we dont use and_then logic here as it is hard because of the order of the arguments if res.is_err(): return res - if obj.created_date is None: - obj.created_date = BaseDateTime.now() res = self.partition.set( credentials=credentials, obj=obj, @@ -744,6 +744,9 @@ def query_all_kwargs( **kwargs: dict[str, Any], ) -> Result[list[BaseStash.object_type], str]: order_by = kwargs.pop("order_by", None) + created_date = kwargs.pop("created_date", None) + deleted_date = kwargs.pop("deleted_date", None) + updated_date = kwargs.pop("updated_date", None) qks = QueryKeys.from_dict(kwargs) return self.query_all(credentials=credentials, qks=qks, order_by=order_by) From 0faaa05922093253b4fb7fa90afd9df9061c99ed Mon Sep 17 00:00:00 2001 From: teo Date: Wed, 17 Jul 2024 15:17:43 +0300 Subject: [PATCH 087/117] fix tox --- packages/syft/src/syft/store/document_store.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/syft/src/syft/store/document_store.py b/packages/syft/src/syft/store/document_store.py index c754c8062df..4012bc25ca5 100644 --- a/packages/syft/src/syft/store/document_store.py +++ b/packages/syft/src/syft/store/document_store.py @@ -744,9 +744,9 @@ def query_all_kwargs( **kwargs: dict[str, Any], ) -> Result[list[BaseStash.object_type], str]: order_by = kwargs.pop("order_by", None) - created_date = kwargs.pop("created_date", None) - deleted_date = kwargs.pop("deleted_date", None) - updated_date = kwargs.pop("updated_date", None) + _ = kwargs.pop("created_date", None) + _ = kwargs.pop("deleted_date", None) + _ = kwargs.pop("updated_date", None) qks = QueryKeys.from_dict(kwargs) return self.query_all(credentials=credentials, qks=qks, order_by=order_by) From 0beede2c4f5549b6c83fa82c5eb90337f2fd711f Mon Sep 17 00:00:00 2001 From: teo Date: Wed, 17 Jul 2024 15:43:43 +0300 Subject: [PATCH 088/117] fix tests --- packages/syft/src/syft/service/user/user_service.py | 4 +++- packages/syft/src/syft/types/syft_object.py | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/syft/src/syft/service/user/user_service.py b/packages/syft/src/syft/service/user/user_service.py index 3017b9a3892..584ed6cce48 100644 --- a/packages/syft/src/syft/service/user/user_service.py +++ b/packages/syft/src/syft/service/user/user_service.py @@ -178,7 +178,9 @@ def search( page_index: int | None = 0, ) -> UserViewPage | None | list[UserView] | SyftError: kwargs = user_search.to_dict(exclude_empty=True) - + kwargs.pop("created_date") + kwargs.pop("updated_date") + kwargs.pop("deleted_date") if len(kwargs) == 0: valid_search_params = list(UserSearch.__fields__.keys()) return SyftError( diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 33a86aa5df8..661f4d1db5a 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -607,6 +607,7 @@ def syft_eq(self, ext_obj: Self | None) -> bool: attrs_to_check = self.__dict__.keys() obj_exclude_attrs = getattr(self, "__exclude_sync_diff_attrs__", []) + obj_exclude_attrs.extend(["created_date", "updated_date", "deleted_date"]) for attr in attrs_to_check: if attr not in base_attrs_sync_ignore and attr not in obj_exclude_attrs: obj_attr = getattr(self, attr) @@ -633,6 +634,7 @@ def syft_get_diffs(self, ext_obj: Self) -> list["AttrDiff"]: attrs_to_check = self.__dict__.keys() obj_exclude_attrs = getattr(self, "__exclude_sync_diff_attrs__", []) + obj_exclude_attrs.extend(["created_date", "updated_date", "deleted_date"]) for attr in attrs_to_check: if attr not in base_attrs_sync_ignore and attr not in obj_exclude_attrs: obj_attr = getattr(self, attr) From 3da044f70188468bfdcdc115148af82b4091765d Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Thu, 18 Jul 2024 12:25:36 +0800 Subject: [PATCH 089/117] Handle flaky worker deletion test --- .../local/syft_worker_deletion_test.py | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/tests/integration/local/syft_worker_deletion_test.py b/tests/integration/local/syft_worker_deletion_test.py index 6de5f0b6078..181030b1a7b 100644 --- a/tests/integration/local/syft_worker_deletion_test.py +++ b/tests/integration/local/syft_worker_deletion_test.py @@ -2,6 +2,7 @@ from collections.abc import Generator from collections.abc import Iterable from itertools import product +import operator from secrets import token_hex import time from typing import Any @@ -67,34 +68,63 @@ def matrix( return [dict(kvs) for kvs in args] -SERVER_ARGS_TEST_CASES = matrix( - n_consumers=[1], - dev_mode=[True, False], - thread_workers=[True, False], -) +SERVER_ARGS_TEST_CASES = { + "n_consumers": [1], + "dev_mode": [True, False], + "thread_workers": [True, False], +} + + +class FlakyMark(RuntimeError): + """To mark a flaky part of a test to use with @pytest.mark.flaky""" + pass -@pytest.mark.parametrize("server_args", SERVER_ARGS_TEST_CASES) + +@pytest.mark.flaky(reruns=3, rerun_delay=1, only_rerun=["FlakyMark"]) +@pytest.mark.parametrize( + "server_args", + matrix( + **{**SERVER_ARGS_TEST_CASES, "n_consumers": [3]}, + ), +) @pytest.mark.parametrize("force", [True, False]) -def test_delete_idle_worker(server: ServerHandle, force: bool) -> None: +def test_delete_idle_worker( + server: ServerHandle, force: bool, server_args: dict[str, Any] +) -> None: client = server.login(email="info@openmined.org", password="changethis") - worker = client.worker.get_all()[0] - res = client.worker.delete(worker.id, force=force) + original_workers = client.worker.get_all() + worker_to_delete = max(original_workers, key=operator.attrgetter("name")) + + res = client.worker.delete(worker_to_delete.id, force=force) assert not isinstance(res, SyftError) if force: - assert len(client.worker.get_all()) == 0 + assert ( + len(workers := client.worker.get_all()) == len(original_workers) - 1 + and all(w.id != worker_to_delete.id for w in workers) + ), f"{workers.message=} {server_args=} {[(w.id, w.name) for w in original_workers]}" + return start = time.time() while True: - if len(client.worker.get_all()) == 0: + workers = client.worker.get_all() + if isinstance(workers, SyftError): + raise FlakyMark( + f"`workers = client.worker.get_all()` failed.\n" + f"{workers.message=} {server_args=} {[(w.id, w.name) for w in original_workers]}" + ) + + if len(workers) == len(original_workers) - 1 and all( + w.id != worker_to_delete.id for w in workers + ): break if time.time() - start > 3: raise TimeoutError("Worker did not get removed from stash.") -@pytest.mark.parametrize("server_args", SERVER_ARGS_TEST_CASES) +@pytest.mark.parametrize("server_args", matrix(**SERVER_ARGS_TEST_CASES)) @pytest.mark.parametrize("force", [True, False]) def test_delete_worker(server: ServerHandle, force: bool) -> None: client = server.login(email="info@openmined.org", password="changethis") From d5b261df37be55e9e7cfedc54abbf4a342e2ff86 Mon Sep 17 00:00:00 2001 From: alfred-openmined-bot <145415986+alfred-openmined-bot@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:05:16 +0000 Subject: [PATCH 090/117] bump protocol and remove notebooks --- packages/syft/src/syft/protocol/protocol_version.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index 4b64e99064c..1b5f6f9afcb 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -368,7 +368,7 @@ "Dataset": { "1": { "version": 1, - "hash": "3be049e4f3d423699ba5d7c2d1f60b2b11c0c6691b505e1c6100a743a7398665", + "hash": "0ca6b0b4a3aebb2c8f351668075b44951bb20d1e23a779b82109124f334ce3a4", "action": "add" } }, @@ -382,7 +382,7 @@ "CreateDataset": { "1": { "version": 1, - "hash": "3f9cdbf797ca0ed7b1c95ffb50cb696b1127ac8b80438dbb517561c5992a6ba9", + "hash": "7e02dfa89540c3dbebacbb13810d95cdc4e36db31d56cffed7ab54abe25716c9", "action": "add" } }, From c585c9098ccc39d9706227c0e14d953a454410b5 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Thu, 18 Jul 2024 15:03:44 +0530 Subject: [PATCH 091/117] bump to stable version 0.8.7 --- .bumpversion.cfg | 2 +- .bumpversion_stable.cfg | 2 +- VERSION | 2 +- packages/grid/VERSION | 2 +- packages/grid/backend/grid/images/worker_cpu.dockerfile | 2 +- packages/grid/devspace.yaml | 2 +- packages/grid/frontend/package.json | 2 +- packages/grid/helm/syft/Chart.yaml | 4 ++-- packages/grid/helm/syft/values.yaml | 2 +- packages/syft/setup.cfg | 2 +- packages/syft/src/syft/VERSION | 2 +- packages/syft/src/syft/__init__.py | 2 +- packages/syft/src/syft/stable_version.py | 2 +- packages/syftcli/manifest.yml | 8 ++++---- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index e146a7c8c8b..8259ef220b8 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.7-beta.14 +current_version = 0.8.7 tag = False tag_name = {new_version} commit = True diff --git a/.bumpversion_stable.cfg b/.bumpversion_stable.cfg index 52b011ac7b1..4ed947e8dd6 100644 --- a/.bumpversion_stable.cfg +++ b/.bumpversion_stable.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.6 +current_version = 0.8.7 tag = False tag_name = {new_version} commit = True diff --git a/VERSION b/VERSION index 0c01f370f55..689e705e14c 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.14" +__version__ = "0.8.7" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/VERSION b/packages/grid/VERSION index 0c01f370f55..689e705e14c 100644 --- a/packages/grid/VERSION +++ b/packages/grid/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.14" +__version__ = "0.8.7" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/backend/grid/images/worker_cpu.dockerfile b/packages/grid/backend/grid/images/worker_cpu.dockerfile index a873bbead6d..16dd6a25499 100644 --- a/packages/grid/backend/grid/images/worker_cpu.dockerfile +++ b/packages/grid/backend/grid/images/worker_cpu.dockerfile @@ -5,7 +5,7 @@ # NOTE: This dockerfile will be built inside a syft-backend container in PROD # Hence COPY will not work the same way in DEV vs. PROD -ARG SYFT_VERSION_TAG="0.8.7-beta.14" +ARG SYFT_VERSION_TAG="0.8.7" FROM openmined/syft-backend:${SYFT_VERSION_TAG} # should match base image python version diff --git a/packages/grid/devspace.yaml b/packages/grid/devspace.yaml index 7920791b541..6855edffe54 100644 --- a/packages/grid/devspace.yaml +++ b/packages/grid/devspace.yaml @@ -28,7 +28,7 @@ vars: DOCKER_IMAGE_RATHOLE: openmined/syft-rathole DOCKER_IMAGE_ENCLAVE_ATTESTATION: openmined/syft-enclave-attestation CONTAINER_REGISTRY: "docker.io" - VERSION: "0.8.7-beta.14" + VERSION: "0.8.7" PLATFORM: $(uname -m | grep -q 'arm64' && echo "arm64" || echo "amd64") # This is a list of `images` that DevSpace can build for this project diff --git a/packages/grid/frontend/package.json b/packages/grid/frontend/package.json index 180462c5d6f..db69dc97b53 100644 --- a/packages/grid/frontend/package.json +++ b/packages/grid/frontend/package.json @@ -1,6 +1,6 @@ { "name": "syft-ui", - "version": "0.8.7-beta.14", + "version": "0.8.7", "private": true, "scripts": { "dev": "pnpm i && vite dev --host --port 80", diff --git a/packages/grid/helm/syft/Chart.yaml b/packages/grid/helm/syft/Chart.yaml index 7ebe62c3364..8c10e70d217 100644 --- a/packages/grid/helm/syft/Chart.yaml +++ b/packages/grid/helm/syft/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: syft description: Perform numpy-like analysis on data that remains in someone elses server type: application -version: "0.8.7-beta.14" -appVersion: "0.8.7-beta.14" +version: "0.8.7" +appVersion: "0.8.7" home: https://github.com/OpenMined/PySyft/ icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png diff --git a/packages/grid/helm/syft/values.yaml b/packages/grid/helm/syft/values.yaml index 48bb41fa11a..c2437c45ea1 100644 --- a/packages/grid/helm/syft/values.yaml +++ b/packages/grid/helm/syft/values.yaml @@ -1,7 +1,7 @@ global: # Affects only backend, frontend, and seaweedfs containers registry: docker.io - version: 0.8.7-beta.14 + version: 0.8.7 # Force default secret values for development. DO NOT SET THIS TO FALSE IN PRODUCTION randomizedSecrets: true diff --git a/packages/syft/setup.cfg b/packages/syft/setup.cfg index 9ee693855b2..222735cfefb 100644 --- a/packages/syft/setup.cfg +++ b/packages/syft/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = syft -version = attr: "0.8.7-beta.14" +version = attr: "0.8.7" description = Perform numpy-like analysis on data that remains in someone elses server author = OpenMined author_email = info@openmined.org diff --git a/packages/syft/src/syft/VERSION b/packages/syft/src/syft/VERSION index 0c01f370f55..689e705e14c 100644 --- a/packages/syft/src/syft/VERSION +++ b/packages/syft/src/syft/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.14" +__version__ = "0.8.7" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index d61d8de882f..238d7dc27ee 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.8.7-beta.14" +__version__ = "0.8.7" # stdlib from collections.abc import Callable diff --git a/packages/syft/src/syft/stable_version.py b/packages/syft/src/syft/stable_version.py index d596aae77cd..abd01cb6bdf 100644 --- a/packages/syft/src/syft/stable_version.py +++ b/packages/syft/src/syft/stable_version.py @@ -1 +1 @@ -LATEST_STABLE_SYFT = "0.8.6" +LATEST_STABLE_SYFT = "0.8.7" diff --git a/packages/syftcli/manifest.yml b/packages/syftcli/manifest.yml index be37bbf6f71..48f44e9bf0d 100644 --- a/packages/syftcli/manifest.yml +++ b/packages/syftcli/manifest.yml @@ -1,11 +1,11 @@ manifestVersion: 1.0 -syftVersion: 0.8.7-beta.14 -dockerTag: 0.8.7-beta.14 +syftVersion: 0.8.7 +dockerTag: 0.8.7 images: - - docker.io/openmined/syft-frontend:0.8.7-beta.14 - - docker.io/openmined/syft-backend:0.8.7-beta.14 + - docker.io/openmined/syft-frontend:0.8.7 + - docker.io/openmined/syft-backend:0.8.7 - docker.io/library/mongo:7.0.4 - docker.io/traefik:v2.11.0 From d6824866cf51069fda2e9edfba52ba382a3e5006 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Thu, 18 Jul 2024 15:04:33 +0530 Subject: [PATCH 092/117] disable backend.test.basecpu --- .github/workflows/pr-tests-stack.yml | 10 +++++----- README.md | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr-tests-stack.yml b/.github/workflows/pr-tests-stack.yml index 458092a16c5..cc570615272 100644 --- a/.github/workflows/pr-tests-stack.yml +++ b/.github/workflows/pr-tests-stack.yml @@ -56,11 +56,11 @@ jobs: pip install uv==0.2.17 tox tox-uv==1.9.0 uv --version - - name: Run syft backend base image building test - if: steps.changes.outputs.stack == 'true' - timeout-minutes: 60 - run: | - tox -e backend.test.basecpu + # - name: Run syft backend base image building test + # if: steps.changes.outputs.stack == 'true' + # timeout-minutes: 60 + # run: | + # tox -e backend.test.basecpu pr-tests-syft-integration: strategy: diff --git a/README.md b/README.md index 2d437486896..b89130201c7 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ $ pip install -U syft[data_science] ```python # from Jupyter / Python import syft as sy -sy.requires(">=0.8.6,<0.8.7") +sy.requires(">=0.8.7,<0.8.8") server = sy.orchestra.launch( name="my-datasite", port=8080, @@ -146,11 +146,12 @@ helm install ... --set ingress.class="gce" # Versions `0.9.0` - Coming soon... -`0.8.7` (Beta) - `dev` branch 👈🏽 API - Coming soon... -`0.8.6` (Stable) - API +`0.8.8` (Beta) - `dev` branch 👈🏽 API - Coming soon... +`0.8.7` (Stable) - API Deprecated: +- `0.8.6` - API - `0.8.5-post.2` - API - `0.8.4` - API - `0.8.3` - API From 4a32da7c8078d1f558bc5f4c7389e046f9d7fa41 Mon Sep 17 00:00:00 2001 From: alfred-openmined-bot <145415986+alfred-openmined-bot@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:46:11 +0000 Subject: [PATCH 093/117] [syft]bump version --- .bumpversion.cfg | 2 +- VERSION | 2 +- packages/grid/VERSION | 2 +- .../backend/grid/images/worker_cpu.dockerfile | 2 +- packages/grid/devspace.yaml | 2 +- packages/grid/frontend/package.json | 2 +- packages/grid/helm/repo/index.yaml | 191 +-- .../grid/helm/repo/syft-0.8.7-beta.15.tgz | Bin 0 -> 18043 bytes packages/grid/helm/syft/Chart.yaml | 4 +- packages/grid/helm/syft/templates/NOTES.txt | 1082 +++++++---------- packages/grid/helm/syft/values.yaml | 2 +- packages/syft/setup.cfg | 2 +- packages/syft/src/syft/VERSION | 2 +- packages/syft/src/syft/__init__.py | 2 +- packages/syftcli/manifest.yml | 8 +- 15 files changed, 589 insertions(+), 716 deletions(-) create mode 100644 packages/grid/helm/repo/syft-0.8.7-beta.15.tgz diff --git a/.bumpversion.cfg b/.bumpversion.cfg index e146a7c8c8b..b503c8bb0f2 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.7-beta.14 +current_version = 0.8.7-beta.15 tag = False tag_name = {new_version} commit = True diff --git a/VERSION b/VERSION index 0c01f370f55..27f3763909a 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.14" +__version__ = "0.8.7-beta.15" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/VERSION b/packages/grid/VERSION index 0c01f370f55..27f3763909a 100644 --- a/packages/grid/VERSION +++ b/packages/grid/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.14" +__version__ = "0.8.7-beta.15" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/backend/grid/images/worker_cpu.dockerfile b/packages/grid/backend/grid/images/worker_cpu.dockerfile index a873bbead6d..179dc4fa70f 100644 --- a/packages/grid/backend/grid/images/worker_cpu.dockerfile +++ b/packages/grid/backend/grid/images/worker_cpu.dockerfile @@ -5,7 +5,7 @@ # NOTE: This dockerfile will be built inside a syft-backend container in PROD # Hence COPY will not work the same way in DEV vs. PROD -ARG SYFT_VERSION_TAG="0.8.7-beta.14" +ARG SYFT_VERSION_TAG="0.8.7-beta.15" FROM openmined/syft-backend:${SYFT_VERSION_TAG} # should match base image python version diff --git a/packages/grid/devspace.yaml b/packages/grid/devspace.yaml index 7920791b541..7c7f125feec 100644 --- a/packages/grid/devspace.yaml +++ b/packages/grid/devspace.yaml @@ -28,7 +28,7 @@ vars: DOCKER_IMAGE_RATHOLE: openmined/syft-rathole DOCKER_IMAGE_ENCLAVE_ATTESTATION: openmined/syft-enclave-attestation CONTAINER_REGISTRY: "docker.io" - VERSION: "0.8.7-beta.14" + VERSION: "0.8.7-beta.15" PLATFORM: $(uname -m | grep -q 'arm64' && echo "arm64" || echo "amd64") # This is a list of `images` that DevSpace can build for this project diff --git a/packages/grid/frontend/package.json b/packages/grid/frontend/package.json index 180462c5d6f..f0abfb28bee 100644 --- a/packages/grid/frontend/package.json +++ b/packages/grid/frontend/package.json @@ -1,6 +1,6 @@ { "name": "syft-ui", - "version": "0.8.7-beta.14", + "version": "0.8.7-beta.15", "private": true, "scripts": { "dev": "pnpm i && vite dev --host --port 80", diff --git a/packages/grid/helm/repo/index.yaml b/packages/grid/helm/repo/index.yaml index 088ca146c2c..a34bf857801 100644 --- a/packages/grid/helm/repo/index.yaml +++ b/packages/grid/helm/repo/index.yaml @@ -1,9 +1,22 @@ apiVersion: v1 entries: syft: + - apiVersion: v2 + appVersion: 0.8.7-beta.15 + created: "2024-07-18T09:44:18.697011581Z" + description: Perform numpy-like analysis on data that remains in someone elses + server + digest: 56879d9a9f10febce88676d3d20621d74d17f9e33f5df6ae1e9bc3078c216f0c + home: https://github.com/OpenMined/PySyft/ + icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png + name: syft + type: application + urls: + - https://openmined.github.io/PySyft/helm/syft-0.8.7-beta.15.tgz + version: 0.8.7-beta.15 - apiVersion: v2 appVersion: 0.8.7-beta.14 - created: "2024-07-14T12:48:16.383106715Z" + created: "2024-07-18T09:44:18.696136502Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e7cbca1d603ba11e09ae2a3089cfdafaa08cfa07c553c4f0fb8b42f8d3028f7 @@ -16,7 +29,7 @@ entries: version: 0.8.7-beta.14 - apiVersion: v2 appVersion: 0.8.7-beta.13 - created: "2024-07-14T12:48:16.381397481Z" + created: "2024-07-18T09:44:18.695250653Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1dbe3ecdfec57bf25020cbcff783fab908f0eb0640ad684470b2fd1da1928005 @@ -29,7 +42,7 @@ entries: version: 0.8.7-beta.13 - apiVersion: v2 appVersion: 0.8.7-beta.12 - created: "2024-07-14T12:48:16.380688282Z" + created: "2024-07-18T09:44:18.694546535Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e92b2f3a522dabb3a79ff762a7042ae16d2bf3a53eebbb2885a69b9f834d109c @@ -42,7 +55,7 @@ entries: version: 0.8.7-beta.12 - apiVersion: v2 appVersion: 0.8.7-beta.11 - created: "2024-07-14T12:48:16.379990154Z" + created: "2024-07-18T09:44:18.693800357Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 099f6cbd44b699ee2410a4be012ed1a8a65bcacb06a43057b2779d7fe34fc0ad @@ -55,7 +68,7 @@ entries: version: 0.8.7-beta.11 - apiVersion: v2 appVersion: 0.8.7-beta.10 - created: "2024-07-14T12:48:16.379291705Z" + created: "2024-07-18T09:44:18.693068297Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 00773cb241522e281c1915339fc362e047650e08958a736e93d6539f44cb5e25 @@ -68,7 +81,7 @@ entries: version: 0.8.7-beta.10 - apiVersion: v2 appVersion: 0.8.7-beta.9 - created: "2024-07-14T12:48:16.388267418Z" + created: "2024-07-18T09:44:18.703118454Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a3f8e85d9ddef7a644b959fcc2fcb0fc08f7b6abae1045e893d0d62fa4ae132e @@ -81,7 +94,7 @@ entries: version: 0.8.7-beta.9 - apiVersion: v2 appVersion: 0.8.7-beta.8 - created: "2024-07-14T12:48:16.387623261Z" + created: "2024-07-18T09:44:18.70245435Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a422ac88d8fd1fb80d5004d5eb6e95fa9efc7f6a87da12e5ac04829da7f04c4d @@ -94,7 +107,7 @@ entries: version: 0.8.7-beta.8 - apiVersion: v2 appVersion: 0.8.7-beta.7 - created: "2024-07-14T12:48:16.386972992Z" + created: "2024-07-18T09:44:18.701730695Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0dc313a1092e6256a7c8aad002c8ec380b3add2c289d680db1e238a336399b7a @@ -107,7 +120,7 @@ entries: version: 0.8.7-beta.7 - apiVersion: v2 appVersion: 0.8.7-beta.6 - created: "2024-07-14T12:48:16.386341078Z" + created: "2024-07-18T09:44:18.700741185Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 052a2ec1102d2a4c9915f95647abd4a6012f56fa05a106f4952ee9b55bf7bae8 @@ -120,7 +133,7 @@ entries: version: 0.8.7-beta.6 - apiVersion: v2 appVersion: 0.8.7-beta.5 - created: "2024-07-14T12:48:16.385692963Z" + created: "2024-07-18T09:44:18.699545536Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1728af756907c3fcbe87c2fd2de014a2d963c22a4c2eb6af6596b525a9b9a18a @@ -133,7 +146,7 @@ entries: version: 0.8.7-beta.5 - apiVersion: v2 appVersion: 0.8.7-beta.4 - created: "2024-07-14T12:48:16.385048795Z" + created: "2024-07-18T09:44:18.698909676Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 387a57a3904a05ed61e92ee48605ef6fd5044ff7e822e0924e0d4c485e2c88d2 @@ -146,7 +159,7 @@ entries: version: 0.8.7-beta.4 - apiVersion: v2 appVersion: 0.8.7-beta.3 - created: "2024-07-14T12:48:16.384413735Z" + created: "2024-07-18T09:44:18.698278614Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 3668002b7a4118516b2ecd61d6275f60d83fc12841587ab8f62e1c1200731c67 @@ -159,7 +172,7 @@ entries: version: 0.8.7-beta.3 - apiVersion: v2 appVersion: 0.8.7-beta.2 - created: "2024-07-14T12:48:16.383772393Z" + created: "2024-07-18T09:44:18.697608639Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e62217ffcadee2b8896ab0543f9ccc42f2df898fd979438ac9376d780b802af7 @@ -172,7 +185,7 @@ entries: version: 0.8.7-beta.2 - apiVersion: v2 appVersion: 0.8.7-beta.1 - created: "2024-07-14T12:48:16.378617882Z" + created: "2024-07-18T09:44:18.691587681Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 553981fe1d5c980e6903b3ff2f1b9b97431f6dd8aee91e3976bcc5594285235e @@ -185,7 +198,7 @@ entries: version: 0.8.7-beta.1 - apiVersion: v2 appVersion: 0.8.6 - created: "2024-07-14T12:48:16.378070285Z" + created: "2024-07-18T09:44:18.691075221Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ddbbe6fea1702e57404875eb3019a3b1a341017bdbb5fbc6ce418507e5c15756 @@ -198,7 +211,7 @@ entries: version: 0.8.6 - apiVersion: v2 appVersion: 0.8.6-beta.1 - created: "2024-07-14T12:48:16.377535653Z" + created: "2024-07-18T09:44:18.690541181Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: cc2c81ef6796ac853dce256e6bf8a6af966c21803e6534ea21920af681c62e61 @@ -211,7 +224,7 @@ entries: version: 0.8.6-beta.1 - apiVersion: v2 appVersion: 0.8.5 - created: "2024-07-14T12:48:16.376992826Z" + created: "2024-07-18T09:44:18.689971183Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: db5d90d44006209fd5ecdebd88f5fd56c70f7c76898343719a0ff8da46da948a @@ -224,7 +237,7 @@ entries: version: 0.8.5 - apiVersion: v2 appVersion: 0.8.5-post.2 - created: "2024-07-14T12:48:16.376231799Z" + created: "2024-07-18T09:44:18.689218985Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ea3f7269b55f773fa165d7008c054b7cf3ec4c62eb40a96f08cd3a9b77fd2165 @@ -237,7 +250,7 @@ entries: version: 0.8.5-post.2 - apiVersion: v2 appVersion: 0.8.5-post.1 - created: "2024-07-14T12:48:16.37568788Z" + created: "2024-07-18T09:44:18.688684404Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9deb844d3dc2d8480c60f8c631dcc7794adfb39cec3aa3b1ce22ea26fdf87d02 @@ -250,7 +263,7 @@ entries: version: 0.8.5-post.1 - apiVersion: v2 appVersion: 0.8.5-beta.10 - created: "2024-07-14T12:48:16.368097513Z" + created: "2024-07-18T09:44:18.681146757Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9cfe01e8f57eca462261a24a805b41509be2de9a0fee76e331d124ed98c4bc49 @@ -263,7 +276,7 @@ entries: version: 0.8.5-beta.10 - apiVersion: v2 appVersion: 0.8.5-beta.9 - created: "2024-07-14T12:48:16.374916865Z" + created: "2024-07-18T09:44:18.68792915Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 057f1733f2bc966e15618f62629315c8207773ef6211c79c4feb557dae15c32b @@ -276,7 +289,7 @@ entries: version: 0.8.5-beta.9 - apiVersion: v2 appVersion: 0.8.5-beta.8 - created: "2024-07-14T12:48:16.373739578Z" + created: "2024-07-18T09:44:18.687168595Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 921cbce836c3032ef62b48cc82b5b4fcbe44fb81d473cf4d69a4bf0f806eb298 @@ -289,7 +302,7 @@ entries: version: 0.8.5-beta.8 - apiVersion: v2 appVersion: 0.8.5-beta.7 - created: "2024-07-14T12:48:16.372756916Z" + created: "2024-07-18T09:44:18.686406458Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 75482e955b2b9853a80bd653afb1d56535f78f3bfb7726798522307eb3effbbd @@ -302,7 +315,7 @@ entries: version: 0.8.5-beta.7 - apiVersion: v2 appVersion: 0.8.5-beta.6 - created: "2024-07-14T12:48:16.371971694Z" + created: "2024-07-18T09:44:18.685605628Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6a2dfaf65ca855e1b3d7b966d4ff291e6fcbe761e2fc2a78033211ccd3a75de0 @@ -315,7 +328,7 @@ entries: version: 0.8.5-beta.6 - apiVersion: v2 appVersion: 0.8.5-beta.5 - created: "2024-07-14T12:48:16.371178147Z" + created: "2024-07-18T09:44:18.68424052Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fead03823bef04d66901d563aa755c68ab277f72b126aaa6f0dce76a6f3bdb6d @@ -328,7 +341,7 @@ entries: version: 0.8.5-beta.5 - apiVersion: v2 appVersion: 0.8.5-beta.4 - created: "2024-07-14T12:48:16.370401542Z" + created: "2024-07-18T09:44:18.683483723Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 93e4539d5726a7fd0d6a3e93d1c17c6a358a923ddc01d102eab22f37377502ab @@ -341,7 +354,7 @@ entries: version: 0.8.5-beta.4 - apiVersion: v2 appVersion: 0.8.5-beta.3 - created: "2024-07-14T12:48:16.369609467Z" + created: "2024-07-18T09:44:18.682699174Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: f91e9390edf3441469048f5da646099af98f8b6d199409d0e2c1e6da3a51f054 @@ -354,7 +367,7 @@ entries: version: 0.8.5-beta.3 - apiVersion: v2 appVersion: 0.8.5-beta.2 - created: "2024-07-14T12:48:16.368859942Z" + created: "2024-07-18T09:44:18.681900047Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 59159c3aa4888038edc3c0135c83402363d7a0639fe62966a1e9d4928a364fa8 @@ -367,7 +380,7 @@ entries: version: 0.8.5-beta.2 - apiVersion: v2 appVersion: 0.8.5-beta.1 - created: "2024-07-14T12:48:16.36732211Z" + created: "2024-07-18T09:44:18.680370022Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 65aeb74c52ed8ba5474af500b4c1188a570ee4cb1f2a2da356b3488d28356ed9 @@ -379,7 +392,7 @@ entries: version: 0.8.5-beta.1 - apiVersion: v2 appVersion: 0.8.4 - created: "2024-07-14T12:48:16.366927711Z" + created: "2024-07-18T09:44:18.679989029Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 08afea8e3a9eef225b7e611f0bc1216c140053ef8e51439b02337faeac621fd0 @@ -391,7 +404,7 @@ entries: version: 0.8.4 - apiVersion: v2 appVersion: 0.8.4-beta.31 - created: "2024-07-14T12:48:16.363695182Z" + created: "2024-07-18T09:44:18.676732507Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fabf3e2f37e53fa623f5d3d99b00feae06e278e5cd63bce419089946312ab1fc @@ -403,7 +416,7 @@ entries: version: 0.8.4-beta.31 - apiVersion: v2 appVersion: 0.8.4-beta.30 - created: "2024-07-14T12:48:16.363285764Z" + created: "2024-07-18T09:44:18.676317329Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e8f792709f73ec14eab48a268bdf50a4505b340bd142cddd7c7bfffd94009ad @@ -415,7 +428,7 @@ entries: version: 0.8.4-beta.30 - apiVersion: v2 appVersion: 0.8.4-beta.29 - created: "2024-07-14T12:48:16.362505462Z" + created: "2024-07-18T09:44:18.675503365Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 4c985d6a9b3456769c4013f9e85e7374c0f963d2d27627e61f914f5537de1971 @@ -427,7 +440,7 @@ entries: version: 0.8.4-beta.29 - apiVersion: v2 appVersion: 0.8.4-beta.28 - created: "2024-07-14T12:48:16.361966622Z" + created: "2024-07-18T09:44:18.67509477Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: bd2aa3c92c768c47c502e31a326f341addcb34e64d22cdcbf5cc3f19689d859c @@ -439,7 +452,7 @@ entries: version: 0.8.4-beta.28 - apiVersion: v2 appVersion: 0.8.4-beta.27 - created: "2024-07-14T12:48:16.361557665Z" + created: "2024-07-18T09:44:18.674682568Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e8ad0869993af39d7adda8cb868dc0b24cfb63b4bb9820dc579939c1007a60ba @@ -451,7 +464,7 @@ entries: version: 0.8.4-beta.27 - apiVersion: v2 appVersion: 0.8.4-beta.26 - created: "2024-07-14T12:48:16.361149991Z" + created: "2024-07-18T09:44:18.67426697Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 30dccf630aa25a86a03c67572fe5411687d8ce6d58def448ea10efdba2b85e3a @@ -463,7 +476,7 @@ entries: version: 0.8.4-beta.26 - apiVersion: v2 appVersion: 0.8.4-beta.25 - created: "2024-07-14T12:48:16.360740353Z" + created: "2024-07-18T09:44:18.673810786Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b6e2043bcf5a0335967d770c7939f5a7832955359a7d871c90b265660ff26e5f @@ -475,7 +488,7 @@ entries: version: 0.8.4-beta.25 - apiVersion: v2 appVersion: 0.8.4-beta.24 - created: "2024-07-14T12:48:16.360330315Z" + created: "2024-07-18T09:44:18.673400587Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b19efa95394d50bb8d76da6ec306de5d3bb9ea55371fafea95a1282a697fa33e @@ -487,7 +500,7 @@ entries: version: 0.8.4-beta.24 - apiVersion: v2 appVersion: 0.8.4-beta.23 - created: "2024-07-14T12:48:16.359913894Z" + created: "2024-07-18T09:44:18.672990299Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 5c5d05c15bff548574896118ce92335ae10c5b78f5307fe9b2618e5a5aa71a5c @@ -499,7 +512,7 @@ entries: version: 0.8.4-beta.23 - apiVersion: v2 appVersion: 0.8.4-beta.22 - created: "2024-07-14T12:48:16.359493016Z" + created: "2024-07-18T09:44:18.672570453Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0160dbce938198132ca9cd2a5cb362816344687291f5b6d7cf6de8f2855e9414 @@ -511,7 +524,7 @@ entries: version: 0.8.4-beta.22 - apiVersion: v2 appVersion: 0.8.4-beta.21 - created: "2024-07-14T12:48:16.35904211Z" + created: "2024-07-18T09:44:18.672145167Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7dce153d2fcae7513e9c132e139b2721fd975ea3cc43a370e34dbeb2a1b7f683 @@ -523,7 +536,7 @@ entries: version: 0.8.4-beta.21 - apiVersion: v2 appVersion: 0.8.4-beta.20 - created: "2024-07-14T12:48:16.35791944Z" + created: "2024-07-18T09:44:18.671692649Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c51189a187bbf24135382e25cb00964e0330dfcd3b2f0c884581a6686f05dd28 @@ -535,7 +548,7 @@ entries: version: 0.8.4-beta.20 - apiVersion: v2 appVersion: 0.8.4-beta.19 - created: "2024-07-14T12:48:16.356942108Z" + created: "2024-07-18T09:44:18.670359287Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 8219575dedb42fa2ddbf2768a4e9afbfacbc2dff7e953d77c7b10a41b78dc687 @@ -547,7 +560,7 @@ entries: version: 0.8.4-beta.19 - apiVersion: v2 appVersion: 0.8.4-beta.18 - created: "2024-07-14T12:48:16.35653782Z" + created: "2024-07-18T09:44:18.669451207Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6418cde559cf12f1f7fea5a2b123bba950e50eeb3be002441827d2ab7f9e4ef7 @@ -559,7 +572,7 @@ entries: version: 0.8.4-beta.18 - apiVersion: v2 appVersion: 0.8.4-beta.16 - created: "2024-07-14T12:48:16.356130817Z" + created: "2024-07-18T09:44:18.669046489Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9c9840a7c9476dbb08e0ac83926330718fe50c89879752dd8f92712b036109c0 @@ -571,7 +584,7 @@ entries: version: 0.8.4-beta.16 - apiVersion: v2 appVersion: 0.8.4-beta.15 - created: "2024-07-14T12:48:16.355727852Z" + created: "2024-07-18T09:44:18.668638194Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0955fd22da028315e30c68132cbfa4bdc82bae622039bcfce0de339707bb82eb @@ -583,7 +596,7 @@ entries: version: 0.8.4-beta.15 - apiVersion: v2 appVersion: 0.8.4-beta.14 - created: "2024-07-14T12:48:16.355327231Z" + created: "2024-07-18T09:44:18.668233817Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 56208571956abe20ed7a5cc1867cab2667ed792c63e53d0e8bb70a9b438b7bf6 @@ -595,7 +608,7 @@ entries: version: 0.8.4-beta.14 - apiVersion: v2 appVersion: 0.8.4-beta.13 - created: "2024-07-14T12:48:16.354975542Z" + created: "2024-07-18T09:44:18.667883421Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: d7222c72412b6ee5833fbb07d2549be179cdfc7ccd89e0ad947d112fce799b83 @@ -607,7 +620,7 @@ entries: version: 0.8.4-beta.13 - apiVersion: v2 appVersion: 0.8.4-beta.12 - created: "2024-07-14T12:48:16.354626367Z" + created: "2024-07-18T09:44:18.667534357Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: af08c723756e397962b2d5190dedfd50797b771c5caf58b93a6f65d8fa24785c @@ -619,7 +632,7 @@ entries: version: 0.8.4-beta.12 - apiVersion: v2 appVersion: 0.8.4-beta.11 - created: "2024-07-14T12:48:16.354267935Z" + created: "2024-07-18T09:44:18.66718891Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a0235835ba57d185a83dd8a26281fa37b2077c3a37fe3a1c50585005695927e3 @@ -631,7 +644,7 @@ entries: version: 0.8.4-beta.11 - apiVersion: v2 appVersion: 0.8.4-beta.10 - created: "2024-07-14T12:48:16.353886641Z" + created: "2024-07-18T09:44:18.66684728Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 910ddfeba0c5e66651500dd11404afff092adc0f768ed68e0d93b04b83aa4388 @@ -643,7 +656,7 @@ entries: version: 0.8.4-beta.10 - apiVersion: v2 appVersion: 0.8.4-beta.9 - created: "2024-07-14T12:48:16.366311125Z" + created: "2024-07-18T09:44:18.679575695Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c25ca8a9f072d6a5d02232448deaef5668aca05f24dfffbba3ebe30a4f75bb26 @@ -655,7 +668,7 @@ entries: version: 0.8.4-beta.9 - apiVersion: v2 appVersion: 0.8.4-beta.8 - created: "2024-07-14T12:48:16.365397803Z" + created: "2024-07-18T09:44:18.679234355Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7249a39d4137e457b369384ba0a365c271c780d93a8327ce25083df763c39999 @@ -667,7 +680,7 @@ entries: version: 0.8.4-beta.8 - apiVersion: v2 appVersion: 0.8.4-beta.7 - created: "2024-07-14T12:48:16.36505446Z" + created: "2024-07-18T09:44:18.67888997Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ee750c7c8d6ea05bd447375e624fdd7f66dd87680ab81f7b7e73df7379a9024a @@ -679,7 +692,7 @@ entries: version: 0.8.4-beta.7 - apiVersion: v2 appVersion: 0.8.4-beta.6 - created: "2024-07-14T12:48:16.364708601Z" + created: "2024-07-18T09:44:18.678543091Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0e046be9f73df7444a995608c59af16fab9030b139b2acb4d6db6185b8eb5337 @@ -691,7 +704,7 @@ entries: version: 0.8.4-beta.6 - apiVersion: v2 appVersion: 0.8.4-beta.5 - created: "2024-07-14T12:48:16.364373513Z" + created: "2024-07-18T09:44:18.678176314Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b56e9a23d46810eccdb4cf5272cc05126da3f6db314e541959c3efb5f260620b @@ -703,7 +716,7 @@ entries: version: 0.8.4-beta.5 - apiVersion: v2 appVersion: 0.8.4-beta.4 - created: "2024-07-14T12:48:16.364035099Z" + created: "2024-07-18T09:44:18.677468375Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1d5808ecaf55391f3b27ae6236400066508acbd242e33db24a1ab4bffa77409e @@ -715,7 +728,7 @@ entries: version: 0.8.4-beta.4 - apiVersion: v2 appVersion: 0.8.4-beta.3 - created: "2024-07-14T12:48:16.362874744Z" + created: "2024-07-18T09:44:18.675859813Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b64efa8529d82be56c6ab60487ed24420a5614d96d2509c1f93c1003eda71a54 @@ -727,7 +740,7 @@ entries: version: 0.8.4-beta.3 - apiVersion: v2 appVersion: 0.8.4-beta.2 - created: "2024-07-14T12:48:16.357497218Z" + created: "2024-07-18T09:44:18.671234101Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -743,7 +756,7 @@ entries: version: 0.8.4-beta.2 - apiVersion: v2 appVersion: 0.8.4-beta.1 - created: "2024-07-14T12:48:16.353530804Z" + created: "2024-07-18T09:44:18.666492967Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -759,7 +772,7 @@ entries: version: 0.8.4-beta.1 - apiVersion: v2 appVersion: 0.8.3 - created: "2024-07-14T12:48:16.352961928Z" + created: "2024-07-18T09:44:18.665903122Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -775,7 +788,7 @@ entries: version: 0.8.3 - apiVersion: v2 appVersion: 0.8.3-beta.6 - created: "2024-07-14T12:48:16.351935353Z" + created: "2024-07-18T09:44:18.665238668Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -791,7 +804,7 @@ entries: version: 0.8.3-beta.6 - apiVersion: v2 appVersion: 0.8.3-beta.5 - created: "2024-07-14T12:48:16.35102644Z" + created: "2024-07-18T09:44:18.664634707Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -807,7 +820,7 @@ entries: version: 0.8.3-beta.5 - apiVersion: v2 appVersion: 0.8.3-beta.4 - created: "2024-07-14T12:48:16.350416717Z" + created: "2024-07-18T09:44:18.663644077Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -823,7 +836,7 @@ entries: version: 0.8.3-beta.4 - apiVersion: v2 appVersion: 0.8.3-beta.2 - created: "2024-07-14T12:48:16.34971405Z" + created: "2024-07-18T09:44:18.662603789Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -839,7 +852,7 @@ entries: version: 0.8.3-beta.2 - apiVersion: v2 appVersion: 0.8.3-beta.1 - created: "2024-07-14T12:48:16.349167956Z" + created: "2024-07-18T09:44:18.662014215Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -855,7 +868,7 @@ entries: version: 0.8.3-beta.1 - apiVersion: v2 appVersion: 0.8.2 - created: "2024-07-14T12:48:16.348621793Z" + created: "2024-07-18T09:44:18.661459726Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -871,7 +884,7 @@ entries: version: 0.8.2 - apiVersion: v2 appVersion: 0.8.2-beta.60 - created: "2024-07-14T12:48:16.347982144Z" + created: "2024-07-18T09:44:18.660824016Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -887,7 +900,7 @@ entries: version: 0.8.2-beta.60 - apiVersion: v2 appVersion: 0.8.2-beta.59 - created: "2024-07-14T12:48:16.347337786Z" + created: "2024-07-18T09:44:18.660176543Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -903,7 +916,7 @@ entries: version: 0.8.2-beta.59 - apiVersion: v2 appVersion: 0.8.2-beta.58 - created: "2024-07-14T12:48:16.346676957Z" + created: "2024-07-18T09:44:18.659537266Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -919,7 +932,7 @@ entries: version: 0.8.2-beta.58 - apiVersion: v2 appVersion: 0.8.2-beta.57 - created: "2024-07-14T12:48:16.345610839Z" + created: "2024-07-18T09:44:18.658888141Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -935,7 +948,7 @@ entries: version: 0.8.2-beta.57 - apiVersion: v2 appVersion: 0.8.2-beta.56 - created: "2024-07-14T12:48:16.344597911Z" + created: "2024-07-18T09:44:18.658212445Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -951,7 +964,7 @@ entries: version: 0.8.2-beta.56 - apiVersion: v2 appVersion: 0.8.2-beta.52 - created: "2024-07-14T12:48:16.343958252Z" + created: "2024-07-18T09:44:18.656843817Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -967,7 +980,7 @@ entries: version: 0.8.2-beta.52 - apiVersion: v2 appVersion: 0.8.2-beta.51 - created: "2024-07-14T12:48:16.343310728Z" + created: "2024-07-18T09:44:18.656202316Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -983,7 +996,7 @@ entries: version: 0.8.2-beta.51 - apiVersion: v2 appVersion: 0.8.2-beta.50 - created: "2024-07-14T12:48:16.342658525Z" + created: "2024-07-18T09:44:18.65555318Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -999,7 +1012,7 @@ entries: version: 0.8.2-beta.50 - apiVersion: v2 appVersion: 0.8.2-beta.49 - created: "2024-07-14T12:48:16.341907308Z" + created: "2024-07-18T09:44:18.654891381Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1015,7 +1028,7 @@ entries: version: 0.8.2-beta.49 - apiVersion: v2 appVersion: 0.8.2-beta.48 - created: "2024-07-14T12:48:16.341261868Z" + created: "2024-07-18T09:44:18.654246854Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1031,7 +1044,7 @@ entries: version: 0.8.2-beta.48 - apiVersion: v2 appVersion: 0.8.2-beta.47 - created: "2024-07-14T12:48:16.340597603Z" + created: "2024-07-18T09:44:18.653553185Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1047,7 +1060,7 @@ entries: version: 0.8.2-beta.47 - apiVersion: v2 appVersion: 0.8.2-beta.46 - created: "2024-07-14T12:48:16.340010513Z" + created: "2024-07-18T09:44:18.652733921Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1063,7 +1076,7 @@ entries: version: 0.8.2-beta.46 - apiVersion: v2 appVersion: 0.8.2-beta.45 - created: "2024-07-14T12:48:16.338776556Z" + created: "2024-07-18T09:44:18.652155157Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1079,7 +1092,7 @@ entries: version: 0.8.2-beta.45 - apiVersion: v2 appVersion: 0.8.2-beta.44 - created: "2024-07-14T12:48:16.338177133Z" + created: "2024-07-18T09:44:18.65155345Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1095,7 +1108,7 @@ entries: version: 0.8.2-beta.44 - apiVersion: v2 appVersion: 0.8.2-beta.43 - created: "2024-07-14T12:48:16.337596755Z" + created: "2024-07-18T09:44:18.650315225Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1111,7 +1124,7 @@ entries: version: 0.8.2-beta.43 - apiVersion: v2 appVersion: 0.8.2-beta.41 - created: "2024-07-14T12:48:16.336953048Z" + created: "2024-07-18T09:44:18.649618229Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1127,7 +1140,7 @@ entries: version: 0.8.2-beta.41 - apiVersion: v2 appVersion: 0.8.2-beta.40 - created: "2024-07-14T12:48:16.336306917Z" + created: "2024-07-18T09:44:18.648953655Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1143,7 +1156,7 @@ entries: version: 0.8.2-beta.40 - apiVersion: v2 appVersion: 0.8.2-beta.39 - created: "2024-07-14T12:48:16.335749462Z" + created: "2024-07-18T09:44:18.648396651Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1159,7 +1172,7 @@ entries: version: 0.8.2-beta.39 - apiVersion: v2 appVersion: 0.8.2-beta.38 - created: "2024-07-14T12:48:16.33517182Z" + created: "2024-07-18T09:44:18.647841832Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1175,7 +1188,7 @@ entries: version: 0.8.2-beta.38 - apiVersion: v2 appVersion: 0.8.2-beta.37 - created: "2024-07-14T12:48:16.334618462Z" + created: "2024-07-18T09:44:18.647258069Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1191,7 +1204,7 @@ entries: version: 0.8.2-beta.37 - apiVersion: v2 appVersion: 0.8.1 - created: "2024-07-14T12:48:16.333962593Z" + created: "2024-07-18T09:44:18.646646093Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1205,4 +1218,4 @@ entries: urls: - https://openmined.github.io/PySyft/helm/syft-0.8.1.tgz version: 0.8.1 -generated: "2024-07-14T12:48:16.332623073Z" +generated: "2024-07-18T09:44:18.645850393Z" diff --git a/packages/grid/helm/repo/syft-0.8.7-beta.15.tgz b/packages/grid/helm/repo/syft-0.8.7-beta.15.tgz new file mode 100644 index 0000000000000000000000000000000000000000..a71fb16e4d78a885db796a670745de0ecb5d88ad GIT binary patch literal 18043 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 literal 0 HcmV?d00001 diff --git a/packages/grid/helm/syft/Chart.yaml b/packages/grid/helm/syft/Chart.yaml index 7ebe62c3364..a0e1bf432c2 100644 --- a/packages/grid/helm/syft/Chart.yaml +++ b/packages/grid/helm/syft/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: syft description: Perform numpy-like analysis on data that remains in someone elses server type: application -version: "0.8.7-beta.14" -appVersion: "0.8.7-beta.14" +version: "0.8.7-beta.15" +appVersion: "0.8.7-beta.15" home: https://github.com/OpenMined/PySyft/ icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png diff --git a/packages/grid/helm/syft/templates/NOTES.txt b/packages/grid/helm/syft/templates/NOTES.txt index f625e4e727a..679523d63fb 100644 --- a/packages/grid/helm/syft/templates/NOTES.txt +++ b/packages/grid/helm/syft/templates/NOTES.txt @@ -10,1193 +10,1053 @@ Following class versions are either added/removed. { + "BaseDateTime": { + "1": { + "version": 1, + "hash": "614db484b1950be729902b1861bd3a7b33899176507c61cef11dc0d44611cfd3", + "action": "add" + } + }, "PartialSyftObject": { - "2": { - "version": 2, - "hash": "a32dc097345cffb073caa322281fd8de5f89f0072e9244d093a8bf32ce260642", + "1": { + "version": 1, + "hash": "19a995fcc2833f4fab24584fd99b71a80c2ef1f13c06f83af79e4482846b1656", "action": "add" } }, "ServerMetadata": { - "4": { - "version": 4, - "hash": "e5e0c2d926bf1fea0696126c9cd2ea5308c198f9412de1732a509082cb738e35", - "action": "add" - }, - "5": { - "version": 5, - "hash": "13bfe668b20779b2ab04227dc6b92d545b9ea83baaf0002cad5bcc450f34d246", + "1": { + "version": 1, + "hash": "1691c7667eca86b20c4189e90ce4e643dd41fd3682cdb69c6308878f2a6f135c", "action": "add" } }, "StoreConfig": { - "2": { - "version": 2, - "hash": "af833ac27e16cd3dd93061e4870847df37e480893d867966a0ae8dcca57b9abb", + "1": { + "version": 1, + "hash": "a9997fce6a8a0ed2884c58b8eb9382f8554bdd18fff61f8bf0451945bcff12c7", "action": "add" } }, "MongoDict": { - "2": { - "version": 2, - "hash": "2ab3c12b81326108badd66307d4c4fefb1d60e76d5be2c67e70bb607b4992e93", + "1": { + "version": 1, + "hash": "57e36f57eed75e62b29e2bac1295035a9bf2c0e3c56719dac24cb6cc685be00b", "action": "add" } }, "MongoStoreConfig": { - "2": { - "version": 2, - "hash": "89f75ccf2d640d2dc47aa68bdbd766e4b83433a98653ade174724a631f47fd4d", + "1": { + "version": 1, + "hash": "53342b27d34165b7e2699f8e7ad70d13d125875e6a75e8fa18f5796428f41036", "action": "add" } }, "LinkedObject": { - "2": { - "version": 2, - "hash": "d9c00f99c5385cbcdd11173dfd30b532ddcbc4e8c37f6121a01061cf71b91b5e", + "1": { + "version": 1, + "hash": "d80f5ac7f51a9383be1a3cb334d56ae50e49733ed3199f3b6b5d6febd9de410b", "action": "add" } }, "BaseConfig": { - "2": { - "version": 2, - "hash": "09bb3e3ba91f6c2604d4a057a7be48afa8fb4720b683ac4019569323900acdc9", + "1": { + "version": 1, + "hash": "10bd7566041d0f0a3aa295367785fdcc2c5bbf0ded984ac9230754f37496a6a7", "action": "add" } }, "ServiceConfig": { - "2": { - "version": 2, - "hash": "df15d8e09dedcbee2e07292ad71a8fd42cf0d52ac4ffdaaa27ef87b7f2629a8a", + "1": { + "version": 1, + "hash": "28af8a296f5ff63de50438277eaa1f4380682e6aca9f2ca28320d7a444825e88", "action": "add" } }, "LibConfig": { - "2": { - "version": 2, - "hash": "6453cb794e0a89c8a0f4529d2f81e4f04b141a0d313760c38f41f2dd42258941", + "1": { + "version": 1, + "hash": "ee8f0e3f6aae81948d72e30226645e8eb5d312a6770411a1edca748168c467c0", "action": "add" } }, "APIEndpoint": { - "2": { - "version": 2, - "hash": "695974643dbc32a1a653218a9b2fedfdd341bdd687584cf80035bb51e7ed9be1", + "1": { + "version": 1, + "hash": "cfa6f314481a5bf3c448c33bf2312a9c33cbcf03cdc96864ad9a108f62b09346", "action": "add" } }, "LibEndpoint": { - "2": { - "version": 2, - "hash": "acc9924f09471081899ed21d2d4da3e4ed307edd5e703ee0041a41827e26ccde", + "1": { + "version": 1, + "hash": "a585c83a33a019d363ae5a0c6d4197193654307c19a4829dfbf8a8cfd2c1842a", "action": "add" } }, "SignedSyftAPICall": { - "2": { - "version": 2, - "hash": "4dfc0709ab211d55250d2be8f6ec60be1f9517d98a73c98d2a360d92e49822ff", + "1": { + "version": 1, + "hash": "2f959455f7130f4e59360b8aa58f19785b76eaa0f8a5a9188a6cbf32b31311ca", "action": "add" } }, "SyftAPICall": { - "2": { - "version": 2, - "hash": "b457a48a7f0ddc67525d91faf660667adcb80f7a478999a35396a2e4bc22c562", + "1": { + "version": 1, + "hash": "59e89e7b9ea30deaed64d1ffd9bc0769b999d3082b305428432c1f5be36c6343", "action": "add" } }, "SyftAPIData": { - "2": { - "version": 2, - "hash": "46b073b98cfb3a4a0f5dc6c55885278f263bc208d3704821849568e246101aa8", + "1": { + "version": 1, + "hash": "820b279c581cafd9bb5009702d4e3db22ec3a3156676426304b9038dad260a24", "action": "add" } }, "SyftAPI": { - "2": { - "version": 2, - "hash": "03ec5999de8f43ce83da079d836aec737d1142ec11265c0f3ca89da3139fad36", - "action": "add" - }, - "3": { - "version": 3, - "hash": "b82f04c734e7cc3a14bf5cf88173e2ed41a09ddd332b0b4a79747c333ca8db1e", + "1": { + "version": 1, + "hash": "cc13ab058ee36748c14b0d4bd9b9e894c7566fff09cfa4170b3eece520169f15", "action": "add" } }, "User": { - "3": { - "version": 3, - "hash": "cdd25c47e32ac79e177bd26b8d3231847f4722247543954fc967686159ac17a2", + "1": { + "version": 1, + "hash": "2df4b68182c558dba5485a8a6867acf2a5c341b249ad67373a504098aa8c4343", "action": "add" } }, "UserUpdate": { - "3": { - "version": 3, - "hash": "01c3a470b326229bc892bea96b425c059edfde3bca57b0af83491a4fecbd0402", + "1": { + "version": 1, + "hash": "1bf6707c69b809c804fb939c7c37d787c2f6889508a4bec37d24221af2eb777a", "action": "add" } }, "UserCreate": { - "3": { - "version": 3, - "hash": "cb2d9872cba80c960c748b232547556fa69901c108d84ab46f177cb47f0dd3fc", + "1": { + "version": 1, + "hash": "49d6087e2309ba59987f3126e286e74b3a66492a08ad82fa507ea17d52ce78e3", "action": "add" } }, "UserSearch": { - "2": { - "version": 2, - "hash": "c2676b012142f68ae64a11f3807e35430a046f51b7cac6682aa453c0345a9a32", + "1": { + "version": 1, + "hash": "9ac946338cca68d00d1696a57943442f062628ec3daf53077d0bdd3f72cd9fa0", "action": "add" } }, "UserView": { - "3": { - "version": 3, - "hash": "a07bebf2362391b915fb2554e61c98e35cb4f945ba8c3c3299dd059dc6f0e137", + "1": { + "version": 1, + "hash": "0b52d758e31d5889c9cd88afb467aae4a74e34a5276924e07012243c34d300fe", "action": "add" } }, "UserViewPage": { - "2": { - "version": 2, - "hash": "9ccdbff62daac91fc9951a62c7d54d35418035a0ad4fd979bd1f7262c2cdabc9", + "1": { + "version": 1, + "hash": "1cd6528d02ec180f080d5c35f0da760d8a59af9da7baaa9c17c1c7cedcc858fa", "action": "add" } }, "UserPrivateKey": { - "2": { - "version": 2, - "hash": "3e7a37177e86a5a0c54a6e6cc87eb2c3a266e5e65cb8dd33f6b0c3fccc7b584d", + "1": { + "version": 1, + "hash": "4817d8147aba94373f320dcd90e65f097cf6e5a2ef353aa8520e23128d522b5d", "action": "add" } }, "DateTime": { - "2": { - "version": 2, - "hash": "298922f94fc06eb8ce080cd19bc124929943729ea83bf15b463b37fe959141cb", + "1": { + "version": 1, + "hash": "394abb554114ead4d63c36e3fe83ac018dead4b21a8465174009577c46d54c58", "action": "add" } }, "ReplyNotification": { - "2": { - "version": 2, - "hash": "0420ed6a014e3a16bcf063208cfdc393a02f4ec0ddbd0635dc15308b5deafc92", + "1": { + "version": 1, + "hash": "84102dfc59d711b03c2f3d3a6ecaca000b6835f1bbdd9af801057f7aacb5f1d0", "action": "add" } }, "Notification": { - "2": { - "version": 2, - "hash": "38defc169bf225474e0b8037aedf66dee78f5e0aef3af75ab24d1e8f5d55f23a", + "1": { + "version": 1, + "hash": "af4cb232bff390c431e399975f048b34da7e940ace8b23b940a3b398c91c5326", "action": "add" } }, "CreateNotification": { - "2": { - "version": 2, - "hash": "079523cd89527b90003bef1ab4f985e374550bfb1f7921f8906702a9f6938205", + "1": { + "version": 1, + "hash": "7e426c946b7d5db6f9427960ec16042f3018091d835ca5966f3568c324a2ab53", "action": "add" } }, "NotificationPreferences": { "1": { "version": 1, - "hash": "499e02b45defab561decaef6bdcf0ec1a6bbda834bd7d25a465982159b8c2909", + "hash": "a42f06b367e7c6cbabcbf3cfcc84d1ca0873e457d972ebd060e87c9d6185f62b", "action": "add" } }, "NotifierSettings": { "1": { "version": 1, - "hash": "8edcbf73f2098f6a20d393f09c5805493da5346e8f7070f841c36ac7b777edb1", + "hash": "65c8ab814d35fac32f68d3000756692592cc59940f30e3af3dcdfa2328755b9d", "action": "add" } }, "SyftImageRegistry": { - "2": { - "version": 2, - "hash": "2495c6836c6f0ba991637766657ccd04e992d367102d336a04c608d95cbf9895", + "1": { + "version": 1, + "hash": "67e18903e41cba1afe136adf29d404b63ec04fea6e928abb2533ec4fa52b246b", "action": "add" } }, "SyftWorkerImage": { - "2": { - "version": 2, - "hash": "dcd40e107f930c0efcd525694e89eedea1546fdc31d44373fce7e9d4ac2bbc2e", + "1": { + "version": 1, + "hash": "44da7badfbe573d5403d3ab78c077f17dbefc560b81fdf927b671815be047441", "action": "add" } }, "SyftWorker": { - "2": { - "version": 2, - "hash": "6dbf5487cfb6fceea8a57d1cbb1320107f4a4116fb0269f151082e15f9d150b5", - "action": "add" - }, - "3": { - "version": 3, - "hash": "905b97e80b2a9d509a5d37ae248ed6ddc1e028e851330c836ee5ce26444fac88", + "1": { + "version": 1, + "hash": "9d897f6039eabe48dfa8e8d5c5cdcb283b0375b4c64571b457777eaaf3fb1920", "action": "add" } }, "WorkerPool": { - "2": { - "version": 2, - "hash": "d2205590c821af416ba8f13f3e2b834fa3bb561f08dca060eb2bd86f7eca89e2", + "1": { + "version": 1, + "hash": "16efc5dd2596ae744fd611c8f46af9eaec1bd5729eb20e85e9fd2f31df402564", "action": "add" } }, "MarkdownDescription": { - "2": { - "version": 2, - "hash": "d8f5ec42e69d55eabe044a417bfbf6d57b867eadcc975377e1fc8a499a9f90f3", + "1": { + "version": 1, + "hash": "31a73f8824cad1636a55d14b6a1074cdb071d0d4e16e86baaa3d4f63a7e80134", "action": "add" } }, "HTMLObject": { "1": { "version": 1, - "hash": "4127056b8f9f904f2dcb225de2952ad7b57c4b2874ac76800afa234c826d6702", + "hash": "97f2e93f5ceaa88015047186f66a17ff13df2a6b7925b41331f9e19d5a515a9f", "action": "add" } }, "ServerSettingsUpdate": { - "4": { - "version": 4, - "hash": "09b96c7c25e9261144ffe3409ac47e943abe5cf433759f68c03a321d21d69c1b", - "action": "add" - }, - "5": { - "version": 5, - "hash": "81a9e2930fe91f7744a5a495f73eb9f7c04145ebe1848257ea52b537fed4b3d7", + "1": { + "version": 1, + "hash": "1e4260ad879ae80728c3ffae2cd1d48759abd51f9d0960d4b25855cdbb4c506b", "action": "add" } }, "ServerSettings": { - "3": { - "version": 3, - "hash": "6b2240b92099684b0e431d27c0be2a22daad234b890c95eb607f0cc9e73c9f0d", - "action": "add" - }, - "5": { - "version": 5, - "hash": "522690efe97c50dff81936640e95207861406e480d7e1d87587e558dbd7a506c", - "action": "add" - }, - "6": { - "version": 6, - "hash": "be6d6402a5ccf0b93847ebcde75f4ea357f3b45003a1a7c01426e9e34ea3b5e1", + "1": { + "version": 1, + "hash": "5a1e7470cbeaaae5b80ac9beecb743734f7e4e42d429a09ea8defa569a5ddff1", "action": "add" } }, "HTTPConnection": { - "3": { - "version": 3, - "hash": "2e567111a679e9f01b84eafc96d5e14e52b12fea991957e547f2edcbc0ede34c", + "1": { + "version": 1, + "hash": "bf10f81646c71069c76292b1237b4a3de1e507264392c5c591d067636ce6fb46", "action": "add" } }, "PythonConnection": { - "3": { - "version": 3, - "hash": "854a2ffc94e21fdcc4878ddc16f60bef8e7bf8ddc72dec63c9cb182ad7e4bbb7", + "1": { + "version": 1, + "hash": "28010778b5e3463ff6960a0e2224818de00bc7b5e6f892192e02e399ccbe18b5", "action": "add" } }, "ActionDataEmpty": { - "2": { - "version": 2, - "hash": "76445c74c9636f33524ed1ec60796caabfda2dcf85a950387ee9526b2659efe4", + "1": { + "version": 1, + "hash": "e0e4a5cf18d05b6b747addc048515c6f2a5f35f0766ebaee96d898cb971e1c5b", "action": "add" } }, "ObjectNotReady": { - "2": { - "version": 2, - "hash": "09e8e20e1f96189b96ddda19d1cffafed98dfa8fd80b286ea91b814c7aa0aa5b", + "1": { + "version": 1, + "hash": "8cf471e205cd0893d6aae5f0227d14db7df1c9698da08a3ab991f59132d17fe9", "action": "add" } }, "ActionDataLink": { - "2": { - "version": 2, - "hash": "45f82b2a0124f7adadc515c40f71551a37ea4b04fdc2caa220e39988e8d83675", + "1": { + "version": 1, + "hash": "3469478343439e411b761c270eec63eb3d533e459ad72d0965158c3a6cdf3b9a", "action": "add" } }, "Action": { - "3": { - "version": 3, - "hash": "9baeef92e1199d9686ad27bcaf55ad0621233560dd70377fc964ccc4ab21bcb4", + "1": { + "version": 1, + "hash": "021826d7c6f69bd0283d025d40661f3ffbeba8810ca94de01344f6afbdae62cd", "action": "add" } }, "ActionObject": { - "3": { - "version": 3, - "hash": "e13cca90723c27b17529295e1050ba4736aa42e548511f922ab4d10a78e9c558", - "action": "add" - }, - "4": { - "version": 4, - "hash": "da069dc83b2c583d5624f86541ed95d9c8a85774a1fb64e37fdd87e490e06300", + "1": { + "version": 1, + "hash": "0a5f4bc343cb114a251f06686ecdbb59d74bfb3d29a098b176699deb35a1e683", "action": "add" } }, "AnyActionObject": { - "3": { - "version": 3, - "hash": "8b6a450bbc40f381cb3404ea6ff86024651debcdebe785db0819ab1ffd6535b0", - "action": "add" - }, - "4": { - "version": 4, - "hash": "a944e6db84aa6cda0d4cb278cc836df1ce64882896a9d3da798148e1e9bb5c42", - "action": "add" - } - }, - "BlobFile": { - "4": { - "version": 4, - "hash": "6d59e20f3a9bf16cf199deddb0d246b100d5ab616a4811e96b682df58546b869", - "action": "add" - } - }, - "BlobFileOBject": { - "2": { - "version": 2, - "hash": "af3c2e435c20258b94377716fb6babb0bfb8ea684c88a93aff968f95fb1497f6", - "action": "add" - }, - "3": { - "version": 3, - "hash": "417f4eb6f978a273c3b7cad93fc80caab122bebdf21923520dbfcadcc5160baf", + "1": { + "version": 1, + "hash": "b3c44c7788c59c03fa1baeec656c2ca6e633f4cbd4b23ff7ece6ee94c38449f0", "action": "add" } }, - "SecureFilePathLocation": { - "2": { - "version": 2, - "hash": "1680c4c2f81f3e93fe126c5888288577b32e76546f16be3ffe5c3fdcce1aac3f", + "CustomEndpointActionObject": { + "1": { + "version": 1, + "hash": "c7addbaf2777707f3e91e5c1e092343476cd22efc4ec8617f39ccf76e61a5a14", "action": "add" } }, - "SeaweedSecureFilePathLocation": { - "3": { - "version": 3, - "hash": "0d34e64267f3c870a5ce5307802a23fcfbb796cf48b979c2d1d4c0ef772f8131", + "DataSubject": { + "1": { + "version": 1, + "hash": "582cdf9e82b5d6915b7f09f7c0d5f08328b11a2ce9b0198e5083f1672c2e2bf5", "action": "add" } }, - "AzureSecureFilePathLocation": { - "2": { - "version": 2, - "hash": "a97c52808be5afceaea7f9b3ac6c00d4256d7f9a8c7f2200acf8f82451018319", + "DataSubjectCreate": { + "1": { + "version": 1, + "hash": "5a8423c2690d55f425bfeecc87cd4a797a75d88ebb5fbda754d4f269b62d2ceb", "action": "add" } }, - "BlobStorageEntry": { - "3": { - "version": 3, - "hash": "6ff74feabd8a58ae0e1881c03f3ffbb70c95944bef507f8c5b1493bfb6594ea5", + "DataSubjectMemberRelationship": { + "1": { + "version": 1, + "hash": "0810483ea76ea10c8f286c6035dc0b2085291f345183be50c179f3a05a577110", "action": "add" } }, - "BlobStorageMetadata": { - "3": { - "version": 3, - "hash": "738daa84b6824841254ba7a651a433dd0ff1c44961ed142920786cbc60329ffa", + "Contributor": { + "1": { + "version": 1, + "hash": "30c32bd44098f00e0b15496be441763b6e50af8b12d3d2bef33aca6287193876", "action": "add" } }, - "CreateBlobStorageEntry": { - "2": { - "version": 2, - "hash": "9c0069727e5b845a004717dc28abcf1486f5581cba4ec0526fdb3553d40ecd7a", + "Asset": { + "1": { + "version": 1, + "hash": "000abc78719611c106295cf12b1690b7e5411dc1bb9db9d4afd22956da90d1f4", "action": "add" } }, - "BlobRetrieval": { - "3": { - "version": 3, - "hash": "3b7be2fa9b5821c03808ae2dd244feb04817f5b1f1f821cd861f111fdc8692f9", + "CreateAsset": { + "1": { + "version": 1, + "hash": "357d52576cb12b24fb3980342bb49a562b065c0e4419e87d34176340628c7309", "action": "add" } }, - "SyftObjectRetrieval": { - "4": { - "version": 4, - "hash": "4d6a3175fd8753919ceed4d7b19a6a25baa47013da8f9d2e4eae3afd2c72f246", + "Dataset": { + "1": { + "version": 1, + "hash": "0ca6b0b4a3aebb2c8f351668075b44951bb20d1e23a779b82109124f334ce3a4", "action": "add" } }, - "BlobRetrievalByURL": { - "4": { - "version": 4, - "hash": "6a77259a8c83f85e83e89cee4c7ea7b1d57ccac4f70ecfb86b6c5db21c62ee79", - "action": "add" - }, - "5": { - "version": 5, - "hash": "e9c5e16f14e5bd45209f44ebf6c758a8c4a315b2d335a33bc529606506037890", + "DatasetPageView": { + "1": { + "version": 1, + "hash": "aa0dd69637281b80d5523b4409a2c7e89db114c9fe79c858063c6dadff8977d1", "action": "add" } }, - "BlobDeposit": { - "2": { - "version": 2, - "hash": "cf27595f05e3f60c825ef3b547ab72f04cc983688b12ef9233785b05b5a24551", + "CreateDataset": { + "1": { + "version": 1, + "hash": "7e02dfa89540c3dbebacbb13810d95cdc4e36db31d56cffed7ab54abe25716c9", "action": "add" } }, - "WorkerSettings": { - "3": { - "version": 3, - "hash": "982d68aca23fdecd9d8986f6ac95a2812ddac784c5a30655367df5356c9778f1", + "SyftLog": { + "1": { + "version": 1, + "hash": "1bcd71e5bf3f0db3bba0996f33b6b2bde3489b9c71f11e6b30c3495c76a8f53f", "action": "add" } }, - "HTTPServerRoute": { - "3": { - "version": 3, - "hash": "530fec14b476cf67afeef8667fd5397a2bca51744869e41828f4328bed647f72", + "JobItem": { + "1": { + "version": 1, + "hash": "0b32277b7d3b9bdc14a2a51cc9005f8254e7f7b6ec059ddcccbcd681a807afb6", "action": "add" } }, - "PythonServerRoute": { - "3": { - "version": 3, - "hash": "f9f52b5764f2a5c3bd2b628f793e2ab9d0e5163f0bf4a469d4b3ee804ee27eeb", + "ExecutionOutput": { + "1": { + "version": 1, + "hash": "e36c71685edf5276a3427cb6749550486d3a177c1dcf73dd337ab2a73c0ce6b5", "action": "add" } }, - "VeilidServerRoute": { + "TwinObject": { "1": { "version": 1, - "hash": "0924cb1d76957bdc7f39ccb54e2944ce07bc83c0bf37ccf5f89d7328c0088eeb", + "hash": "4f31243fb348dbb083579afd6f638d75af010cb53d19bfba59b74afff41ccbbb", "action": "add" } }, - "EnclaveMetadata": { - "3": { - "version": 3, - "hash": "94998d8fad3c2ca1f371a08641873e24504065bfe785548aba72dfaf9687c409", + "PolicyRule": { + "1": { + "version": 1, + "hash": "44d1ca1db97be46f66558aa1a729ff31bf8e113c6a913b11aedf9d6b6ad5b7b5", "action": "add" } }, - "CustomEndpointActionObject": { + "CreatePolicyRule": { "1": { "version": 1, - "hash": "aba8c35a83b81f602ae19393e9bd1813ca1d191d055272499c63543961089b86", + "hash": "342bb723526d445151a0435f57d251f4c1219f8ae7cca3e8e9fce52e2ee1b8b1", "action": "add" } }, - "DataSubject": { - "2": { - "version": 2, - "hash": "24329941dbb93f9382527b9b2e70da58369aefa65ae6934a4f55725487259515", + "CreatePolicyRuleConstant": { + "1": { + "version": 1, + "hash": "78b54832cb0468a87013bc36bc11d4759874ca1b5065a1b711f1e5ef5d94c2df", "action": "add" } }, - "DataSubjectCreate": { - "2": { - "version": 2, - "hash": "1584dc6cbd2df80118d46aa9cf4788c96be420ce3a1d3ff041664fb265626871", + "Matches": { + "1": { + "version": 1, + "hash": "dd6d91ddb2ec5eaf60be2b0899ecfdb9a15f7904aa39d2f4d9bb2d7b793040e6", "action": "add" } }, - "DataSubjectMemberRelationship": { - "2": { - "version": 2, - "hash": "26876c004bb080c06af331965466e66d454ccb6b6a03d12aec0d44032302412b", + "PreFill": { + "1": { + "version": 1, + "hash": "c7aefb11dc4c4569dcd1e6988371047a32a8be1b32ad46d12adba419a19769ad", "action": "add" } }, - "Contributor": { - "2": { - "version": 2, - "hash": "281a88bcfd8840b3f92780d31075bfa369b2ff0e5d4044ebbc269bebca451b47", + "UserOwned": { + "1": { + "version": 1, + "hash": "c8738dc3d8c2a5ef461b85a0467c3dff53dab16b54a4d12b44b1477906aef51d", "action": "add" } }, - "Asset": { - "2": { - "version": 2, - "hash": "84f33e07c0a4a627808ada7ae092b9e11305a2a6a9d4f264f62ed906a834663d", + "MixedInputPolicy": { + "1": { + "version": 1, + "hash": "37bb12d950518d9579c8ec7c4cc22ac731ea82caf8c1370dd0b0a82b46462dde", "action": "add" } }, - "CreateAsset": { - "2": { - "version": 2, - "hash": "0fbe735bdf6acd91f5589369188c02d25d014b7112afbcde8b04d52aca2abb65", + "ExactMatch": { + "1": { + "version": 1, + "hash": "5eb37edbf5e451d942e599247f3eaed923c1fe9d91eefdba02bf06503f6cc08d", "action": "add" } }, - "Dataset": { - "2": { - "version": 2, - "hash": "e9df341cf5128d9ce09fb137e6413745842818675c9dfbbf824e521cb0196dd0", - "action": "add" - }, - "3": { - "version": 3, - "hash": "acc25456a60ccef861de65eea1feef612ef9fa1ed6e986b466450c4adf73906b", + "OutputHistory": { + "1": { + "version": 1, + "hash": "9366db79d131f8c65e5a4ff12c90e2aa0c11e302debe06e46eeb93b26e2aaf61", "action": "add" } }, - "DatasetPageView": { - "2": { - "version": 2, - "hash": "0e336a3afd446aa58fc6ec6950691baa36b76a0649b9da31bbecb4db1b0587cf", + "OutputPolicyExecuteCount": { + "1": { + "version": 1, + "hash": "2a77e5ed5c7b0391147562651ad4061e20b11745c191fbc34cb549da37ba72dd", "action": "add" } }, - "CreateDataset": { - "2": { - "version": 2, - "hash": "3e4983b35c6513a64198cf5346aec23017192045aad562e85deb7e212be78784", - "action": "add" - }, - "3": { - "version": 3, - "hash": "7ecb8d62a8c12e385ff45ed700106bb1463926237fbdde3e84a83f38419d54de", + "OutputPolicyExecuteOnce": { + "1": { + "version": 1, + "hash": "5589c00d127d9eb1f5ccf3a16def8219737784d57bb3bf9be5cb6d83325ef436", "action": "add" } }, - "SyftLog": { - "3": { - "version": 3, - "hash": "c2ee3f4c34dc7af3af533865dc07384403fb757e7959272c9d6d08110623a216", - "action": "add" - }, - "4": { - "version": 4, - "hash": "3b90dcb66359a1d03345291b47dcb8b5c166b1e0344dbe84d9c1f3a8e57f99eb", + "EmptyInputPolicy": { + "1": { + "version": 1, + "hash": "7ef81cfd223be0064600e1503f8b04bafc16385e27730e9319466e68a077c68b", "action": "add" } }, - "JobItem": { - "4": { - "version": 4, - "hash": "3e2eaae1b2c367b5bc52cbc4eb3390b1f5a6a6f8cae69523bbfc8e071c314bf8", - "action": "add" - }, - "6": { - "version": 6, - "hash": "b633f770c9c47a849b75fe6b93c573c94eadab23c689aa812a8671cec9543650", + "UserPolicy": { + "1": { + "version": 1, + "hash": "74373bb71a334f4dcf77623ae10ff5b1c7e5b3006f65f2051ffb1e01f422f982", "action": "add" } }, - "ExecutionOutput": { + "SubmitUserPolicy": { "1": { "version": 1, - "hash": "c6cb71d6ae689e71c31685c29a7ecd44d1c0c5b31fd19991b535cb597db7b44a", - "action": "add" - }, - "2": { - "version": 2, - "hash": "1b045334d8049f3970e655da11f3f62bc8a9f78e562fd75ed517c97fc95bb1c3", + "hash": "ec4e808eb39613bcdbbbf9ffb3267612084a9d99880a2f3bee3ef32d46329c02", "action": "add" } }, - "TwinObject": { - "2": { - "version": 2, - "hash": "c1f81d875b96cec303af7d869e5a70f7b619f0f4849ad6a8987e75cf6e2f4538", + "UserCodeStatusCollection": { + "1": { + "version": 1, + "hash": "735ecf2d4abb1e7d19b2e751d880f32b01ce267ba10e417ef1b440be3d94d8f1", "action": "add" } }, - "PolicyRule": { + "UserCode": { "1": { "version": 1, - "hash": "b92557f8bd715caadb4eba68793f167493d36f29972006c2bd59b0ec8e829ba7", + "hash": "3bcd14413b9c4fbde7c5612c2ed713518340280b5cff89cf2aaaf1c77c4037a8", "action": "add" } }, - "CreatePolicyRule": { + "SubmitUserCode": { "1": { "version": 1, - "hash": "2962b14b70451ea8e13746ebadff62d927f62111d3d5610787ecb3b9cefcc897", + "hash": "d2bb8cfe12f070b4adafded78ce01900c5409bd83f055f94b1e285745ef65a76", "action": "add" } }, - "CreatePolicyRuleConstant": { + "UserCodeExecutionResult": { "1": { "version": 1, - "hash": "3807c5bf87bd1a58ecae8a97083e636f0471d4604121fb1f61182bd7dbbc1c47", + "hash": "1f4cbc62caac4dd193f427306405dc7a099ae744bea5830cf57149ce71c1e589", "action": "add" } }, - "Matches": { + "UserCodeExecutionOutput": { "1": { "version": 1, - "hash": "20dd67c0d60cd0047267dc83a767568d90fc418e84a05186eaba6f6a0279c50b", + "hash": "c1d53300a39dbbb437d7d5a1257bd175a067b1065f4099a0938fac7540035258", "action": "add" } }, - "PreFill": { + "CodeHistory": { "1": { "version": 1, - "hash": "557185e0437884ea9da718b449d0c6b38bc6c107e29d5f36ab6e34b8509a884d", + "hash": "e3ef5346f108257828f364d22b12d9311812c9cf843200afef5dc4d9302f9b21", "action": "add" } }, - "UserOwned": { + "CodeHistoryView": { "1": { "version": 1, - "hash": "50de8777b4027f394d910f5304d3d27c48cc58abdd9882c0e1cddc10b69f85c5", + "hash": "8b8b97d334b51d1ce0a9efab722411ff25caa3f12be319105954497e0a306eb2", "action": "add" } }, - "MixedInputPolicy": { + "CodeHistoriesDict": { "1": { "version": 1, - "hash": "b4d6b42c04a8b64a1ec065e700af67347c44a180cdfdb8f4e9b3bc030cf3bfe4", + "hash": "01d7dcd4b21525a06e4484d8699a4a34a5c84f1f6026ec55e32eb30412742601", "action": "add" } }, - "ExactMatch": { - "2": { - "version": 2, - "hash": "7fcc80c7ec005a0e1484b9d44fe9892ad886fda82044a9a96b0c33fbffc63d4f", + "UsersCodeHistoriesDict": { + "1": { + "version": 1, + "hash": "4ed8b83973258ea19a1f91feb2590ff73b801be86f4296cc3db48f6929ff784c", "action": "add" } }, - "OutputHistory": { - "2": { - "version": 2, - "hash": "e9844cc602cb57168e3062263961ad5d22a1e93a5bb3765ee364637813c9daca", + "BlobFile": { + "1": { + "version": 1, + "hash": "d99239100f1cb0b73c69b2ad7cab01a06909cc3a4976ba2b3b67cf6fe5e2f516", "action": "add" } }, - "OutputPolicyExecuteCount": { - "2": { - "version": 2, - "hash": "82a309e0616864a3505600a88fcfb772c2d5f781e286a285953e495f93a2b3e2", + "BlobFileOBject": { + "1": { + "version": 1, + "hash": "6c40dab2c8d2220d4fff7cc653d76cc026a856db7e2b5713b6341e255adc7ea2", "action": "add" } }, - "OutputPolicyExecuteOnce": { - "2": { - "version": 2, - "hash": "0b0baa12dd349997fb67887005c5c76f559d02d1a5570700af31d17a39016e72", + "SecureFilePathLocation": { + "1": { + "version": 1, + "hash": "ea5978b98d7773d221665b450454c9130c103a5c850669a0acd620607cd614b7", "action": "add" } }, - "EmptyInputPolicy": { - "2": { - "version": 2, - "hash": "f1724dfc2f8f1f33db2a9c9f0a18bed8c763539592e8cbadd586df7af90b66fe", + "SeaweedSecureFilePathLocation": { + "1": { + "version": 1, + "hash": "3fc9bfc8c1b1cf660c9747e8c1fe3eb2220e78d4e3b5d6b5c5f29a07a77ebf3e", "action": "add" } }, - "UserPolicy": { - "2": { - "version": 2, - "hash": "4b2396d083ad1200f66f83610a16c98fcf2fe9cbe918dfe1f2a893d3b700b6eb", + "AzureSecureFilePathLocation": { + "1": { + "version": 1, + "hash": "090a9e962eeb655586ee966c5651d8996363969818a38f9a486fd64d33047e05", "action": "add" } }, - "SubmitUserPolicy": { - "2": { - "version": 2, - "hash": "91594efc92f7d6115c148930f02f90a06728fb8e1ed567c2c03cdae1967b62e3", + "BlobStorageEntry": { + "1": { + "version": 1, + "hash": "afdc6a1d8a24b1ee1ed9d3e79f5bac64b4f0d9d36800f07f10be0b896470345f", "action": "add" } }, - "UserCodeStatusCollection": { + "BlobStorageMetadata": { "1": { "version": 1, - "hash": "96bea86ece8bd4cb2948deba4fbdc1aa95a54b6f5ef03dbf8c805f1b3cc36db1", + "hash": "9d4b61ac4ea1910c2f7c767a50a6a52544a24663548f069e79bd906f11b538e4", "action": "add" } }, - "UserCode": { - "4": { - "version": 4, - "hash": "60ee9415e8692ad6c0fe9e5e65961d3b7e4247fbc765abcd871f612f546155f9", - "action": "add" - }, - "5": { - "version": 5, - "hash": "c3845ff8d7e006525f208dc19f93e0f0757a15b63b3e3664fabfa789dbe5fd2e", + "CreateBlobStorageEntry": { + "1": { + "version": 1, + "hash": "ffc3cbfeade67d074dc5bf7d655a1eb8c83630076028a72b3cc4548f3b413e14", "action": "add" } }, - "SubmitUserCode": { - "4": { - "version": 4, - "hash": "330b62d200c304e12b47e5b288fe7f419dcdb22f0aad2e31aa978a0a5993dbcb", - "action": "add" - }, - "5": { - "version": 5, - "hash": "ca0d501801f3aac1ad53f1e7844520dc7733c64f3fa012abb9fd95940c170d6e", + "SyftObjectMigrationState": { + "1": { + "version": 1, + "hash": "ee83315828551f18904bab18e0cac48896493620561215b04cc448e6ce5834af", "action": "add" } }, - "UserCodeExecutionResult": { - "2": { - "version": 2, - "hash": "72aed37d1b165f36aeeba41e13c9ac570b17b35ced11a53b70d289e95d5d0c5e", + "StoreMetadata": { + "1": { + "version": 1, + "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", "action": "add" } }, - "UserCodeExecutionOutput": { + "MigrationData": { "1": { "version": 1, - "hash": "d180eb86a0baa95c0df100beda459586793af07259e21c1a559bcf961661cffd", + "hash": "cb96b8c8413609e1224341d1b0dd1efb08387c0ff7b0ff65eba36c0b104c9ed1", "action": "add" } }, - "CodeHistory": { - "2": { - "version": 2, - "hash": "7740375395772ee76a693b592f8ca72b954b75478d9b77eb38a2efbd0e3f53cb", - "action": "add" - }, - "3": { - "version": 3, - "hash": "7bede78c55f99d0e0294b0555ab2bace37f78fc5f58f423bba485b88ae190dc3", + "BlobRetrieval": { + "1": { + "version": 1, + "hash": "c422c74b89a9349742acaa848566fe18bfef1a83333458b858c074baed37a859", "action": "add" } }, - "CodeHistoryView": { - "2": { - "version": 2, - "hash": "c289d9a50f718966d7edb647025c1bcfb71b38e11f4d0d2a18d24c6a7b6d9bbf", + "SyftObjectRetrieval": { + "1": { + "version": 1, + "hash": "b2b62447445adc4cd0b77ab59d6fa56624dd316fb50281e570daad07556b6db2", "action": "add" } }, - "CodeHistoriesDict": { - "2": { - "version": 2, - "hash": "25f10dd11e5d360760b253ca76a38a1399cbbb6a209dad884bebff563acf0d58", + "BlobRetrievalByURL": { + "1": { + "version": 1, + "hash": "4db0e3b7a6334d3835356d8393866711e243e360af25a95f3cc4066f032404b5", "action": "add" } }, - "UsersCodeHistoriesDict": { - "2": { - "version": 2, - "hash": "5c5840b39300d5540c8dbeab673dc925e8187d8589f36a84063af822437ebe88", + "BlobDeposit": { + "1": { + "version": 1, + "hash": "6eb5cc57dc763126bfc6ec5a2b79d02e77eadf9d9efb1888a5c366b7799c1c24", "action": "add" } }, "OnDiskBlobDeposit": { - "2": { - "version": 2, - "hash": "83d6ec5c1c0c67627ad117b287201a75d9d91eb043921992bc761cf08b9526f0", + "1": { + "version": 1, + "hash": "817bf1bee4a35bfa1cd25d6779a10d8d180b1b3f1e837952f81f48b9411d1970", "action": "add" } }, "RemoteConfig": { - "2": { - "version": 2, - "hash": "9ec87d036c109dd408ed2ab8042a735f0150358799c4acc8af582148605373fc", + "1": { + "version": 1, + "hash": "179d067099a178d748c6d9a0477e8de7c3b55577439669eca7150258f2409567", "action": "add" } }, "AzureRemoteConfig": { - "2": { - "version": 2, - "hash": "4f5f6f4d0b52788c2ae484c5da6346f1c8b25ae064d865da69e6dffb32275852", + "1": { + "version": 1, + "hash": "a143811fec0da5fd881e927643ef667c91c78a2c90519cf88da7da20738bd187", "action": "add" } }, "SeaweedFSBlobDeposit": { - "4": { - "version": 4, - "hash": "d5c268e0ccbb00149319679b95eb43134ae80ae43814d7f991732530c79399a1", + "1": { + "version": 1, + "hash": "febeb2a2ce81aa2c512e4c6b611b582984042aafa0541403d4584662273a166c", "action": "add" } }, "DictStoreConfig": { - "2": { - "version": 2, - "hash": "4f7084ac3353fb7c16b010b654150096c08de108fbdaf6e8837654aa38a32466", + "1": { + "version": 1, + "hash": "2e1365c5535fa51c22eef79f67dd6444789bc829c27881367e3050e06e2ffbfe", "action": "add" } }, "NumpyArrayObject": { - "3": { - "version": 3, - "hash": "9e43f7bea261b729e7f6fa523ed050ba148fc1caf973ac996f9501af61b6ae8a", - "action": "add" - }, - "4": { - "version": 4, - "hash": "939a577d5929ac8a9c421b1d07acba1c33db63143e6614d533624e4548bf614b", + "1": { + "version": 1, + "hash": "05dd2917b7692b3daf4e7ad083a46fa7ec7a2be8faac8d4a654809189c986443", "action": "add" } }, "NumpyScalarObject": { - "3": { - "version": 3, - "hash": "5f6698e55cfb7105e279e9c28a3c30e759db143d2aa673abef448b78a2a39f69", - "action": "add" - }, - "4": { - "version": 4, - "hash": "5a4e86b712a242037958a3af68d2ab276dc7438db9b9551797323f051ca1a98a", + "1": { + "version": 1, + "hash": "8753e5c78270a5cacbf0439447724772f4765351a4a8b58b0a5c416a6b2c8b6e", "action": "add" } }, "NumpyBoolObject": { - "3": { - "version": 3, - "hash": "3c8db86e9ea1b6c1ee457610b05831c242fb0d375fcc8176bb64f9ae08a5eb00", - "action": "add" - }, - "4": { - "version": 4, - "hash": "b783d03c5d1fe9c4c8d346e2902c1e4ac7faac563c145ee4388c9c2c960963e2", + "1": { + "version": 1, + "hash": "331c44f8fa3d0a077f1aaad7313bae2c43b386d04def7b8bedae9fdf7690134d", "action": "add" } }, "PandasDataframeObject": { - "3": { - "version": 3, - "hash": "a130e7c5f88b4dbbef3030dd5b6b4bf7db3b4f60585f68b920bc250cee46022e", - "action": "add" - }, - "4": { - "version": 4, - "hash": "8b9a0b2c6652c60381c818d327d109404c735e62ad4e827fcd9042ec86325422", + "1": { + "version": 1, + "hash": "5e8018364cea31d5f185a901da4ab89846b02153ee7d041ee8a6d305ece31f90", "action": "add" } }, "PandasSeriesObject": { - "3": { - "version": 3, - "hash": "c36e22ffea7633813ac0d53fd2075de0606abe240acd72d206830c424f62bbc8", - "action": "add" - }, - "4": { - "version": 4, - "hash": "3286a2085b84d6499c97df36a78eca1a0d701e265a43f733cdf5e20ac78ab32d", + "1": { + "version": 1, + "hash": "b8bd482bf16fc7177e9778292cd42f8835b6ced2ce8dc88908b4b8e6d7c7528f", "action": "add" } }, "Change": { - "2": { - "version": 2, - "hash": "26073bb329dd19c65714ed0e2eb5a53aa4454adc02d7f1a22d6f4890149babcf", + "1": { + "version": 1, + "hash": "75fb9a5cd4e76b189ebe130a421d3921a0c251947a48bbb92a2ef1c315dc3c16", "action": "add" } }, "ChangeStatus": { - "2": { - "version": 2, - "hash": "260b340ed0b44c82a17e0d5662914a0cbf5ca02e62e36be2cc5e0dba0fc7ef01", + "1": { + "version": 1, + "hash": "c914a6f7637b555a51b71e8e197e591f7a2e28121e29b5dd586f87e0383d179d", "action": "add" } }, "ActionStoreChange": { - "2": { - "version": 2, - "hash": "98ae17d2677c72d5820ea6824a4f5fa1a5441fa4064d0fef9f6597056dfbcfcd", + "1": { + "version": 1, + "hash": "1a803bb08924b49f3114fd46e0e132f819d4d56be5e03a27e9fe90947ca26e85", "action": "add" } }, "CreateCustomImageChange": { - "2": { - "version": 2, - "hash": "4b4c9312ab44c7b7c1c68ba9548da80e2454f6b8ea99f7652e546c635fd7f37b", - "action": "add" - }, - "3": { - "version": 3, - "hash": "c6c74ecacd2be69c6d494e25c6ccc5df92f28a26273316424aa9daf0936d00d6", + "1": { + "version": 1, + "hash": "c3dbea3f49979fdcc517c0d13cd02739ca2fe86b370c42496a224f142ae31562", "action": "add" } }, "CreateCustomWorkerPoolChange": { - "2": { - "version": 2, - "hash": "cafeea65a74c11caf6dae2ebe47175d6d0947e35ca7b832240513eaab3fd63d8", - "action": "add" - }, - "3": { - "version": 3, - "hash": "3a96efb85ffaba05479c16963de853e7d4a77bd36db5341dbcb9426fb28fee7e", + "1": { + "version": 1, + "hash": "0355793dd58b364dcb84fff29714b6a26446bead3ba95c6d75e3200008e580f4", "action": "add" } }, "Request": { - "2": { - "version": 2, - "hash": "fad2e98b71d28b0039a631af4714858c495559ccbc93ccc2b1beed463f6d9452", - "action": "add" - }, - "3": { - "version": 3, - "hash": "25602e25c595d36f3755a8e8e16fc94ce9e832af36e8670f88406a0b180fcc51", + "1": { + "version": 1, + "hash": "1d69f5f0074114f99aa29c5ee77cb20b9151e5b50e77b026f11c3632a12efadf", "action": "add" } }, "RequestInfo": { - "2": { - "version": 2, - "hash": "65d41c5f3bc80202993c2167d42c030217956bd7932b92179f20016f47ab00b1", + "1": { + "version": 1, + "hash": "779562547744ebed64548f8021647292604fdf4256bf79685dfa14a1e56cc27b", "action": "add" } }, "RequestInfoFilter": { - "2": { - "version": 2, - "hash": "dea1b2af70f35864698027ca79eac4e1a23f03eb2faa26109259353a92afa960", + "1": { + "version": 1, + "hash": "bb881a003032f4676321218d7cd09580f4d64fccaa1cf9e118fdcd5c73c3d3a8", "action": "add" } }, "SubmitRequest": { - "2": { - "version": 2, - "hash": "76819df6cbf6288428a1fe523e88f53fdd6e7399ba8196140b96bcd891e67517", + "1": { + "version": 1, + "hash": "6c38b6ffd0a6f7442746e68b9ace7b21cb1dca7d2031929db5f9a302a280403f", "action": "add" } }, "ObjectMutation": { - "2": { - "version": 2, - "hash": "215cd56d33a58c8f5f725ad5ff32f62aa0b11330328ea952dc4df040983babbd", + "1": { + "version": 1, + "hash": "ce88096760ce9334599c8194ec97b0a1470651ad680d9d21b8826a0df0af2a36", "action": "add" } }, "EnumMutation": { - "2": { - "version": 2, - "hash": "9c3b684b8a0c165eee84a58fb0955b85c3f8c34d7bd34a31dd07a7e24ef82be2", + "1": { + "version": 1, + "hash": "5173fda73df17a344eb663b7692cca48bd46bf1773455439836b852cd165448c", "action": "add" } }, "UserCodeStatusChange": { - "3": { - "version": 3, - "hash": "f9243a74da84b4e5a8ea63bc73a027e385e8e0e90658cac161d9c35bbfbb981d", + "1": { + "version": 1, + "hash": "89aaf7f1368c782e3a1b9e79988877f6eaa05ab84365f7d321b757fde7fe86e7", "action": "add" } }, "SyncedUserCodeStatusChange": { - "3": { - "version": 3, - "hash": "133db7a12c8b883d8c7ce73a7c5b79e93400c7baeacbe9a32bd42c8188ed5252", + "1": { + "version": 1, + "hash": "d9ad2d341eb645bd50d06330cd30fd4c266f93e37b9f5391d58b78365fc440e6", "action": "add" } }, "TwinAPIContextView": { "1": { "version": 1, - "hash": "1a2836ba7832013912a649c4d73ed85ef5e3323af8f75f7d1bc9e7db4c483a60", + "hash": "e099eef32cb3a8a806cbdc54cc7fca96bed3d60344bd571163ec049db407938b", "action": "add" } }, "CustomAPIView": { "1": { "version": 1, - "hash": "4defa7437482a8499ffeb84705f74dd24ca44e03379040d7324c8f2eaeb9fe82", + "hash": "769e96bebd05736ab860591670fb6da19406239b0104ddc71bd092a134335146", "action": "add" } }, "CustomApiEndpoint": { "1": { "version": 1, - "hash": "1651e640f1b9fb3e39d86336ce7bbcd6539fb44344382d02342474b2f01e2464", + "hash": "ec4a217585336d1b59c93c18570443a63f4fbb24d2c088fbacf80bcf389d23e8", "action": "add" } }, "PrivateAPIEndpoint": { "1": { "version": 1, - "hash": "c703dfc895ad585d15b2b79b7641555dbacaad80016842dc1c10fa46297a2691", + "hash": "6d7d143432c2811c520ab6dade005ba40173b590e5c676be04f5921b970ef938", "action": "add" } }, "PublicAPIEndpoint": { "1": { "version": 1, - "hash": "3586329beedf63913954d811d46bda3fcf8f1f25669f27b0c35e624a4cdf1370", + "hash": "3bf51fc33aa8feb1abc9d0ef792e8889da31a57050430e0bd8e17f2065ff8734", "action": "add" } }, "UpdateTwinAPIEndpoint": { "1": { "version": 1, - "hash": "92aeddf7a8cb90a542c600c0daeca0c236888cadcc5274ec81ea99516fe3199b", + "hash": "851e59412716e73c7f70a696619e0b375ce136b43f6fe2ea784747091caba5d8", "action": "add" } }, "CreateTwinAPIEndpoint": { "1": { "version": 1, - "hash": "5efa208b4003c5e6580a567dd1677bb298e9a08c3c5c8e4291e3c68b9a5865f2", + "hash": "3d0b84dae95ebcc6647b5aabe54e65b3c6bf957665fde57d8037806a4aac13be", "action": "add" } }, "TwinAPIEndpoint": { "1": { "version": 1, - "hash": "ca4925c40e21464f49ecb0b9c2067328a7fa95242be91ca02f705b7b2230fa6e", + "hash": "d1947b8f9c80d6c9b443e5a9f0758afa8849a5f12b9a511feefd7e4f82c374f4", "action": "add" } }, "SyncState": { - "2": { - "version": 2, - "hash": "22b70f9e51f667204ab4653cef18363831d50175e8962b62ac830b1f11ee1857", + "1": { + "version": 1, + "hash": "9a3f0bb973858b55bc766c9770c4d9abcc817898f797d94a89938650c0c67868", "action": "add" - }, - "3": { - "version": 3, - "hash": "a06fb5e7826b4a33bc738280b661a2384fd4d4757551945b9302d01a1abaff85", + } + }, + "WorkerSettings": { + "1": { + "version": 1, + "hash": "b8ddbe75a95b0312a64b5f25e0fc415aeac5c391975d02b515db8c848482f737", "action": "add" } }, - "ServerPeer": { - "2": { - "version": 2, - "hash": "daf8c5226dfa253ad13719aed78625c9d982b17a8927ffb818ab7cb56c255153", + "HTTPServerRoute": { + "1": { + "version": 1, + "hash": "938245604a9c7e50001299afff5b669b2548364e356fed22a22780497831bf81", + "action": "add" + } + }, + "PythonServerRoute": { + "1": { + "version": 1, + "hash": "a068d8f942d55ecb6d45af88a27c6ebf208584275bf589cbc308df3f774ab9a9", + "action": "add" + } + }, + "VeilidServerRoute": { + "1": { + "version": 1, + "hash": "e676bc165601d2ede69707a4b6168ed4674f3f98887026d098a2dd4da4dfd097", "action": "add" - }, - "3": { - "version": 3, - "hash": "eee060523d89db3abc29fd6e6997f9a8210d221923f768e4a672521e8fb1fb31", + } + }, + "ServerPeer": { + "1": { + "version": 1, + "hash": "0d5f252018e324ea0d2dcb5c2ad8bd15707220565fce4f14de7f63a8f9e4391b", "action": "add" } }, "ServerPeerUpdate": { "1": { "version": 1, - "hash": "38a171ff362dd1da6d2eb34d51aea753496b2860d6b25adc595e6241ca5bf63c", + "hash": "0b854b57db7a18118c1fd8f31495b2ba4eeb9fbe4f24c631ff112418a94570d3", "action": "add" } }, "AssociationRequestChange": { "1": { "version": 1, - "hash": "2102685cc30aec0d5a2b1f62f38b475745dc129599fce6c57e2bb92d13f1179d", + "hash": "0134ac0002879c85fc9ddb06bed6306a8905c8434b0a40d3a96ce24a7bd4da90", "action": "add" } }, "QueueItem": { - "4": { - "version": 4, - "hash": "aa04c1a0807164b9307a18d250e09eaf27f74efef61bec9392cd386eb43aa5e6", + "1": { + "version": 1, + "hash": "1db212c46b6c56ccc5579cfe2141b693f0cd9286e2ede71210393e8455379bf1", "action": "add" } }, "ActionQueueItem": { - "3": { - "version": 3, - "hash": "df2399704de2c69a8a10524133bdb062bee6c48ad18b713d7d7f23fab1819bf7", + "1": { + "version": 1, + "hash": "396d579dfc2e2b36b9fbed2f204bffcca1bea7ee2db7175045dd3328ebf08718", "action": "add" } }, "APIEndpointQueueItem": { "1": { "version": 1, - "hash": "d94c0bc1efc18f0217b7342ac49a3ddd4d26df9ffa678a706e84643f7cd3df00", + "hash": "f04b3990a8d29c116d301e70df54d58f188895307a411dc13a666ff764ffd8dd", "action": "add" } }, - "SyftObjectMigrationState": { - "2": { - "version": 2, - "hash": "51f416fbce4ff408903b96aafa924fc3adde33b19172122b06acd04a1651c7ab", + "ZMQClientConfig": { + "1": { + "version": 1, + "hash": "36ee8f75067d5144f0ed062cdc79466caae16b7a128231d89b6b430174843bde", + "action": "add" + } + }, + "SQLiteStoreConfig": { + "1": { + "version": 1, + "hash": "ad062a5f863ae84683867d2a6a5e1d4420c010a64b88bc7b392106e33d71ac03", "action": "add" } }, "ProjectThreadMessage": { - "2": { - "version": 2, - "hash": "506b292e24486632a2e7d816c48a3051b23527c8a3a35f726ffd7249222b15bb", + "1": { + "version": 1, + "hash": "99256d7592577d1e37df94a06eabc0a287f2d79e144c51fd719315e278edb46d", "action": "add" } }, "ProjectMessage": { - "2": { - "version": 2, - "hash": "1fabc4acc439749ba2f62f1cf01b56c91a31d59d908bfe206822f88552d3ce71", + "1": { + "version": 1, + "hash": "b5004b6354f71b19c81dd5f4b20bf446e0b959f5608a22707e96b944dd8175b0", "action": "add" } }, "ProjectRequestResponse": { - "2": { - "version": 2, - "hash": "7b08ce278d58b8ee96d7bc594079c808ec06fd148f14aedc638aba4075d05a1e", + "1": { + "version": 1, + "hash": "52162a8a779a4a301d8755691bf4cf994c86b9f650f9e8c8a923b44e635b1bc0", "action": "add" } }, "ProjectRequest": { - "2": { - "version": 2, - "hash": "ceb9fc7a258dc1574ced311051466f2686f29b1bd65828810f2c87d2022c8533", + "1": { + "version": 1, + "hash": "dc684135d5a5a48e5fc7988598c1e6e0de76cf1c5995f1c283fcf63d0eb4d24f", "action": "add" } }, "AnswerProjectPoll": { - "2": { - "version": 2, - "hash": "b9bd5e61af04a96b93fd9f2e2d8548f8defc391258014c4fbbe4dc80f47c9705", + "1": { + "version": 1, + "hash": "c83d83a5ba6cc034d5061df200b3f1d029aa770b1e13dbef959bb1790323dc6e", "action": "add" } }, "ProjectPoll": { - "2": { - "version": 2, - "hash": "0dcad5d725714cd023f6d7d40139bb6657a9f39a027ee67442b970c43006623a", + "1": { + "version": 1, + "hash": "ecf69b3b324e0bee9c82295796d44c4e8f796496cdc9db6d4302c2f160566466", "action": "add" } }, "Project": { - "2": { - "version": 2, - "hash": "2088e56054a45f13600d63cb44f00674dfa43e79e63639c912c0e58302526e3c", + "1": { + "version": 1, + "hash": "de86a1163ddbcd1cc3cc2b1b5dfcb85a8ad9f9d4bbc759c2b1f92a0d0a2ff184", "action": "add" } }, "ProjectSubmit": { - "2": { - "version": 2, - "hash": "5341778735a00699b085a0d99afca630cbff8d25aa0f2205a09f74e93263c5e0", - "action": "add" - } - }, - "ZMQClientConfig": { - "4": { - "version": 4, - "hash": "f54c62694a0b058ebf41d48b783b70423894a0609f50bc3d347b7b135d142674", - "action": "add" - } - }, - "SQLiteStoreConfig": { - "2": { - "version": 2, - "hash": "b6d391bd7884886daef88b08734cf41b4d278b474c22cfc3574b9e7ec140c9e3", - "action": "add" - } - }, - "Plan": { - "2": { - "version": 2, - "hash": "eec308b8fd9437fc74a65f0cf70dff586130b35866d1e1512de49d45e7896981", - "action": "add" - } - }, - "StoreMetadata": { "1": { "version": 1, - "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", + "hash": "7555ba11ee5a814dcd9c45647300020f7359efc1081559940990cbd745936cac", "action": "add" } }, - "MigrationData": { + "Plan": { "1": { "version": 1, - "hash": "ae07a6345762b8ebe9d2a100776e2405fd17516c9d224913a3358c96480ba889", + "hash": "ed05cb87aec832098fc464ac36cd6bceaab705463d0d2fa1b2d8e1ccc510018c", "action": "add" } } diff --git a/packages/grid/helm/syft/values.yaml b/packages/grid/helm/syft/values.yaml index 48bb41fa11a..69ee750665b 100644 --- a/packages/grid/helm/syft/values.yaml +++ b/packages/grid/helm/syft/values.yaml @@ -1,7 +1,7 @@ global: # Affects only backend, frontend, and seaweedfs containers registry: docker.io - version: 0.8.7-beta.14 + version: 0.8.7-beta.15 # Force default secret values for development. DO NOT SET THIS TO FALSE IN PRODUCTION randomizedSecrets: true diff --git a/packages/syft/setup.cfg b/packages/syft/setup.cfg index 9ee693855b2..ee6e8c2006b 100644 --- a/packages/syft/setup.cfg +++ b/packages/syft/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = syft -version = attr: "0.8.7-beta.14" +version = attr: "0.8.7-beta.15" description = Perform numpy-like analysis on data that remains in someone elses server author = OpenMined author_email = info@openmined.org diff --git a/packages/syft/src/syft/VERSION b/packages/syft/src/syft/VERSION index 0c01f370f55..27f3763909a 100644 --- a/packages/syft/src/syft/VERSION +++ b/packages/syft/src/syft/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.14" +__version__ = "0.8.7-beta.15" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index d61d8de882f..eff14c659df 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.8.7-beta.14" +__version__ = "0.8.7-beta.15" # stdlib from collections.abc import Callable diff --git a/packages/syftcli/manifest.yml b/packages/syftcli/manifest.yml index be37bbf6f71..1e591898eca 100644 --- a/packages/syftcli/manifest.yml +++ b/packages/syftcli/manifest.yml @@ -1,11 +1,11 @@ manifestVersion: 1.0 -syftVersion: 0.8.7-beta.14 -dockerTag: 0.8.7-beta.14 +syftVersion: 0.8.7-beta.15 +dockerTag: 0.8.7-beta.15 images: - - docker.io/openmined/syft-frontend:0.8.7-beta.14 - - docker.io/openmined/syft-backend:0.8.7-beta.14 + - docker.io/openmined/syft-frontend:0.8.7-beta.15 + - docker.io/openmined/syft-backend:0.8.7-beta.15 - docker.io/library/mongo:7.0.4 - docker.io/traefik:v2.11.0 From 94faeb3c05d2204c19bc2ec6e90ef867e11d6c93 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Thu, 18 Jul 2024 16:45:32 +0530 Subject: [PATCH 094/117] fix dev values filename in syft.test.helm --- tox.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tox.ini b/tox.ini index ea12d1b8003..d0e58bc3f55 100644 --- a/tox.ini +++ b/tox.ini @@ -723,9 +723,9 @@ commands = echo "Installing local helm charts"; \ if [[ "{posargs}" == "override" ]]; then \ echo "Overriding resourcesPreset"; \ - helm install ${CLUSTER_NAME} ./helm/syft -f ./helm/values.dev.yaml --kube-context k3d-${CLUSTER_NAME} --namespace syft --create-namespace --set server.resourcesPreset=null --set seaweedfs.resourcesPreset=null --set mongo.resourcesPreset=null --set registry.resourcesPreset=null --set proxy.resourcesPreset=null --set frontend.resourcesPreset=null; \ + helm install ${CLUSTER_NAME} ./helm/syft -f ./helm/examples/dev/base.yaml --kube-context k3d-${CLUSTER_NAME} --namespace syft --create-namespace --set server.resourcesPreset=null --set seaweedfs.resourcesPreset=null --set mongo.resourcesPreset=null --set registry.resourcesPreset=null --set proxy.resourcesPreset=null --set frontend.resourcesPreset=null; \ else \ - helm install ${CLUSTER_NAME} ./helm/syft -f ./helm/values.dev.yaml --kube-context k3d-${CLUSTER_NAME} --namespace syft --create-namespace; \ + helm install ${CLUSTER_NAME} ./helm/syft -f ./helm/examples/dev/base.yaml --kube-context k3d-${CLUSTER_NAME} --namespace syft --create-namespace; \ fi \ else \ echo "Installing helm charts from repo for syft version: ${SYFT_VERSION}"; \ @@ -733,9 +733,9 @@ commands = helm repo update openmined; \ if [[ "{posargs}" == "override" ]]; then \ echo "Overriding resourcesPreset"; \ - helm install ${CLUSTER_NAME} openmined/syft --version=${SYFT_VERSION} -f ./helm/values.dev.yaml --kube-context k3d-${CLUSTER_NAME} --namespace syft --create-namespace --set server.resourcesPreset=null --set seaweedfs.resourcesPreset=null --set mongo.resourcesPreset=null --set registry.resourcesPreset=null --set proxy.resourcesPreset=null --set frontend.resourcesPreset=null; \ + helm install ${CLUSTER_NAME} openmined/syft --version=${SYFT_VERSION} -f ./helm/examples/dev/base.yaml --kube-context k3d-${CLUSTER_NAME} --namespace syft --create-namespace --set server.resourcesPreset=null --set seaweedfs.resourcesPreset=null --set mongo.resourcesPreset=null --set registry.resourcesPreset=null --set proxy.resourcesPreset=null --set frontend.resourcesPreset=null; \ else \ - helm install ${CLUSTER_NAME} openmined/syft --version=${SYFT_VERSION} -f ./helm/values.dev.yaml --kube-context k3d-${CLUSTER_NAME} --namespace syft --create-namespace; \ + helm install ${CLUSTER_NAME} openmined/syft --version=${SYFT_VERSION} -f ./helm/examples/dev/base.yaml --kube-context k3d-${CLUSTER_NAME} --namespace syft --create-namespace; \ fi \ fi' From cd609c467bca032174b4f24d0e36d7a529f93d02 Mon Sep 17 00:00:00 2001 From: Aziz Berkay Yesilyurt Date: Thu, 18 Jul 2024 13:34:43 +0200 Subject: [PATCH 095/117] revert asset.data change --- packages/syft/src/syft/service/dataset/dataset.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index 5ab3eb1411b..db5fe2f482f 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -289,8 +289,6 @@ def data(self) -> Any: if api is None or api.services is None: return None res = api.services.action.get(self.action_id) - if isinstance(res, str): - return SyftError(message=f"Could not access private data. {str(res)}") if self.has_permission(res): return res.syft_action_data else: From 8a126f937b75224073669b90bd78e0d0d97451a2 Mon Sep 17 00:00:00 2001 From: Aziz Berkay Yesilyurt Date: Thu, 18 Jul 2024 13:56:14 +0200 Subject: [PATCH 096/117] set log level to critical if not in dev mode --- packages/syft/src/syft/server/uvicorn.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/syft/src/syft/server/uvicorn.py b/packages/syft/src/syft/server/uvicorn.py index 3626db6aa13..953d19a4c2e 100644 --- a/packages/syft/src/syft/server/uvicorn.py +++ b/packages/syft/src/syft/server/uvicorn.py @@ -1,5 +1,6 @@ # stdlib from collections.abc import Callable +import logging import multiprocessing import multiprocessing.synchronize import os @@ -122,7 +123,8 @@ def run_uvicorn( starting_uvicorn_event: multiprocessing.synchronize.Event, **kwargs: Any, ) -> None: - should_reset = kwargs.get("dev_mode") and kwargs.get("reset") + dev_mode = kwargs.get("dev_mode") + should_reset = dev_mode and kwargs.get("reset") if should_reset: print("Found `reset=True` in the launch configuration. Resetting the server...") @@ -140,6 +142,12 @@ def run_uvicorn( except Exception: # nosec print(f"Failed to kill python process on port: {port}") + log_level = "critical" + if dev_mode: + log_level = "info" + logging.getLogger("uvicorn").setLevel(logging.CRITICAL) + logging.getLogger("uvicorn.access").setLevel(logging.CRITICAL) + if kwargs.get("debug"): attach_debugger() @@ -166,8 +174,9 @@ def run_uvicorn( host=host, port=port, factory=True, - reload=kwargs.get("dev_mode"), - reload_dirs=[Path(__file__).parent.parent] if kwargs.get("dev_mode") else None, + reload=dev_mode, + reload_dirs=[Path(__file__).parent.parent] if dev_mode else None, + log_level=log_level, ) From 9c56616217730549e112c5cf9df8d8d13f06c1c1 Mon Sep 17 00:00:00 2001 From: Aziz Berkay Yesilyurt Date: Thu, 18 Jul 2024 14:02:49 +0200 Subject: [PATCH 097/117] data returns None instead and displays a warning --- .../01-data-scientist-submit-code.ipynb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb b/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb index 6063d233753..13e52c83015 100644 --- a/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb +++ b/notebooks/tutorials/model-training/01-data-scientist-submit-code.ipynb @@ -4,7 +4,9 @@ "cell_type": "code", "execution_count": null, "id": "0", - "metadata": {}, + "metadata": { + "metadata": {} + }, "outputs": [], "source": [ "# third party\n", @@ -27,7 +29,9 @@ "cell_type": "code", "execution_count": null, "id": "2", - "metadata": {}, + "metadata": { + "metadata": {} + }, "outputs": [], "source": [ "server = sy.orchestra.launch(name=\"mnist-torch-datasite\", dev_mode=True)\n", @@ -46,7 +50,9 @@ "cell_type": "code", "execution_count": null, "id": "4", - "metadata": {}, + "metadata": { + "metadata": {} + }, "outputs": [], "source": [ "datasets = ds_client.datasets.get_all()\n", @@ -103,7 +109,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert isinstance(training_images.data, sy.SyftError)\n", + "assert training_images.data is None\n", "training_labels.data" ] }, From 01f51e62e0c5c7aa7924b3b3ec4656329decea1f Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Thu, 18 Jul 2024 14:26:49 +0200 Subject: [PATCH 098/117] fix py310 any serialization --- notebooks/api/0.8/00-load-data.ipynb | 19 +++++++++++-------- .../src/syft/serde/recursive_primitives.py | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/notebooks/api/0.8/00-load-data.ipynb b/notebooks/api/0.8/00-load-data.ipynb index 5370bd2e595..0d7d6b21a57 100644 --- a/notebooks/api/0.8/00-load-data.ipynb +++ b/notebooks/api/0.8/00-load-data.ipynb @@ -609,11 +609,7 @@ }, { "cell_type": "markdown", - "metadata": { - "jupyter": { - "source_hidden": true - } - }, + "metadata": {}, "source": [ "### Reading the Syft Dataset from Datasite Server\n", "\n", @@ -708,6 +704,13 @@ " server.land()" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, @@ -718,9 +721,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python [conda env:syft310] *", "language": "python", - "name": "python3" + "name": "conda-env-syft310-py" }, "language_info": { "codemirror_mode": { @@ -732,7 +735,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.10.14" }, "toc": { "base_numbering": 1, diff --git a/packages/syft/src/syft/serde/recursive_primitives.py b/packages/syft/src/syft/serde/recursive_primitives.py index e1036eb4f94..38d8281434d 100644 --- a/packages/syft/src/syft/serde/recursive_primitives.py +++ b/packages/syft/src/syft/serde/recursive_primitives.py @@ -446,6 +446,8 @@ def recursive_serde_register_type( canonical_name: str | None = None, version: int | None = None, ) -> None: + # former case is for instance for _GerericAlias itself or UnionGenericAlias + # Latter case is true for for instance List[str], which is currently not used if (isinstance(t, type) and issubclass(t, _GenericAlias)) or issubclass( type(t), _GenericAlias ): @@ -500,6 +502,14 @@ def deserialize_typevar(type_blob: bytes) -> type: return TypeVar(name=name) # type: ignore +def serialize_any(serialized_type: TypeVar) -> bytes: + return b"" + + +def deserialize_any(type_blob: bytes) -> type: # type: ignore + return Any # type: ignore + + recursive_serde_register( UnionType, serialize=serialize_union_type, @@ -524,6 +534,13 @@ def deserialize_typevar(type_blob: bytes) -> type: deserialize=deserialize_typevar, version=1, ) +recursive_serde_register( + Any, + canonical_name="Any", + serialize=serialize_any, + deserialize=deserialize_any, + version=1, +) recursive_serde_register_type( _UnionGenericAlias, @@ -544,7 +561,7 @@ def deserialize_typevar(type_blob: bytes) -> type: ) recursive_serde_register_type(GenericAlias, canonical_name="GenericAlias", version=1) -recursive_serde_register_type(Any, canonical_name="Any", version=1) +# recursive_serde_register_type(Any, canonical_name="Any", version=1) recursive_serde_register_type(EnumMeta, canonical_name="EnumMeta", version=1) recursive_serde_register_type(ABCMeta, canonical_name="ABCMeta", version=1) From 6566332fcdf98c6dbcd071b4f9b526058f0f074e Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Thu, 18 Jul 2024 18:14:40 +0530 Subject: [PATCH 099/117] revert asset.data is None in gateway_test --- tests/integration/network/gateway_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/network/gateway_test.py b/tests/integration/network/gateway_test.py index 39ddc0bad5d..fd4b9751c42 100644 --- a/tests/integration/network/gateway_test.py +++ b/tests/integration/network/gateway_test.py @@ -222,7 +222,7 @@ def test_dataset_search(set_env_var, gateway_port: int, datasite_1_port: int) -> assert isinstance(dataset, Dataset) assert len(dataset.assets) == 1 assert isinstance(dataset.assets[0].mock, np.ndarray) - assert isinstance(dataset.assets[0].data, SyftError) + assert dataset.assets[0].data is None # search a wrong dataset should return an empty list wrong_search = sy.search(_random_hash()) From 3cf2ddf2528e380635302ac5f9a17e6e860c9a77 Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Thu, 18 Jul 2024 14:51:16 +0200 Subject: [PATCH 100/117] merge undo nb changes --- notebooks/api/0.8/00-load-data.ipynb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/notebooks/api/0.8/00-load-data.ipynb b/notebooks/api/0.8/00-load-data.ipynb index 0d7d6b21a57..5370bd2e595 100644 --- a/notebooks/api/0.8/00-load-data.ipynb +++ b/notebooks/api/0.8/00-load-data.ipynb @@ -609,7 +609,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "jupyter": { + "source_hidden": true + } + }, "source": [ "### Reading the Syft Dataset from Datasite Server\n", "\n", @@ -704,13 +708,6 @@ " server.land()" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, @@ -721,9 +718,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python [conda env:syft310] *", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "conda-env-syft310-py" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -735,7 +732,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.14" + "version": "3.12.2" }, "toc": { "base_numbering": 1, From 6d290905c989aebeaef546d4c67a3d5aec2fe120 Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Thu, 18 Jul 2024 15:21:48 +0200 Subject: [PATCH 101/117] fix syftobject --- .../src/syft/protocol/protocol_version.json | 19 +++++++++++++------ packages/syft/src/syft/types/syft_object.py | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index a1098e600ee..b4793310320 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -1052,16 +1052,23 @@ } }, "SyftObject": { - "2": { - "version": 2, - "hash": "26efd140219eb651d18467b0430b9dbde17c57670f050e300823075f6e44d3e5", + "1": { + "version": 1, + "hash": "bb70d874355988908d3a92a3941d6613a6995a4850be3b6a0147f4d387724406", "action": "add" } }, "ProjectEvent": { - "2": { - "version": 2, - "hash": "cbe61714b816b769a856fe7b47c3001e6da716883b2845e03485e3e7b0a02b91", + "1": { + "version": 1, + "hash": "dc0486c52daebd5e98c2b3b03ffd9a9a14bc3d86d8dc0c23e41ebf6c31fe2ffb", + "action": "add" + } + }, + "SyftObjectVersioned": { + "1": { + "version": 1, + "hash": "7c842dcdbb57e2528ffa690ea18c19fff3c8a591811d40cad2b19be3100e2ff4", "action": "add" } } diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 3a84ef5bc3e..f987479cafc 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -346,6 +346,7 @@ def __lt__(self, other: Self) -> bool: return self.utc_timestamp < other.utc_timestamp +@serializable() class SyftObject(SyftObjectVersioned): __canonical_name__ = "SyftObject" __version__ = SYFT_OBJECT_VERSION_1 From 3fbbdf301747696b1480f8a3b1aa77b8dc3078c1 Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Thu, 18 Jul 2024 18:17:20 +0200 Subject: [PATCH 102/117] fix any --- packages/syft/src/syft/types/syft_object_registry.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/syft/src/syft/types/syft_object_registry.py b/packages/syft/src/syft/types/syft_object_registry.py index 68952b5874b..a86bed7ddee 100644 --- a/packages/syft/src/syft/types/syft_object_registry.py +++ b/packages/syft/src/syft/types/syft_object_registry.py @@ -80,7 +80,15 @@ def get_canonical_name_version(cls, obj: Any) -> tuple[str, int]: @classmethod def get_serde_properties(cls, canonical_name: str, version: int) -> tuple: - return cls.__object_serialization_registry__[canonical_name][version] + try: + return cls.__object_serialization_registry__[canonical_name][version] + except Exception: + # This is a hack for python 3.10 in which Any is not a type + # if the server uses py>3.10 and the client 3.10 this goes wrong + if canonical_name == "Any_typing._SpecialForm": + return cls.__object_serialization_registry__["Any"][version] + else: + raise @classmethod def get_serde_class(cls, canonical_name: str, version: int) -> type["SyftObject"]: From 7c35a7f60a30eabc7e97b00376b976d53d81193d Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Fri, 19 Jul 2024 12:43:08 +0530 Subject: [PATCH 103/117] hardcode syft version to latest beta in 10-container-images --- notebooks/api/0.8/10-container-images.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/notebooks/api/0.8/10-container-images.ipynb b/notebooks/api/0.8/10-container-images.ipynb index 22e4706bf7f..ab3f6d0338b 100644 --- a/notebooks/api/0.8/10-container-images.ipynb +++ b/notebooks/api/0.8/10-container-images.ipynb @@ -150,7 +150,8 @@ " if (bool(os.environ[\"DEV_MODE\"]) and running_as_container)\n", " else sy.__version__\n", ")\n", - "syft_base_worker_tag" + "# TODO: Remove this once the stable syft version is released\n", + "syft_base_worker_tag = \"0.8.7-beta.15\"" ] }, { From 8413d4556cd681ba2963026000aa2ed6c310e76a Mon Sep 17 00:00:00 2001 From: alfred-openmined-bot <145415986+alfred-openmined-bot@users.noreply.github.com> Date: Fri, 19 Jul 2024 08:02:48 +0000 Subject: [PATCH 104/117] [syft]bump version --- .bumpversion.cfg | 2 +- VERSION | 2 +- packages/grid/VERSION | 2 +- .../backend/grid/images/worker_cpu.dockerfile | 2 +- packages/grid/devspace.yaml | 2 +- packages/grid/frontend/package.json | 2 +- packages/grid/helm/repo/index.yaml | 193 ++++++++++-------- .../grid/helm/repo/syft-0.8.7-beta.16.tgz | Bin 0 -> 18043 bytes packages/grid/helm/syft/Chart.yaml | 4 +- packages/grid/helm/syft/values.yaml | 2 +- packages/syft/setup.cfg | 2 +- packages/syft/src/syft/VERSION | 2 +- packages/syft/src/syft/__init__.py | 2 +- packages/syftcli/manifest.yml | 8 +- 14 files changed, 119 insertions(+), 106 deletions(-) create mode 100644 packages/grid/helm/repo/syft-0.8.7-beta.16.tgz diff --git a/.bumpversion.cfg b/.bumpversion.cfg index b503c8bb0f2..112787ac5a9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.7-beta.15 +current_version = 0.8.7-beta.16 tag = False tag_name = {new_version} commit = True diff --git a/VERSION b/VERSION index 27f3763909a..0923036f0b3 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.15" +__version__ = "0.8.7-beta.16" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/VERSION b/packages/grid/VERSION index 27f3763909a..0923036f0b3 100644 --- a/packages/grid/VERSION +++ b/packages/grid/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.15" +__version__ = "0.8.7-beta.16" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/backend/grid/images/worker_cpu.dockerfile b/packages/grid/backend/grid/images/worker_cpu.dockerfile index 179dc4fa70f..abc64b067af 100644 --- a/packages/grid/backend/grid/images/worker_cpu.dockerfile +++ b/packages/grid/backend/grid/images/worker_cpu.dockerfile @@ -5,7 +5,7 @@ # NOTE: This dockerfile will be built inside a syft-backend container in PROD # Hence COPY will not work the same way in DEV vs. PROD -ARG SYFT_VERSION_TAG="0.8.7-beta.15" +ARG SYFT_VERSION_TAG="0.8.7-beta.16" FROM openmined/syft-backend:${SYFT_VERSION_TAG} # should match base image python version diff --git a/packages/grid/devspace.yaml b/packages/grid/devspace.yaml index 7c7f125feec..ffcc497ddb4 100644 --- a/packages/grid/devspace.yaml +++ b/packages/grid/devspace.yaml @@ -28,7 +28,7 @@ vars: DOCKER_IMAGE_RATHOLE: openmined/syft-rathole DOCKER_IMAGE_ENCLAVE_ATTESTATION: openmined/syft-enclave-attestation CONTAINER_REGISTRY: "docker.io" - VERSION: "0.8.7-beta.15" + VERSION: "0.8.7-beta.16" PLATFORM: $(uname -m | grep -q 'arm64' && echo "arm64" || echo "amd64") # This is a list of `images` that DevSpace can build for this project diff --git a/packages/grid/frontend/package.json b/packages/grid/frontend/package.json index f0abfb28bee..75dc49b4979 100644 --- a/packages/grid/frontend/package.json +++ b/packages/grid/frontend/package.json @@ -1,6 +1,6 @@ { "name": "syft-ui", - "version": "0.8.7-beta.15", + "version": "0.8.7-beta.16", "private": true, "scripts": { "dev": "pnpm i && vite dev --host --port 80", diff --git a/packages/grid/helm/repo/index.yaml b/packages/grid/helm/repo/index.yaml index a34bf857801..c2d0dba9c21 100644 --- a/packages/grid/helm/repo/index.yaml +++ b/packages/grid/helm/repo/index.yaml @@ -1,9 +1,22 @@ apiVersion: v1 entries: syft: + - apiVersion: v2 + appVersion: 0.8.7-beta.16 + created: "2024-07-19T08:00:47.014272764Z" + description: Perform numpy-like analysis on data that remains in someone elses + server + digest: 75190eae57b64c2c47ab4a7fe3c6e94f35eb8045807a843ec8d7b26585c9e840 + home: https://github.com/OpenMined/PySyft/ + icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png + name: syft + type: application + urls: + - https://openmined.github.io/PySyft/helm/syft-0.8.7-beta.16.tgz + version: 0.8.7-beta.16 - apiVersion: v2 appVersion: 0.8.7-beta.15 - created: "2024-07-18T09:44:18.697011581Z" + created: "2024-07-19T08:00:47.012948682Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 56879d9a9f10febce88676d3d20621d74d17f9e33f5df6ae1e9bc3078c216f0c @@ -16,7 +29,7 @@ entries: version: 0.8.7-beta.15 - apiVersion: v2 appVersion: 0.8.7-beta.14 - created: "2024-07-18T09:44:18.696136502Z" + created: "2024-07-19T08:00:47.011858282Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e7cbca1d603ba11e09ae2a3089cfdafaa08cfa07c553c4f0fb8b42f8d3028f7 @@ -29,7 +42,7 @@ entries: version: 0.8.7-beta.14 - apiVersion: v2 appVersion: 0.8.7-beta.13 - created: "2024-07-18T09:44:18.695250653Z" + created: "2024-07-19T08:00:47.010938574Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1dbe3ecdfec57bf25020cbcff783fab908f0eb0640ad684470b2fd1da1928005 @@ -42,7 +55,7 @@ entries: version: 0.8.7-beta.13 - apiVersion: v2 appVersion: 0.8.7-beta.12 - created: "2024-07-18T09:44:18.694546535Z" + created: "2024-07-19T08:00:47.010210325Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e92b2f3a522dabb3a79ff762a7042ae16d2bf3a53eebbb2885a69b9f834d109c @@ -55,7 +68,7 @@ entries: version: 0.8.7-beta.12 - apiVersion: v2 appVersion: 0.8.7-beta.11 - created: "2024-07-18T09:44:18.693800357Z" + created: "2024-07-19T08:00:47.009504488Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 099f6cbd44b699ee2410a4be012ed1a8a65bcacb06a43057b2779d7fe34fc0ad @@ -68,7 +81,7 @@ entries: version: 0.8.7-beta.11 - apiVersion: v2 appVersion: 0.8.7-beta.10 - created: "2024-07-18T09:44:18.693068297Z" + created: "2024-07-19T08:00:47.008807007Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 00773cb241522e281c1915339fc362e047650e08958a736e93d6539f44cb5e25 @@ -81,7 +94,7 @@ entries: version: 0.8.7-beta.10 - apiVersion: v2 appVersion: 0.8.7-beta.9 - created: "2024-07-18T09:44:18.703118454Z" + created: "2024-07-19T08:00:47.019477968Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a3f8e85d9ddef7a644b959fcc2fcb0fc08f7b6abae1045e893d0d62fa4ae132e @@ -94,7 +107,7 @@ entries: version: 0.8.7-beta.9 - apiVersion: v2 appVersion: 0.8.7-beta.8 - created: "2024-07-18T09:44:18.70245435Z" + created: "2024-07-19T08:00:47.018823548Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a422ac88d8fd1fb80d5004d5eb6e95fa9efc7f6a87da12e5ac04829da7f04c4d @@ -107,7 +120,7 @@ entries: version: 0.8.7-beta.8 - apiVersion: v2 appVersion: 0.8.7-beta.7 - created: "2024-07-18T09:44:18.701730695Z" + created: "2024-07-19T08:00:47.018142819Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0dc313a1092e6256a7c8aad002c8ec380b3add2c289d680db1e238a336399b7a @@ -120,7 +133,7 @@ entries: version: 0.8.7-beta.7 - apiVersion: v2 appVersion: 0.8.7-beta.6 - created: "2024-07-18T09:44:18.700741185Z" + created: "2024-07-19T08:00:47.017502776Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 052a2ec1102d2a4c9915f95647abd4a6012f56fa05a106f4952ee9b55bf7bae8 @@ -133,7 +146,7 @@ entries: version: 0.8.7-beta.6 - apiVersion: v2 appVersion: 0.8.7-beta.5 - created: "2024-07-18T09:44:18.699545536Z" + created: "2024-07-19T08:00:47.01686135Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1728af756907c3fcbe87c2fd2de014a2d963c22a4c2eb6af6596b525a9b9a18a @@ -146,7 +159,7 @@ entries: version: 0.8.7-beta.5 - apiVersion: v2 appVersion: 0.8.7-beta.4 - created: "2024-07-18T09:44:18.698909676Z" + created: "2024-07-19T08:00:47.016237437Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 387a57a3904a05ed61e92ee48605ef6fd5044ff7e822e0924e0d4c485e2c88d2 @@ -159,7 +172,7 @@ entries: version: 0.8.7-beta.4 - apiVersion: v2 appVersion: 0.8.7-beta.3 - created: "2024-07-18T09:44:18.698278614Z" + created: "2024-07-19T08:00:47.015602895Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 3668002b7a4118516b2ecd61d6275f60d83fc12841587ab8f62e1c1200731c67 @@ -172,7 +185,7 @@ entries: version: 0.8.7-beta.3 - apiVersion: v2 appVersion: 0.8.7-beta.2 - created: "2024-07-18T09:44:18.697608639Z" + created: "2024-07-19T08:00:47.014959215Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e62217ffcadee2b8896ab0543f9ccc42f2df898fd979438ac9376d780b802af7 @@ -185,7 +198,7 @@ entries: version: 0.8.7-beta.2 - apiVersion: v2 appVersion: 0.8.7-beta.1 - created: "2024-07-18T09:44:18.691587681Z" + created: "2024-07-19T08:00:47.008129384Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 553981fe1d5c980e6903b3ff2f1b9b97431f6dd8aee91e3976bcc5594285235e @@ -198,7 +211,7 @@ entries: version: 0.8.7-beta.1 - apiVersion: v2 appVersion: 0.8.6 - created: "2024-07-18T09:44:18.691075221Z" + created: "2024-07-19T08:00:47.00760616Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ddbbe6fea1702e57404875eb3019a3b1a341017bdbb5fbc6ce418507e5c15756 @@ -211,7 +224,7 @@ entries: version: 0.8.6 - apiVersion: v2 appVersion: 0.8.6-beta.1 - created: "2024-07-18T09:44:18.690541181Z" + created: "2024-07-19T08:00:47.007023435Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: cc2c81ef6796ac853dce256e6bf8a6af966c21803e6534ea21920af681c62e61 @@ -224,7 +237,7 @@ entries: version: 0.8.6-beta.1 - apiVersion: v2 appVersion: 0.8.5 - created: "2024-07-18T09:44:18.689971183Z" + created: "2024-07-19T08:00:47.006372531Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: db5d90d44006209fd5ecdebd88f5fd56c70f7c76898343719a0ff8da46da948a @@ -237,7 +250,7 @@ entries: version: 0.8.5 - apiVersion: v2 appVersion: 0.8.5-post.2 - created: "2024-07-18T09:44:18.689218985Z" + created: "2024-07-19T08:00:47.005121234Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ea3f7269b55f773fa165d7008c054b7cf3ec4c62eb40a96f08cd3a9b77fd2165 @@ -250,7 +263,7 @@ entries: version: 0.8.5-post.2 - apiVersion: v2 appVersion: 0.8.5-post.1 - created: "2024-07-18T09:44:18.688684404Z" + created: "2024-07-19T08:00:47.004136343Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9deb844d3dc2d8480c60f8c631dcc7794adfb39cec3aa3b1ce22ea26fdf87d02 @@ -263,7 +276,7 @@ entries: version: 0.8.5-post.1 - apiVersion: v2 appVersion: 0.8.5-beta.10 - created: "2024-07-18T09:44:18.681146757Z" + created: "2024-07-19T08:00:46.996477416Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9cfe01e8f57eca462261a24a805b41509be2de9a0fee76e331d124ed98c4bc49 @@ -276,7 +289,7 @@ entries: version: 0.8.5-beta.10 - apiVersion: v2 appVersion: 0.8.5-beta.9 - created: "2024-07-18T09:44:18.68792915Z" + created: "2024-07-19T08:00:47.003378218Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 057f1733f2bc966e15618f62629315c8207773ef6211c79c4feb557dae15c32b @@ -289,7 +302,7 @@ entries: version: 0.8.5-beta.9 - apiVersion: v2 appVersion: 0.8.5-beta.8 - created: "2024-07-18T09:44:18.687168595Z" + created: "2024-07-19T08:00:47.002585138Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 921cbce836c3032ef62b48cc82b5b4fcbe44fb81d473cf4d69a4bf0f806eb298 @@ -302,7 +315,7 @@ entries: version: 0.8.5-beta.8 - apiVersion: v2 appVersion: 0.8.5-beta.7 - created: "2024-07-18T09:44:18.686406458Z" + created: "2024-07-19T08:00:47.001833104Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 75482e955b2b9853a80bd653afb1d56535f78f3bfb7726798522307eb3effbbd @@ -315,7 +328,7 @@ entries: version: 0.8.5-beta.7 - apiVersion: v2 appVersion: 0.8.5-beta.6 - created: "2024-07-18T09:44:18.685605628Z" + created: "2024-07-19T08:00:47.001047187Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6a2dfaf65ca855e1b3d7b966d4ff291e6fcbe761e2fc2a78033211ccd3a75de0 @@ -328,7 +341,7 @@ entries: version: 0.8.5-beta.6 - apiVersion: v2 appVersion: 0.8.5-beta.5 - created: "2024-07-18T09:44:18.68424052Z" + created: "2024-07-19T08:00:47.000294152Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fead03823bef04d66901d563aa755c68ab277f72b126aaa6f0dce76a6f3bdb6d @@ -341,7 +354,7 @@ entries: version: 0.8.5-beta.5 - apiVersion: v2 appVersion: 0.8.5-beta.4 - created: "2024-07-18T09:44:18.683483723Z" + created: "2024-07-19T08:00:46.999535245Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 93e4539d5726a7fd0d6a3e93d1c17c6a358a923ddc01d102eab22f37377502ab @@ -354,7 +367,7 @@ entries: version: 0.8.5-beta.4 - apiVersion: v2 appVersion: 0.8.5-beta.3 - created: "2024-07-18T09:44:18.682699174Z" + created: "2024-07-19T08:00:46.998765368Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: f91e9390edf3441469048f5da646099af98f8b6d199409d0e2c1e6da3a51f054 @@ -367,7 +380,7 @@ entries: version: 0.8.5-beta.3 - apiVersion: v2 appVersion: 0.8.5-beta.2 - created: "2024-07-18T09:44:18.681900047Z" + created: "2024-07-19T08:00:46.9979415Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 59159c3aa4888038edc3c0135c83402363d7a0639fe62966a1e9d4928a364fa8 @@ -380,7 +393,7 @@ entries: version: 0.8.5-beta.2 - apiVersion: v2 appVersion: 0.8.5-beta.1 - created: "2024-07-18T09:44:18.680370022Z" + created: "2024-07-19T08:00:46.995714843Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 65aeb74c52ed8ba5474af500b4c1188a570ee4cb1f2a2da356b3488d28356ed9 @@ -392,7 +405,7 @@ entries: version: 0.8.5-beta.1 - apiVersion: v2 appVersion: 0.8.4 - created: "2024-07-18T09:44:18.679989029Z" + created: "2024-07-19T08:00:46.995336081Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 08afea8e3a9eef225b7e611f0bc1216c140053ef8e51439b02337faeac621fd0 @@ -404,7 +417,7 @@ entries: version: 0.8.4 - apiVersion: v2 appVersion: 0.8.4-beta.31 - created: "2024-07-18T09:44:18.676732507Z" + created: "2024-07-19T08:00:46.992873452Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fabf3e2f37e53fa623f5d3d99b00feae06e278e5cd63bce419089946312ab1fc @@ -416,7 +429,7 @@ entries: version: 0.8.4-beta.31 - apiVersion: v2 appVersion: 0.8.4-beta.30 - created: "2024-07-18T09:44:18.676317329Z" + created: "2024-07-19T08:00:46.992462319Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e8f792709f73ec14eab48a268bdf50a4505b340bd142cddd7c7bfffd94009ad @@ -428,7 +441,7 @@ entries: version: 0.8.4-beta.30 - apiVersion: v2 appVersion: 0.8.4-beta.29 - created: "2024-07-18T09:44:18.675503365Z" + created: "2024-07-19T08:00:46.991689657Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 4c985d6a9b3456769c4013f9e85e7374c0f963d2d27627e61f914f5537de1971 @@ -440,7 +453,7 @@ entries: version: 0.8.4-beta.29 - apiVersion: v2 appVersion: 0.8.4-beta.28 - created: "2024-07-18T09:44:18.67509477Z" + created: "2024-07-19T08:00:46.991256683Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: bd2aa3c92c768c47c502e31a326f341addcb34e64d22cdcbf5cc3f19689d859c @@ -452,7 +465,7 @@ entries: version: 0.8.4-beta.28 - apiVersion: v2 appVersion: 0.8.4-beta.27 - created: "2024-07-18T09:44:18.674682568Z" + created: "2024-07-19T08:00:46.990803341Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e8ad0869993af39d7adda8cb868dc0b24cfb63b4bb9820dc579939c1007a60ba @@ -464,7 +477,7 @@ entries: version: 0.8.4-beta.27 - apiVersion: v2 appVersion: 0.8.4-beta.26 - created: "2024-07-18T09:44:18.67426697Z" + created: "2024-07-19T08:00:46.99009183Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 30dccf630aa25a86a03c67572fe5411687d8ce6d58def448ea10efdba2b85e3a @@ -476,7 +489,7 @@ entries: version: 0.8.4-beta.26 - apiVersion: v2 appVersion: 0.8.4-beta.25 - created: "2024-07-18T09:44:18.673810786Z" + created: "2024-07-19T08:00:46.989223538Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b6e2043bcf5a0335967d770c7939f5a7832955359a7d871c90b265660ff26e5f @@ -488,7 +501,7 @@ entries: version: 0.8.4-beta.25 - apiVersion: v2 appVersion: 0.8.4-beta.24 - created: "2024-07-18T09:44:18.673400587Z" + created: "2024-07-19T08:00:46.98880452Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b19efa95394d50bb8d76da6ec306de5d3bb9ea55371fafea95a1282a697fa33e @@ -500,7 +513,7 @@ entries: version: 0.8.4-beta.24 - apiVersion: v2 appVersion: 0.8.4-beta.23 - created: "2024-07-18T09:44:18.672990299Z" + created: "2024-07-19T08:00:46.988395281Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 5c5d05c15bff548574896118ce92335ae10c5b78f5307fe9b2618e5a5aa71a5c @@ -512,7 +525,7 @@ entries: version: 0.8.4-beta.23 - apiVersion: v2 appVersion: 0.8.4-beta.22 - created: "2024-07-18T09:44:18.672570453Z" + created: "2024-07-19T08:00:46.987980071Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0160dbce938198132ca9cd2a5cb362816344687291f5b6d7cf6de8f2855e9414 @@ -524,7 +537,7 @@ entries: version: 0.8.4-beta.22 - apiVersion: v2 appVersion: 0.8.4-beta.21 - created: "2024-07-18T09:44:18.672145167Z" + created: "2024-07-19T08:00:46.9875699Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7dce153d2fcae7513e9c132e139b2721fd975ea3cc43a370e34dbeb2a1b7f683 @@ -536,7 +549,7 @@ entries: version: 0.8.4-beta.21 - apiVersion: v2 appVersion: 0.8.4-beta.20 - created: "2024-07-18T09:44:18.671692649Z" + created: "2024-07-19T08:00:46.98715537Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c51189a187bbf24135382e25cb00964e0330dfcd3b2f0c884581a6686f05dd28 @@ -548,7 +561,7 @@ entries: version: 0.8.4-beta.20 - apiVersion: v2 appVersion: 0.8.4-beta.19 - created: "2024-07-18T09:44:18.670359287Z" + created: "2024-07-19T08:00:46.986108272Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 8219575dedb42fa2ddbf2768a4e9afbfacbc2dff7e953d77c7b10a41b78dc687 @@ -560,7 +573,7 @@ entries: version: 0.8.4-beta.19 - apiVersion: v2 appVersion: 0.8.4-beta.18 - created: "2024-07-18T09:44:18.669451207Z" + created: "2024-07-19T08:00:46.985703572Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6418cde559cf12f1f7fea5a2b123bba950e50eeb3be002441827d2ab7f9e4ef7 @@ -572,7 +585,7 @@ entries: version: 0.8.4-beta.18 - apiVersion: v2 appVersion: 0.8.4-beta.16 - created: "2024-07-18T09:44:18.669046489Z" + created: "2024-07-19T08:00:46.985298099Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9c9840a7c9476dbb08e0ac83926330718fe50c89879752dd8f92712b036109c0 @@ -584,7 +597,7 @@ entries: version: 0.8.4-beta.16 - apiVersion: v2 appVersion: 0.8.4-beta.15 - created: "2024-07-18T09:44:18.668638194Z" + created: "2024-07-19T08:00:46.984884802Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0955fd22da028315e30c68132cbfa4bdc82bae622039bcfce0de339707bb82eb @@ -596,7 +609,7 @@ entries: version: 0.8.4-beta.15 - apiVersion: v2 appVersion: 0.8.4-beta.14 - created: "2024-07-18T09:44:18.668233817Z" + created: "2024-07-19T08:00:46.984466677Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 56208571956abe20ed7a5cc1867cab2667ed792c63e53d0e8bb70a9b438b7bf6 @@ -608,7 +621,7 @@ entries: version: 0.8.4-beta.14 - apiVersion: v2 appVersion: 0.8.4-beta.13 - created: "2024-07-18T09:44:18.667883421Z" + created: "2024-07-19T08:00:46.984082114Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: d7222c72412b6ee5833fbb07d2549be179cdfc7ccd89e0ad947d112fce799b83 @@ -620,7 +633,7 @@ entries: version: 0.8.4-beta.13 - apiVersion: v2 appVersion: 0.8.4-beta.12 - created: "2024-07-18T09:44:18.667534357Z" + created: "2024-07-19T08:00:46.983430154Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: af08c723756e397962b2d5190dedfd50797b771c5caf58b93a6f65d8fa24785c @@ -632,7 +645,7 @@ entries: version: 0.8.4-beta.12 - apiVersion: v2 appVersion: 0.8.4-beta.11 - created: "2024-07-18T09:44:18.66718891Z" + created: "2024-07-19T08:00:46.982576489Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a0235835ba57d185a83dd8a26281fa37b2077c3a37fe3a1c50585005695927e3 @@ -644,7 +657,7 @@ entries: version: 0.8.4-beta.11 - apiVersion: v2 appVersion: 0.8.4-beta.10 - created: "2024-07-18T09:44:18.66684728Z" + created: "2024-07-19T08:00:46.982232382Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 910ddfeba0c5e66651500dd11404afff092adc0f768ed68e0d93b04b83aa4388 @@ -656,7 +669,7 @@ entries: version: 0.8.4-beta.10 - apiVersion: v2 appVersion: 0.8.4-beta.9 - created: "2024-07-18T09:44:18.679575695Z" + created: "2024-07-19T08:00:46.994927233Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c25ca8a9f072d6a5d02232448deaef5668aca05f24dfffbba3ebe30a4f75bb26 @@ -668,7 +681,7 @@ entries: version: 0.8.4-beta.9 - apiVersion: v2 appVersion: 0.8.4-beta.8 - created: "2024-07-18T09:44:18.679234355Z" + created: "2024-07-19T08:00:46.99455877Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7249a39d4137e457b369384ba0a365c271c780d93a8327ce25083df763c39999 @@ -680,7 +693,7 @@ entries: version: 0.8.4-beta.8 - apiVersion: v2 appVersion: 0.8.4-beta.7 - created: "2024-07-18T09:44:18.67888997Z" + created: "2024-07-19T08:00:46.994224722Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ee750c7c8d6ea05bd447375e624fdd7f66dd87680ab81f7b7e73df7379a9024a @@ -692,7 +705,7 @@ entries: version: 0.8.4-beta.7 - apiVersion: v2 appVersion: 0.8.4-beta.6 - created: "2024-07-18T09:44:18.678543091Z" + created: "2024-07-19T08:00:46.993890524Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0e046be9f73df7444a995608c59af16fab9030b139b2acb4d6db6185b8eb5337 @@ -704,7 +717,7 @@ entries: version: 0.8.4-beta.6 - apiVersion: v2 appVersion: 0.8.4-beta.5 - created: "2024-07-18T09:44:18.678176314Z" + created: "2024-07-19T08:00:46.993554252Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b56e9a23d46810eccdb4cf5272cc05126da3f6db314e541959c3efb5f260620b @@ -716,7 +729,7 @@ entries: version: 0.8.4-beta.5 - apiVersion: v2 appVersion: 0.8.4-beta.4 - created: "2024-07-18T09:44:18.677468375Z" + created: "2024-07-19T08:00:46.99321273Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1d5808ecaf55391f3b27ae6236400066508acbd242e33db24a1ab4bffa77409e @@ -728,7 +741,7 @@ entries: version: 0.8.4-beta.4 - apiVersion: v2 appVersion: 0.8.4-beta.3 - created: "2024-07-18T09:44:18.675859813Z" + created: "2024-07-19T08:00:46.992044103Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b64efa8529d82be56c6ab60487ed24420a5614d96d2509c1f93c1003eda71a54 @@ -740,7 +753,7 @@ entries: version: 0.8.4-beta.3 - apiVersion: v2 appVersion: 0.8.4-beta.2 - created: "2024-07-18T09:44:18.671234101Z" + created: "2024-07-19T08:00:46.986707399Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -756,7 +769,7 @@ entries: version: 0.8.4-beta.2 - apiVersion: v2 appVersion: 0.8.4-beta.1 - created: "2024-07-18T09:44:18.666492967Z" + created: "2024-07-19T08:00:46.981879279Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -772,7 +785,7 @@ entries: version: 0.8.4-beta.1 - apiVersion: v2 appVersion: 0.8.3 - created: "2024-07-18T09:44:18.665903122Z" + created: "2024-07-19T08:00:46.981313395Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -788,7 +801,7 @@ entries: version: 0.8.3 - apiVersion: v2 appVersion: 0.8.3-beta.6 - created: "2024-07-18T09:44:18.665238668Z" + created: "2024-07-19T08:00:46.980660838Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -804,7 +817,7 @@ entries: version: 0.8.3-beta.6 - apiVersion: v2 appVersion: 0.8.3-beta.5 - created: "2024-07-18T09:44:18.664634707Z" + created: "2024-07-19T08:00:46.980088032Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -820,7 +833,7 @@ entries: version: 0.8.3-beta.5 - apiVersion: v2 appVersion: 0.8.3-beta.4 - created: "2024-07-18T09:44:18.663644077Z" + created: "2024-07-19T08:00:46.979508944Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -836,7 +849,7 @@ entries: version: 0.8.3-beta.4 - apiVersion: v2 appVersion: 0.8.3-beta.2 - created: "2024-07-18T09:44:18.662603789Z" + created: "2024-07-19T08:00:46.978843072Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -852,7 +865,7 @@ entries: version: 0.8.3-beta.2 - apiVersion: v2 appVersion: 0.8.3-beta.1 - created: "2024-07-18T09:44:18.662014215Z" + created: "2024-07-19T08:00:46.978250608Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -868,7 +881,7 @@ entries: version: 0.8.3-beta.1 - apiVersion: v2 appVersion: 0.8.2 - created: "2024-07-18T09:44:18.661459726Z" + created: "2024-07-19T08:00:46.977667142Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -884,7 +897,7 @@ entries: version: 0.8.2 - apiVersion: v2 appVersion: 0.8.2-beta.60 - created: "2024-07-18T09:44:18.660824016Z" + created: "2024-07-19T08:00:46.97618559Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -900,7 +913,7 @@ entries: version: 0.8.2-beta.60 - apiVersion: v2 appVersion: 0.8.2-beta.59 - created: "2024-07-18T09:44:18.660176543Z" + created: "2024-07-19T08:00:46.975547231Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -916,7 +929,7 @@ entries: version: 0.8.2-beta.59 - apiVersion: v2 appVersion: 0.8.2-beta.58 - created: "2024-07-18T09:44:18.659537266Z" + created: "2024-07-19T08:00:46.974903561Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -932,7 +945,7 @@ entries: version: 0.8.2-beta.58 - apiVersion: v2 appVersion: 0.8.2-beta.57 - created: "2024-07-18T09:44:18.658888141Z" + created: "2024-07-19T08:00:46.974225186Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -948,7 +961,7 @@ entries: version: 0.8.2-beta.57 - apiVersion: v2 appVersion: 0.8.2-beta.56 - created: "2024-07-18T09:44:18.658212445Z" + created: "2024-07-19T08:00:46.973582167Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -964,7 +977,7 @@ entries: version: 0.8.2-beta.56 - apiVersion: v2 appVersion: 0.8.2-beta.52 - created: "2024-07-18T09:44:18.656843817Z" + created: "2024-07-19T08:00:46.972943056Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -980,7 +993,7 @@ entries: version: 0.8.2-beta.52 - apiVersion: v2 appVersion: 0.8.2-beta.51 - created: "2024-07-18T09:44:18.656202316Z" + created: "2024-07-19T08:00:46.972298074Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -996,7 +1009,7 @@ entries: version: 0.8.2-beta.51 - apiVersion: v2 appVersion: 0.8.2-beta.50 - created: "2024-07-18T09:44:18.65555318Z" + created: "2024-07-19T08:00:46.971632462Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1012,7 +1025,7 @@ entries: version: 0.8.2-beta.50 - apiVersion: v2 appVersion: 0.8.2-beta.49 - created: "2024-07-18T09:44:18.654891381Z" + created: "2024-07-19T08:00:46.970694624Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1028,7 +1041,7 @@ entries: version: 0.8.2-beta.49 - apiVersion: v2 appVersion: 0.8.2-beta.48 - created: "2024-07-18T09:44:18.654246854Z" + created: "2024-07-19T08:00:46.969446138Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1044,7 +1057,7 @@ entries: version: 0.8.2-beta.48 - apiVersion: v2 appVersion: 0.8.2-beta.47 - created: "2024-07-18T09:44:18.653553185Z" + created: "2024-07-19T08:00:46.968789644Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1060,7 +1073,7 @@ entries: version: 0.8.2-beta.47 - apiVersion: v2 appVersion: 0.8.2-beta.46 - created: "2024-07-18T09:44:18.652733921Z" + created: "2024-07-19T08:00:46.968237335Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1076,7 +1089,7 @@ entries: version: 0.8.2-beta.46 - apiVersion: v2 appVersion: 0.8.2-beta.45 - created: "2024-07-18T09:44:18.652155157Z" + created: "2024-07-19T08:00:46.967662255Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1092,7 +1105,7 @@ entries: version: 0.8.2-beta.45 - apiVersion: v2 appVersion: 0.8.2-beta.44 - created: "2024-07-18T09:44:18.65155345Z" + created: "2024-07-19T08:00:46.967077005Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1108,7 +1121,7 @@ entries: version: 0.8.2-beta.44 - apiVersion: v2 appVersion: 0.8.2-beta.43 - created: "2024-07-18T09:44:18.650315225Z" + created: "2024-07-19T08:00:46.966402246Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1124,7 +1137,7 @@ entries: version: 0.8.2-beta.43 - apiVersion: v2 appVersion: 0.8.2-beta.41 - created: "2024-07-18T09:44:18.649618229Z" + created: "2024-07-19T08:00:46.965731856Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1140,7 +1153,7 @@ entries: version: 0.8.2-beta.41 - apiVersion: v2 appVersion: 0.8.2-beta.40 - created: "2024-07-18T09:44:18.648953655Z" + created: "2024-07-19T08:00:46.965047219Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1156,7 +1169,7 @@ entries: version: 0.8.2-beta.40 - apiVersion: v2 appVersion: 0.8.2-beta.39 - created: "2024-07-18T09:44:18.648396651Z" + created: "2024-07-19T08:00:46.964432073Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1172,7 +1185,7 @@ entries: version: 0.8.2-beta.39 - apiVersion: v2 appVersion: 0.8.2-beta.38 - created: "2024-07-18T09:44:18.647841832Z" + created: "2024-07-19T08:00:46.963072083Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1188,7 +1201,7 @@ entries: version: 0.8.2-beta.38 - apiVersion: v2 appVersion: 0.8.2-beta.37 - created: "2024-07-18T09:44:18.647258069Z" + created: "2024-07-19T08:00:46.962468459Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1204,7 +1217,7 @@ entries: version: 0.8.2-beta.37 - apiVersion: v2 appVersion: 0.8.1 - created: "2024-07-18T09:44:18.646646093Z" + created: "2024-07-19T08:00:46.961868861Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1218,4 +1231,4 @@ entries: urls: - https://openmined.github.io/PySyft/helm/syft-0.8.1.tgz version: 0.8.1 -generated: "2024-07-18T09:44:18.645850393Z" +generated: "2024-07-19T08:00:46.961161452Z" diff --git a/packages/grid/helm/repo/syft-0.8.7-beta.16.tgz b/packages/grid/helm/repo/syft-0.8.7-beta.16.tgz new file mode 100644 index 0000000000000000000000000000000000000000..26e288a5be25b5b9adfa556fe54e18c944f0ad90 GIT binary patch literal 18043 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 J4~$Wzq!W?|DZHhecuIJ~CXy&+fq)N+ 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⩔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 literal 0 HcmV?d00001 diff --git a/packages/grid/helm/syft/Chart.yaml b/packages/grid/helm/syft/Chart.yaml index a0e1bf432c2..a7d7860f844 100644 --- a/packages/grid/helm/syft/Chart.yaml +++ b/packages/grid/helm/syft/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: syft description: Perform numpy-like analysis on data that remains in someone elses server type: application -version: "0.8.7-beta.15" -appVersion: "0.8.7-beta.15" +version: "0.8.7-beta.16" +appVersion: "0.8.7-beta.16" home: https://github.com/OpenMined/PySyft/ icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png diff --git a/packages/grid/helm/syft/values.yaml b/packages/grid/helm/syft/values.yaml index 69ee750665b..8df3eb69bdc 100644 --- a/packages/grid/helm/syft/values.yaml +++ b/packages/grid/helm/syft/values.yaml @@ -1,7 +1,7 @@ global: # Affects only backend, frontend, and seaweedfs containers registry: docker.io - version: 0.8.7-beta.15 + version: 0.8.7-beta.16 # Force default secret values for development. DO NOT SET THIS TO FALSE IN PRODUCTION randomizedSecrets: true diff --git a/packages/syft/setup.cfg b/packages/syft/setup.cfg index ee6e8c2006b..d0e2533e7c6 100644 --- a/packages/syft/setup.cfg +++ b/packages/syft/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = syft -version = attr: "0.8.7-beta.15" +version = attr: "0.8.7-beta.16" description = Perform numpy-like analysis on data that remains in someone elses server author = OpenMined author_email = info@openmined.org diff --git a/packages/syft/src/syft/VERSION b/packages/syft/src/syft/VERSION index 27f3763909a..0923036f0b3 100644 --- a/packages/syft/src/syft/VERSION +++ b/packages/syft/src/syft/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7-beta.15" +__version__ = "0.8.7-beta.16" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index eff14c659df..f98cb18d57d 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.8.7-beta.15" +__version__ = "0.8.7-beta.16" # stdlib from collections.abc import Callable diff --git a/packages/syftcli/manifest.yml b/packages/syftcli/manifest.yml index 1e591898eca..f314725fe3a 100644 --- a/packages/syftcli/manifest.yml +++ b/packages/syftcli/manifest.yml @@ -1,11 +1,11 @@ manifestVersion: 1.0 -syftVersion: 0.8.7-beta.15 -dockerTag: 0.8.7-beta.15 +syftVersion: 0.8.7-beta.16 +dockerTag: 0.8.7-beta.16 images: - - docker.io/openmined/syft-frontend:0.8.7-beta.15 - - docker.io/openmined/syft-backend:0.8.7-beta.15 + - docker.io/openmined/syft-frontend:0.8.7-beta.16 + - docker.io/openmined/syft-backend:0.8.7-beta.16 - docker.io/library/mongo:7.0.4 - docker.io/traefik:v2.11.0 From 468a6185ac28dd7f4363d57863a1a66bb3ba49da Mon Sep 17 00:00:00 2001 From: Aziz Berkay Yesilyurt Date: Fri, 19 Jul 2024 11:30:26 +0200 Subject: [PATCH 105/117] asset.data displays error instead of a warning --- packages/syft/src/syft/service/dataset/dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index db5fe2f482f..58329a06611 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -292,7 +292,7 @@ def data(self) -> Any: if self.has_permission(res): return res.syft_action_data else: - warning = SyftWarning( + warning = SyftError( message="You do not have permission to access private data." ) display(warning) From b1910663dd27c1100b1eb89e816fa02f5805d052 Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Fri, 19 Jul 2024 11:33:36 +0200 Subject: [PATCH 106/117] remove fullyQualifiedName --- .../syft/src/syft/capnp/recursive_serde.capnp | 7 +- .../src/syft/protocol/protocol_version.json | 42 +++++------ packages/syft/src/syft/serde/recursive.py | 55 ++++---------- .../src/syft/types/syft_object_registry.py | 72 ++----------------- 4 files changed, 43 insertions(+), 133 deletions(-) diff --git a/packages/syft/src/syft/capnp/recursive_serde.capnp b/packages/syft/src/syft/capnp/recursive_serde.capnp index c29ba57aae6..5b6fadb5c65 100644 --- a/packages/syft/src/syft/capnp/recursive_serde.capnp +++ b/packages/syft/src/syft/capnp/recursive_serde.capnp @@ -3,8 +3,7 @@ struct RecursiveSerde { fieldsName @0 :List(Text); fieldsData @1 :List(List(Data)); - fullyQualifiedName @2 :Text; - nonrecursiveBlob @3 :List(Data); - canonicalName @4 :Text; - version @5 :Int32; + nonrecursiveBlob @2 :List(Data); + canonicalName @3 :Text; + version @4 :Int32; } diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index b4793310320..fa34ec9c538 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -1,6 +1,13 @@ { "dev": { "object_versions": { + "SyftObjectVersioned": { + "1": { + "version": 1, + "hash": "7c842dcdbb57e2528ffa690ea18c19fff3c8a591811d40cad2b19be3100e2ff4", + "action": "add" + } + }, "BaseDateTime": { "1": { "version": 1, @@ -8,6 +15,13 @@ "action": "add" } }, + "SyftObject": { + "1": { + "version": 1, + "hash": "bb70d874355988908d3a92a3941d6613a6995a4850be3b6a0147f4d387724406", + "action": "add" + } + }, "PartialSyftObject": { "1": { "version": 1, @@ -988,6 +1002,13 @@ "action": "add" } }, + "ProjectEvent": { + "1": { + "version": 1, + "hash": "dc0486c52daebd5e98c2b3b03ffd9a9a14bc3d86d8dc0c23e41ebf6c31fe2ffb", + "action": "add" + } + }, "ProjectThreadMessage": { "1": { "version": 1, @@ -1050,27 +1071,6 @@ "hash": "ed05cb87aec832098fc464ac36cd6bceaab705463d0d2fa1b2d8e1ccc510018c", "action": "add" } - }, - "SyftObject": { - "1": { - "version": 1, - "hash": "bb70d874355988908d3a92a3941d6613a6995a4850be3b6a0147f4d387724406", - "action": "add" - } - }, - "ProjectEvent": { - "1": { - "version": 1, - "hash": "dc0486c52daebd5e98c2b3b03ffd9a9a14bc3d86d8dc0c23e41ebf6c31fe2ffb", - "action": "add" - } - }, - "SyftObjectVersioned": { - "1": { - "version": 1, - "hash": "7c842dcdbb57e2528ffa690ea18c19fff3c8a591811d40cad2b19be3100e2ff4", - "action": "add" - } } } } diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index 19ede3d0040..4c438975245 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -3,7 +3,6 @@ from enum import Enum from enum import EnumMeta import os -import sys import tempfile import types from typing import Any @@ -17,7 +16,6 @@ # relative from ..types.syft_object_registry import SyftObjectRegistry -from ..util.util import index_syft_by_module_name from .capnp import get_capnp_schema from .util import compatible_with_large_file_writes_capnp @@ -285,7 +283,7 @@ def rs_object2proto(self: Any, for_hashing: bool = False) -> _DynamicStructBuild # todo: rewrite and make sure every object has a canonical name and version canonical_name, version = SyftObjectRegistry.get_canonical_name_version(self) - if not SyftObjectRegistry.has_serde_class("", canonical_name, version): + if not SyftObjectRegistry.has_serde_class(canonical_name, version): # third party raise Exception( f"obj2proto: {canonical_name} version {version} not in SyftObjectRegistry" @@ -382,34 +380,12 @@ def rs_proto2object(proto: _DynamicStructBuilder) -> Any: # relative from .deserialize import _deserialize - # clean this mess, Tudor - module_parts = proto.fullyQualifiedName.split(".") - klass = module_parts.pop() class_type: type | Any = type(None) - if klass != "NoneType": - try: - class_type = index_syft_by_module_name(proto.fullyQualifiedName) # type: ignore[assignment,unused-ignore] - except Exception: # nosec - try: - class_type = getattr(sys.modules[".".join(module_parts)], klass) - except Exception: # nosec - if "syft.user" in proto.fullyQualifiedName: - # relative - from ..server.server import CODE_RELOADER - - for load_user_code in CODE_RELOADER.values(): - load_user_code() - try: - class_type = getattr(sys.modules[".".join(module_parts)], klass) - except Exception: # nosec - pass - canonical_name = proto.canonicalName version = getattr(proto, "version", -1) - fqn = getattr(proto, "fullyQualifiedName", "") - fqn = map_fqns_for_backward_compatibility(fqn) - if not SyftObjectRegistry.has_serde_class(fqn, canonical_name, version): + + if not SyftObjectRegistry.has_serde_class(canonical_name, version): # third party raise Exception( f"proto2obj: {canonical_name} version {version} not in SyftObjectRegistry" @@ -431,13 +407,9 @@ def rs_proto2object(proto: _DynamicStructBuilder) -> Any: cls, _, version, - ) = SyftObjectRegistry.get_serde_properties_bw_compatible( - fqn, canonical_name, version - ) + ) = SyftObjectRegistry.get_serde_properties(canonical_name, version) - if class_type == type(None) or fqn != "": - # yes this looks stupid but it works and the opposite breaks - class_type = cls + class_type = cls if nonrecursive: if deserialize is None: @@ -468,14 +440,15 @@ def rs_proto2object(proto: _DynamicStructBuilder) -> Any: # if we skip the __new__ flow of BaseModel we get the error # AttributeError: object has no attribute '__fields_set__' - if "syft.user" in proto.fullyQualifiedName: - # weird issues with pydantic and ForwardRef on user classes being inited - # with custom state args / kwargs - obj = class_type() - for attr_name, attr_value in kwargs.items(): - setattr(obj, attr_name, attr_value) - else: - obj = class_type(**kwargs) + # if "syft.user" in proto.fullyQualifiedName: + # # weird issues with pydantic and ForwardRef on user classes being inited + # # with custom state args / kwargs + # obj = class_type() + # for attr_name, attr_value in kwargs.items(): + # setattr(obj, attr_name, attr_value) + # else: + # obj = class_type(**kwargs) + obj = class_type(**kwargs) else: obj = class_type.__new__(class_type) # type: ignore diff --git a/packages/syft/src/syft/types/syft_object_registry.py b/packages/syft/src/syft/types/syft_object_registry.py index a86bed7ddee..d5cc342635e 100644 --- a/packages/syft/src/syft/types/syft_object_registry.py +++ b/packages/syft/src/syft/types/syft_object_registry.py @@ -96,74 +96,12 @@ def get_serde_class(cls, canonical_name: str, version: int) -> type["SyftObject" return serde_properties[7] @classmethod - def get_serde_properties_bw_compatible( - cls, fqn: str, canonical_name: str, version: int - ) -> tuple: + def has_serde_class(cls, canonical_name: str | None, version: int) -> bool: # relative - from ..serde.recursive import TYPE_BANK - - if canonical_name != "" and canonical_name is not None: - return cls.get_serde_properties(canonical_name, version) - else: - # this is for backward compatibility with 0.8.6 - try: - # relative - from ..protocol.data_protocol import get_data_protocol - - serde_props = TYPE_BANK[fqn] - klass = serde_props[7] - is_syftobject = hasattr(klass, "__canonical_name__") - if is_syftobject: - canonical_name = klass.__canonical_name__ - dp = get_data_protocol() - try: - version_mutations = dp.protocol_history[ - SYFT_086_PROTOCOL_VERSION - ]["object_versions"][canonical_name] - except Exception: - print(f"could not find {canonical_name} in protocol history") - raise - - version_086 = max( - [ - int(k) - for k, v in version_mutations.items() - if v["action"] == "add" - ] - ) - try: - res = cls.get_serde_properties(canonical_name, version_086) - - except Exception: - print( - f"could not find {canonical_name} {version_086} in ObjectRegistry" - ) - raise - return res - else: - # TODO, add refactoring for non syftobject versions - canonical_name = fqn - version = 1 - return cls.get_serde_properties(canonical_name, version) - except Exception as e: - print(e) - raise - - @classmethod - def has_serde_class( - cls, fqn: str, canonical_name: str | None, version: int - ) -> bool: - # relative - from ..serde.recursive import TYPE_BANK - - if canonical_name != "" and canonical_name is not None: - return ( - canonical_name in cls.__object_serialization_registry__ - and version in cls.__object_serialization_registry__[canonical_name] - ) - else: - # this is for backward compatibility with 0.8.6 - return fqn in TYPE_BANK + return ( + canonical_name in cls.__object_serialization_registry__ + and version in cls.__object_serialization_registry__[canonical_name] + ) @classmethod def add_transform( From 330a7000736c925e73ba0c461a314428a6f3e50a Mon Sep 17 00:00:00 2001 From: Koen van der Veen Date: Fri, 19 Jul 2024 11:51:33 +0200 Subject: [PATCH 107/117] lint --- packages/syft/src/syft/client/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/syft/src/syft/client/api.py b/packages/syft/src/syft/client/api.py index d60416fdf3b..0ff9299bdfe 100644 --- a/packages/syft/src/syft/client/api.py +++ b/packages/syft/src/syft/client/api.py @@ -32,7 +32,6 @@ from ..protocol.data_protocol import get_data_protocol from ..protocol.data_protocol import migrate_args_and_kwargs from ..serde.deserialize import _deserialize -from ..serde.recursive import index_syft_by_module_name from ..serde.serializable import serializable from ..serde.serialize import _serialize from ..serde.signature import Signature @@ -63,6 +62,7 @@ from ..util.markdown import as_markdown_python_code from ..util.notebook_ui.components.tabulator_template import build_tabulator_table from ..util.telemetry import instrument +from ..util.util import index_syft_by_module_name from ..util.util import prompt_warning_message from .connection import ServerConnection From 5aba58b725ed2dd092a1e0af502c8e5078181913 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Fri, 19 Jul 2024 16:30:47 +0530 Subject: [PATCH 108/117] comment image pr test --- .github/workflows/pr-tests-stack.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-tests-stack.yml b/.github/workflows/pr-tests-stack.yml index 458092a16c5..d3d42279e85 100644 --- a/.github/workflows/pr-tests-stack.yml +++ b/.github/workflows/pr-tests-stack.yml @@ -60,7 +60,9 @@ jobs: if: steps.changes.outputs.stack == 'true' timeout-minutes: 60 run: | - tox -e backend.test.basecpu + echo "Skipping pr image test" + # run: | + # tox -e backend.test.basecpu pr-tests-syft-integration: strategy: From 3bb67ac8565773b9ccc846c594ce3759a3facf74 Mon Sep 17 00:00:00 2001 From: alfred-openmined-bot <145415986+alfred-openmined-bot@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:33:44 +0000 Subject: [PATCH 109/117] [syft] bump protocol version --- packages/grid/helm/repo/index.yaml | 195 +-- packages/grid/helm/repo/syft-0.8.7.tgz | Bin 0 -> 18151 bytes packages/syft/PYPI.md | 7 +- .../src/syft/protocol/protocol_version.json | 1076 +--------------- .../src/syft/protocol/releases/0.8.7.json | 1077 +++++++++++++++++ 5 files changed, 1187 insertions(+), 1168 deletions(-) create mode 100644 packages/grid/helm/repo/syft-0.8.7.tgz create mode 100644 packages/syft/src/syft/protocol/releases/0.8.7.json diff --git a/packages/grid/helm/repo/index.yaml b/packages/grid/helm/repo/index.yaml index c2d0dba9c21..8935c5e3425 100644 --- a/packages/grid/helm/repo/index.yaml +++ b/packages/grid/helm/repo/index.yaml @@ -1,9 +1,22 @@ apiVersion: v1 entries: syft: + - apiVersion: v2 + appVersion: 0.8.7 + created: "2024-07-19T11:31:50.870912504Z" + description: Perform numpy-like analysis on data that remains in someone elses + server + digest: 7ea7f63d1c6d0948860547f8aa39343fc5ef399c8e62d9d7edd4473cf44d8186 + home: https://github.com/OpenMined/PySyft/ + icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png + name: syft + type: application + urls: + - https://openmined.github.io/PySyft/helm/syft-0.8.7.tgz + version: 0.8.7 - apiVersion: v2 appVersion: 0.8.7-beta.16 - created: "2024-07-19T08:00:47.014272764Z" + created: "2024-07-19T11:31:50.864303995Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 75190eae57b64c2c47ab4a7fe3c6e94f35eb8045807a843ec8d7b26585c9e840 @@ -16,7 +29,7 @@ entries: version: 0.8.7-beta.16 - apiVersion: v2 appVersion: 0.8.7-beta.15 - created: "2024-07-19T08:00:47.012948682Z" + created: "2024-07-19T11:31:50.86341797Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 56879d9a9f10febce88676d3d20621d74d17f9e33f5df6ae1e9bc3078c216f0c @@ -29,7 +42,7 @@ entries: version: 0.8.7-beta.15 - apiVersion: v2 appVersion: 0.8.7-beta.14 - created: "2024-07-19T08:00:47.011858282Z" + created: "2024-07-19T11:31:50.862578481Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e7cbca1d603ba11e09ae2a3089cfdafaa08cfa07c553c4f0fb8b42f8d3028f7 @@ -42,7 +55,7 @@ entries: version: 0.8.7-beta.14 - apiVersion: v2 appVersion: 0.8.7-beta.13 - created: "2024-07-19T08:00:47.010938574Z" + created: "2024-07-19T11:31:50.861706392Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1dbe3ecdfec57bf25020cbcff783fab908f0eb0640ad684470b2fd1da1928005 @@ -55,7 +68,7 @@ entries: version: 0.8.7-beta.13 - apiVersion: v2 appVersion: 0.8.7-beta.12 - created: "2024-07-19T08:00:47.010210325Z" + created: "2024-07-19T11:31:50.861001584Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e92b2f3a522dabb3a79ff762a7042ae16d2bf3a53eebbb2885a69b9f834d109c @@ -68,7 +81,7 @@ entries: version: 0.8.7-beta.12 - apiVersion: v2 appVersion: 0.8.7-beta.11 - created: "2024-07-19T08:00:47.009504488Z" + created: "2024-07-19T11:31:50.860279135Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 099f6cbd44b699ee2410a4be012ed1a8a65bcacb06a43057b2779d7fe34fc0ad @@ -81,7 +94,7 @@ entries: version: 0.8.7-beta.11 - apiVersion: v2 appVersion: 0.8.7-beta.10 - created: "2024-07-19T08:00:47.008807007Z" + created: "2024-07-19T11:31:50.85908115Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 00773cb241522e281c1915339fc362e047650e08958a736e93d6539f44cb5e25 @@ -94,7 +107,7 @@ entries: version: 0.8.7-beta.10 - apiVersion: v2 appVersion: 0.8.7-beta.9 - created: "2024-07-19T08:00:47.019477968Z" + created: "2024-07-19T11:31:50.870075941Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a3f8e85d9ddef7a644b959fcc2fcb0fc08f7b6abae1045e893d0d62fa4ae132e @@ -107,7 +120,7 @@ entries: version: 0.8.7-beta.9 - apiVersion: v2 appVersion: 0.8.7-beta.8 - created: "2024-07-19T08:00:47.018823548Z" + created: "2024-07-19T11:31:50.869419064Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a422ac88d8fd1fb80d5004d5eb6e95fa9efc7f6a87da12e5ac04829da7f04c4d @@ -120,7 +133,7 @@ entries: version: 0.8.7-beta.8 - apiVersion: v2 appVersion: 0.8.7-beta.7 - created: "2024-07-19T08:00:47.018142819Z" + created: "2024-07-19T11:31:50.86875891Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0dc313a1092e6256a7c8aad002c8ec380b3add2c289d680db1e238a336399b7a @@ -133,7 +146,7 @@ entries: version: 0.8.7-beta.7 - apiVersion: v2 appVersion: 0.8.7-beta.6 - created: "2024-07-19T08:00:47.017502776Z" + created: "2024-07-19T11:31:50.868118734Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 052a2ec1102d2a4c9915f95647abd4a6012f56fa05a106f4952ee9b55bf7bae8 @@ -146,7 +159,7 @@ entries: version: 0.8.7-beta.6 - apiVersion: v2 appVersion: 0.8.7-beta.5 - created: "2024-07-19T08:00:47.01686135Z" + created: "2024-07-19T11:31:50.867454893Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1728af756907c3fcbe87c2fd2de014a2d963c22a4c2eb6af6596b525a9b9a18a @@ -159,7 +172,7 @@ entries: version: 0.8.7-beta.5 - apiVersion: v2 appVersion: 0.8.7-beta.4 - created: "2024-07-19T08:00:47.016237437Z" + created: "2024-07-19T11:31:50.86618484Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 387a57a3904a05ed61e92ee48605ef6fd5044ff7e822e0924e0d4c485e2c88d2 @@ -172,7 +185,7 @@ entries: version: 0.8.7-beta.4 - apiVersion: v2 appVersion: 0.8.7-beta.3 - created: "2024-07-19T08:00:47.015602895Z" + created: "2024-07-19T11:31:50.865555304Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 3668002b7a4118516b2ecd61d6275f60d83fc12841587ab8f62e1c1200731c67 @@ -185,7 +198,7 @@ entries: version: 0.8.7-beta.3 - apiVersion: v2 appVersion: 0.8.7-beta.2 - created: "2024-07-19T08:00:47.014959215Z" + created: "2024-07-19T11:31:50.864903516Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e62217ffcadee2b8896ab0543f9ccc42f2df898fd979438ac9376d780b802af7 @@ -198,7 +211,7 @@ entries: version: 0.8.7-beta.2 - apiVersion: v2 appVersion: 0.8.7-beta.1 - created: "2024-07-19T08:00:47.008129384Z" + created: "2024-07-19T11:31:50.858186779Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 553981fe1d5c980e6903b3ff2f1b9b97431f6dd8aee91e3976bcc5594285235e @@ -211,7 +224,7 @@ entries: version: 0.8.7-beta.1 - apiVersion: v2 appVersion: 0.8.6 - created: "2024-07-19T08:00:47.00760616Z" + created: "2024-07-19T11:31:50.857670664Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ddbbe6fea1702e57404875eb3019a3b1a341017bdbb5fbc6ce418507e5c15756 @@ -224,7 +237,7 @@ entries: version: 0.8.6 - apiVersion: v2 appVersion: 0.8.6-beta.1 - created: "2024-07-19T08:00:47.007023435Z" + created: "2024-07-19T11:31:50.857126818Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: cc2c81ef6796ac853dce256e6bf8a6af966c21803e6534ea21920af681c62e61 @@ -237,7 +250,7 @@ entries: version: 0.8.6-beta.1 - apiVersion: v2 appVersion: 0.8.5 - created: "2024-07-19T08:00:47.006372531Z" + created: "2024-07-19T11:31:50.856579716Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: db5d90d44006209fd5ecdebd88f5fd56c70f7c76898343719a0ff8da46da948a @@ -250,7 +263,7 @@ entries: version: 0.8.5 - apiVersion: v2 appVersion: 0.8.5-post.2 - created: "2024-07-19T08:00:47.005121234Z" + created: "2024-07-19T11:31:50.855819024Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ea3f7269b55f773fa165d7008c054b7cf3ec4c62eb40a96f08cd3a9b77fd2165 @@ -263,7 +276,7 @@ entries: version: 0.8.5-post.2 - apiVersion: v2 appVersion: 0.8.5-post.1 - created: "2024-07-19T08:00:47.004136343Z" + created: "2024-07-19T11:31:50.855235143Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9deb844d3dc2d8480c60f8c631dcc7794adfb39cec3aa3b1ce22ea26fdf87d02 @@ -276,7 +289,7 @@ entries: version: 0.8.5-post.1 - apiVersion: v2 appVersion: 0.8.5-beta.10 - created: "2024-07-19T08:00:46.996477416Z" + created: "2024-07-19T11:31:50.847482922Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9cfe01e8f57eca462261a24a805b41509be2de9a0fee76e331d124ed98c4bc49 @@ -289,7 +302,7 @@ entries: version: 0.8.5-beta.10 - apiVersion: v2 appVersion: 0.8.5-beta.9 - created: "2024-07-19T08:00:47.003378218Z" + created: "2024-07-19T11:31:50.854433245Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 057f1733f2bc966e15618f62629315c8207773ef6211c79c4feb557dae15c32b @@ -302,7 +315,7 @@ entries: version: 0.8.5-beta.9 - apiVersion: v2 appVersion: 0.8.5-beta.8 - created: "2024-07-19T08:00:47.002585138Z" + created: "2024-07-19T11:31:50.853659569Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 921cbce836c3032ef62b48cc82b5b4fcbe44fb81d473cf4d69a4bf0f806eb298 @@ -315,7 +328,7 @@ entries: version: 0.8.5-beta.8 - apiVersion: v2 appVersion: 0.8.5-beta.7 - created: "2024-07-19T08:00:47.001833104Z" + created: "2024-07-19T11:31:50.852858872Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 75482e955b2b9853a80bd653afb1d56535f78f3bfb7726798522307eb3effbbd @@ -328,7 +341,7 @@ entries: version: 0.8.5-beta.7 - apiVersion: v2 appVersion: 0.8.5-beta.6 - created: "2024-07-19T08:00:47.001047187Z" + created: "2024-07-19T11:31:50.851323498Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6a2dfaf65ca855e1b3d7b966d4ff291e6fcbe761e2fc2a78033211ccd3a75de0 @@ -341,7 +354,7 @@ entries: version: 0.8.5-beta.6 - apiVersion: v2 appVersion: 0.8.5-beta.5 - created: "2024-07-19T08:00:47.000294152Z" + created: "2024-07-19T11:31:50.85053768Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fead03823bef04d66901d563aa755c68ab277f72b126aaa6f0dce76a6f3bdb6d @@ -354,7 +367,7 @@ entries: version: 0.8.5-beta.5 - apiVersion: v2 appVersion: 0.8.5-beta.4 - created: "2024-07-19T08:00:46.999535245Z" + created: "2024-07-19T11:31:50.849776748Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 93e4539d5726a7fd0d6a3e93d1c17c6a358a923ddc01d102eab22f37377502ab @@ -367,7 +380,7 @@ entries: version: 0.8.5-beta.4 - apiVersion: v2 appVersion: 0.8.5-beta.3 - created: "2024-07-19T08:00:46.998765368Z" + created: "2024-07-19T11:31:50.849016577Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: f91e9390edf3441469048f5da646099af98f8b6d199409d0e2c1e6da3a51f054 @@ -380,7 +393,7 @@ entries: version: 0.8.5-beta.3 - apiVersion: v2 appVersion: 0.8.5-beta.2 - created: "2024-07-19T08:00:46.9979415Z" + created: "2024-07-19T11:31:50.848255005Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 59159c3aa4888038edc3c0135c83402363d7a0639fe62966a1e9d4928a364fa8 @@ -393,7 +406,7 @@ entries: version: 0.8.5-beta.2 - apiVersion: v2 appVersion: 0.8.5-beta.1 - created: "2024-07-19T08:00:46.995714843Z" + created: "2024-07-19T11:31:50.846690621Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 65aeb74c52ed8ba5474af500b4c1188a570ee4cb1f2a2da356b3488d28356ed9 @@ -405,7 +418,7 @@ entries: version: 0.8.5-beta.1 - apiVersion: v2 appVersion: 0.8.4 - created: "2024-07-19T08:00:46.995336081Z" + created: "2024-07-19T11:31:50.846309569Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 08afea8e3a9eef225b7e611f0bc1216c140053ef8e51439b02337faeac621fd0 @@ -417,7 +430,7 @@ entries: version: 0.8.4 - apiVersion: v2 appVersion: 0.8.4-beta.31 - created: "2024-07-19T08:00:46.992873452Z" + created: "2024-07-19T11:31:50.843012308Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fabf3e2f37e53fa623f5d3d99b00feae06e278e5cd63bce419089946312ab1fc @@ -429,7 +442,7 @@ entries: version: 0.8.4-beta.31 - apiVersion: v2 appVersion: 0.8.4-beta.30 - created: "2024-07-19T08:00:46.992462319Z" + created: "2024-07-19T11:31:50.842602152Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e8f792709f73ec14eab48a268bdf50a4505b340bd142cddd7c7bfffd94009ad @@ -441,7 +454,7 @@ entries: version: 0.8.4-beta.30 - apiVersion: v2 appVersion: 0.8.4-beta.29 - created: "2024-07-19T08:00:46.991689657Z" + created: "2024-07-19T11:31:50.841841901Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 4c985d6a9b3456769c4013f9e85e7374c0f963d2d27627e61f914f5537de1971 @@ -453,7 +466,7 @@ entries: version: 0.8.4-beta.29 - apiVersion: v2 appVersion: 0.8.4-beta.28 - created: "2024-07-19T08:00:46.991256683Z" + created: "2024-07-19T11:31:50.841432055Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: bd2aa3c92c768c47c502e31a326f341addcb34e64d22cdcbf5cc3f19689d859c @@ -465,7 +478,7 @@ entries: version: 0.8.4-beta.28 - apiVersion: v2 appVersion: 0.8.4-beta.27 - created: "2024-07-19T08:00:46.990803341Z" + created: "2024-07-19T11:31:50.841019464Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e8ad0869993af39d7adda8cb868dc0b24cfb63b4bb9820dc579939c1007a60ba @@ -477,7 +490,7 @@ entries: version: 0.8.4-beta.27 - apiVersion: v2 appVersion: 0.8.4-beta.26 - created: "2024-07-19T08:00:46.99009183Z" + created: "2024-07-19T11:31:50.840606453Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 30dccf630aa25a86a03c67572fe5411687d8ce6d58def448ea10efdba2b85e3a @@ -489,7 +502,7 @@ entries: version: 0.8.4-beta.26 - apiVersion: v2 appVersion: 0.8.4-beta.25 - created: "2024-07-19T08:00:46.989223538Z" + created: "2024-07-19T11:31:50.84018796Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b6e2043bcf5a0335967d770c7939f5a7832955359a7d871c90b265660ff26e5f @@ -501,7 +514,7 @@ entries: version: 0.8.4-beta.25 - apiVersion: v2 appVersion: 0.8.4-beta.24 - created: "2024-07-19T08:00:46.98880452Z" + created: "2024-07-19T11:31:50.839770661Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b19efa95394d50bb8d76da6ec306de5d3bb9ea55371fafea95a1282a697fa33e @@ -513,7 +526,7 @@ entries: version: 0.8.4-beta.24 - apiVersion: v2 appVersion: 0.8.4-beta.23 - created: "2024-07-19T08:00:46.988395281Z" + created: "2024-07-19T11:31:50.839319548Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 5c5d05c15bff548574896118ce92335ae10c5b78f5307fe9b2618e5a5aa71a5c @@ -525,7 +538,7 @@ entries: version: 0.8.4-beta.23 - apiVersion: v2 appVersion: 0.8.4-beta.22 - created: "2024-07-19T08:00:46.987980071Z" + created: "2024-07-19T11:31:50.838906726Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0160dbce938198132ca9cd2a5cb362816344687291f5b6d7cf6de8f2855e9414 @@ -537,7 +550,7 @@ entries: version: 0.8.4-beta.22 - apiVersion: v2 appVersion: 0.8.4-beta.21 - created: "2024-07-19T08:00:46.9875699Z" + created: "2024-07-19T11:31:50.838488465Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7dce153d2fcae7513e9c132e139b2721fd975ea3cc43a370e34dbeb2a1b7f683 @@ -549,7 +562,7 @@ entries: version: 0.8.4-beta.21 - apiVersion: v2 appVersion: 0.8.4-beta.20 - created: "2024-07-19T08:00:46.98715537Z" + created: "2024-07-19T11:31:50.838054995Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c51189a187bbf24135382e25cb00964e0330dfcd3b2f0c884581a6686f05dd28 @@ -561,7 +574,7 @@ entries: version: 0.8.4-beta.20 - apiVersion: v2 appVersion: 0.8.4-beta.19 - created: "2024-07-19T08:00:46.986108272Z" + created: "2024-07-19T11:31:50.836251023Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 8219575dedb42fa2ddbf2768a4e9afbfacbc2dff7e953d77c7b10a41b78dc687 @@ -573,7 +586,7 @@ entries: version: 0.8.4-beta.19 - apiVersion: v2 appVersion: 0.8.4-beta.18 - created: "2024-07-19T08:00:46.985703572Z" + created: "2024-07-19T11:31:50.835840196Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6418cde559cf12f1f7fea5a2b123bba950e50eeb3be002441827d2ab7f9e4ef7 @@ -585,7 +598,7 @@ entries: version: 0.8.4-beta.18 - apiVersion: v2 appVersion: 0.8.4-beta.16 - created: "2024-07-19T08:00:46.985298099Z" + created: "2024-07-19T11:31:50.835335573Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9c9840a7c9476dbb08e0ac83926330718fe50c89879752dd8f92712b036109c0 @@ -597,7 +610,7 @@ entries: version: 0.8.4-beta.16 - apiVersion: v2 appVersion: 0.8.4-beta.15 - created: "2024-07-19T08:00:46.984884802Z" + created: "2024-07-19T11:31:50.834903756Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0955fd22da028315e30c68132cbfa4bdc82bae622039bcfce0de339707bb82eb @@ -609,7 +622,7 @@ entries: version: 0.8.4-beta.15 - apiVersion: v2 appVersion: 0.8.4-beta.14 - created: "2024-07-19T08:00:46.984466677Z" + created: "2024-07-19T11:31:50.834498058Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 56208571956abe20ed7a5cc1867cab2667ed792c63e53d0e8bb70a9b438b7bf6 @@ -621,7 +634,7 @@ entries: version: 0.8.4-beta.14 - apiVersion: v2 appVersion: 0.8.4-beta.13 - created: "2024-07-19T08:00:46.984082114Z" + created: "2024-07-19T11:31:50.834147453Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: d7222c72412b6ee5833fbb07d2549be179cdfc7ccd89e0ad947d112fce799b83 @@ -633,7 +646,7 @@ entries: version: 0.8.4-beta.13 - apiVersion: v2 appVersion: 0.8.4-beta.12 - created: "2024-07-19T08:00:46.983430154Z" + created: "2024-07-19T11:31:50.833794303Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: af08c723756e397962b2d5190dedfd50797b771c5caf58b93a6f65d8fa24785c @@ -645,7 +658,7 @@ entries: version: 0.8.4-beta.12 - apiVersion: v2 appVersion: 0.8.4-beta.11 - created: "2024-07-19T08:00:46.982576489Z" + created: "2024-07-19T11:31:50.833442736Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a0235835ba57d185a83dd8a26281fa37b2077c3a37fe3a1c50585005695927e3 @@ -657,7 +670,7 @@ entries: version: 0.8.4-beta.11 - apiVersion: v2 appVersion: 0.8.4-beta.10 - created: "2024-07-19T08:00:46.982232382Z" + created: "2024-07-19T11:31:50.833093503Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 910ddfeba0c5e66651500dd11404afff092adc0f768ed68e0d93b04b83aa4388 @@ -669,7 +682,7 @@ entries: version: 0.8.4-beta.10 - apiVersion: v2 appVersion: 0.8.4-beta.9 - created: "2024-07-19T08:00:46.994927233Z" + created: "2024-07-19T11:31:50.845890837Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c25ca8a9f072d6a5d02232448deaef5668aca05f24dfffbba3ebe30a4f75bb26 @@ -681,7 +694,7 @@ entries: version: 0.8.4-beta.9 - apiVersion: v2 appVersion: 0.8.4-beta.8 - created: "2024-07-19T08:00:46.99455877Z" + created: "2024-07-19T11:31:50.845544449Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7249a39d4137e457b369384ba0a365c271c780d93a8327ce25083df763c39999 @@ -693,7 +706,7 @@ entries: version: 0.8.4-beta.8 - apiVersion: v2 appVersion: 0.8.4-beta.7 - created: "2024-07-19T08:00:46.994224722Z" + created: "2024-07-19T11:31:50.845192041Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ee750c7c8d6ea05bd447375e624fdd7f66dd87680ab81f7b7e73df7379a9024a @@ -705,7 +718,7 @@ entries: version: 0.8.4-beta.7 - apiVersion: v2 appVersion: 0.8.4-beta.6 - created: "2024-07-19T08:00:46.993890524Z" + created: "2024-07-19T11:31:50.844820808Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0e046be9f73df7444a995608c59af16fab9030b139b2acb4d6db6185b8eb5337 @@ -717,7 +730,7 @@ entries: version: 0.8.4-beta.6 - apiVersion: v2 appVersion: 0.8.4-beta.5 - created: "2024-07-19T08:00:46.993554252Z" + created: "2024-07-19T11:31:50.844183016Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b56e9a23d46810eccdb4cf5272cc05126da3f6db314e541959c3efb5f260620b @@ -729,7 +742,7 @@ entries: version: 0.8.4-beta.5 - apiVersion: v2 appVersion: 0.8.4-beta.4 - created: "2024-07-19T08:00:46.99321273Z" + created: "2024-07-19T11:31:50.843366771Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1d5808ecaf55391f3b27ae6236400066508acbd242e33db24a1ab4bffa77409e @@ -741,7 +754,7 @@ entries: version: 0.8.4-beta.4 - apiVersion: v2 appVersion: 0.8.4-beta.3 - created: "2024-07-19T08:00:46.992044103Z" + created: "2024-07-19T11:31:50.842190062Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b64efa8529d82be56c6ab60487ed24420a5614d96d2509c1f93c1003eda71a54 @@ -753,7 +766,7 @@ entries: version: 0.8.4-beta.3 - apiVersion: v2 appVersion: 0.8.4-beta.2 - created: "2024-07-19T08:00:46.986707399Z" + created: "2024-07-19T11:31:50.837597029Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -769,7 +782,7 @@ entries: version: 0.8.4-beta.2 - apiVersion: v2 appVersion: 0.8.4-beta.1 - created: "2024-07-19T08:00:46.981879279Z" + created: "2024-07-19T11:31:50.832739211Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -785,7 +798,7 @@ entries: version: 0.8.4-beta.1 - apiVersion: v2 appVersion: 0.8.3 - created: "2024-07-19T08:00:46.981313395Z" + created: "2024-07-19T11:31:50.832188242Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -801,7 +814,7 @@ entries: version: 0.8.3 - apiVersion: v2 appVersion: 0.8.3-beta.6 - created: "2024-07-19T08:00:46.980660838Z" + created: "2024-07-19T11:31:50.83151842Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -817,7 +830,7 @@ entries: version: 0.8.3-beta.6 - apiVersion: v2 appVersion: 0.8.3-beta.5 - created: "2024-07-19T08:00:46.980088032Z" + created: "2024-07-19T11:31:50.830892461Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -833,7 +846,7 @@ entries: version: 0.8.3-beta.5 - apiVersion: v2 appVersion: 0.8.3-beta.4 - created: "2024-07-19T08:00:46.979508944Z" + created: "2024-07-19T11:31:50.830265389Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -849,7 +862,7 @@ entries: version: 0.8.3-beta.4 - apiVersion: v2 appVersion: 0.8.3-beta.2 - created: "2024-07-19T08:00:46.978843072Z" + created: "2024-07-19T11:31:50.828791015Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -865,7 +878,7 @@ entries: version: 0.8.3-beta.2 - apiVersion: v2 appVersion: 0.8.3-beta.1 - created: "2024-07-19T08:00:46.978250608Z" + created: "2024-07-19T11:31:50.828238753Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -881,7 +894,7 @@ entries: version: 0.8.3-beta.1 - apiVersion: v2 appVersion: 0.8.2 - created: "2024-07-19T08:00:46.977667142Z" + created: "2024-07-19T11:31:50.827683125Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -897,7 +910,7 @@ entries: version: 0.8.2 - apiVersion: v2 appVersion: 0.8.2-beta.60 - created: "2024-07-19T08:00:46.97618559Z" + created: "2024-07-19T11:31:50.827006892Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -913,7 +926,7 @@ entries: version: 0.8.2-beta.60 - apiVersion: v2 appVersion: 0.8.2-beta.59 - created: "2024-07-19T08:00:46.975547231Z" + created: "2024-07-19T11:31:50.826367747Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -929,7 +942,7 @@ entries: version: 0.8.2-beta.59 - apiVersion: v2 appVersion: 0.8.2-beta.58 - created: "2024-07-19T08:00:46.974903561Z" + created: "2024-07-19T11:31:50.825726789Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -945,7 +958,7 @@ entries: version: 0.8.2-beta.58 - apiVersion: v2 appVersion: 0.8.2-beta.57 - created: "2024-07-19T08:00:46.974225186Z" + created: "2024-07-19T11:31:50.825076865Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -961,7 +974,7 @@ entries: version: 0.8.2-beta.57 - apiVersion: v2 appVersion: 0.8.2-beta.56 - created: "2024-07-19T08:00:46.973582167Z" + created: "2024-07-19T11:31:50.824390102Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -977,7 +990,7 @@ entries: version: 0.8.2-beta.56 - apiVersion: v2 appVersion: 0.8.2-beta.52 - created: "2024-07-19T08:00:46.972943056Z" + created: "2024-07-19T11:31:50.823388048Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -993,7 +1006,7 @@ entries: version: 0.8.2-beta.52 - apiVersion: v2 appVersion: 0.8.2-beta.51 - created: "2024-07-19T08:00:46.972298074Z" + created: "2024-07-19T11:31:50.82224956Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1009,7 +1022,7 @@ entries: version: 0.8.2-beta.51 - apiVersion: v2 appVersion: 0.8.2-beta.50 - created: "2024-07-19T08:00:46.971632462Z" + created: "2024-07-19T11:31:50.821603203Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1025,7 +1038,7 @@ entries: version: 0.8.2-beta.50 - apiVersion: v2 appVersion: 0.8.2-beta.49 - created: "2024-07-19T08:00:46.970694624Z" + created: "2024-07-19T11:31:50.820953538Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1041,7 +1054,7 @@ entries: version: 0.8.2-beta.49 - apiVersion: v2 appVersion: 0.8.2-beta.48 - created: "2024-07-19T08:00:46.969446138Z" + created: "2024-07-19T11:31:50.820299005Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1057,7 +1070,7 @@ entries: version: 0.8.2-beta.48 - apiVersion: v2 appVersion: 0.8.2-beta.47 - created: "2024-07-19T08:00:46.968789644Z" + created: "2024-07-19T11:31:50.819452133Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1073,7 +1086,7 @@ entries: version: 0.8.2-beta.47 - apiVersion: v2 appVersion: 0.8.2-beta.46 - created: "2024-07-19T08:00:46.968237335Z" + created: "2024-07-19T11:31:50.818869394Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1089,7 +1102,7 @@ entries: version: 0.8.2-beta.46 - apiVersion: v2 appVersion: 0.8.2-beta.45 - created: "2024-07-19T08:00:46.967662255Z" + created: "2024-07-19T11:31:50.818312904Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1105,7 +1118,7 @@ entries: version: 0.8.2-beta.45 - apiVersion: v2 appVersion: 0.8.2-beta.44 - created: "2024-07-19T08:00:46.967077005Z" + created: "2024-07-19T11:31:50.817734012Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1121,7 +1134,7 @@ entries: version: 0.8.2-beta.44 - apiVersion: v2 appVersion: 0.8.2-beta.43 - created: "2024-07-19T08:00:46.966402246Z" + created: "2024-07-19T11:31:50.816780482Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1137,7 +1150,7 @@ entries: version: 0.8.2-beta.43 - apiVersion: v2 appVersion: 0.8.2-beta.41 - created: "2024-07-19T08:00:46.965731856Z" + created: "2024-07-19T11:31:50.815718578Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1153,7 +1166,7 @@ entries: version: 0.8.2-beta.41 - apiVersion: v2 appVersion: 0.8.2-beta.40 - created: "2024-07-19T08:00:46.965047219Z" + created: "2024-07-19T11:31:50.815028208Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1169,7 +1182,7 @@ entries: version: 0.8.2-beta.40 - apiVersion: v2 appVersion: 0.8.2-beta.39 - created: "2024-07-19T08:00:46.964432073Z" + created: "2024-07-19T11:31:50.814473792Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1185,7 +1198,7 @@ entries: version: 0.8.2-beta.39 - apiVersion: v2 appVersion: 0.8.2-beta.38 - created: "2024-07-19T08:00:46.963072083Z" + created: "2024-07-19T11:31:50.81391087Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1201,7 +1214,7 @@ entries: version: 0.8.2-beta.38 - apiVersion: v2 appVersion: 0.8.2-beta.37 - created: "2024-07-19T08:00:46.962468459Z" + created: "2024-07-19T11:31:50.813330866Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1217,7 +1230,7 @@ entries: version: 0.8.2-beta.37 - apiVersion: v2 appVersion: 0.8.1 - created: "2024-07-19T08:00:46.961868861Z" + created: "2024-07-19T11:31:50.812722189Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1231,4 +1244,4 @@ entries: urls: - https://openmined.github.io/PySyft/helm/syft-0.8.1.tgz version: 0.8.1 -generated: "2024-07-19T08:00:46.961161452Z" +generated: "2024-07-19T11:31:50.81199537Z" diff --git a/packages/grid/helm/repo/syft-0.8.7.tgz b/packages/grid/helm/repo/syft-0.8.7.tgz new file mode 100644 index 0000000000000000000000000000000000000000..75af841eb849c5d899a6151c008412e48570a8c5 GIT binary patch literal 18151 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
Ek+cP-Do-Vx|+bvdVm$ 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.8.6,<0.8.7") +sy.requires(">=0.8.7,<0.8.8") server = sy.orchestra.launch( name="my-datasite", port=8080, @@ -143,11 +143,12 @@ helm install ... --set ingress.class="gce" # Versions `0.9.0` - Coming soon... -`0.8.7` (Beta) - `dev` branch 👈🏽 API - Coming soon... -`0.8.6` (Stable) - API +`0.8.8` (Beta) - `dev` branch 👈🏽 API - Coming soon... +`0.8.7` (Stable) - API Deprecated: +- `0.8.6` - API - `0.8.5-post.2` - API - `0.8.4` - API - `0.8.3` - API diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index fa34ec9c538..a7bb8d85399 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -1,1077 +1,5 @@ { - "dev": { - "object_versions": { - "SyftObjectVersioned": { - "1": { - "version": 1, - "hash": "7c842dcdbb57e2528ffa690ea18c19fff3c8a591811d40cad2b19be3100e2ff4", - "action": "add" - } - }, - "BaseDateTime": { - "1": { - "version": 1, - "hash": "614db484b1950be729902b1861bd3a7b33899176507c61cef11dc0d44611cfd3", - "action": "add" - } - }, - "SyftObject": { - "1": { - "version": 1, - "hash": "bb70d874355988908d3a92a3941d6613a6995a4850be3b6a0147f4d387724406", - "action": "add" - } - }, - "PartialSyftObject": { - "1": { - "version": 1, - "hash": "19a995fcc2833f4fab24584fd99b71a80c2ef1f13c06f83af79e4482846b1656", - "action": "add" - } - }, - "ServerMetadata": { - "1": { - "version": 1, - "hash": "1691c7667eca86b20c4189e90ce4e643dd41fd3682cdb69c6308878f2a6f135c", - "action": "add" - } - }, - "StoreConfig": { - "1": { - "version": 1, - "hash": "a9997fce6a8a0ed2884c58b8eb9382f8554bdd18fff61f8bf0451945bcff12c7", - "action": "add" - } - }, - "MongoDict": { - "1": { - "version": 1, - "hash": "57e36f57eed75e62b29e2bac1295035a9bf2c0e3c56719dac24cb6cc685be00b", - "action": "add" - } - }, - "MongoStoreConfig": { - "1": { - "version": 1, - "hash": "53342b27d34165b7e2699f8e7ad70d13d125875e6a75e8fa18f5796428f41036", - "action": "add" - } - }, - "LinkedObject": { - "1": { - "version": 1, - "hash": "d80f5ac7f51a9383be1a3cb334d56ae50e49733ed3199f3b6b5d6febd9de410b", - "action": "add" - } - }, - "BaseConfig": { - "1": { - "version": 1, - "hash": "10bd7566041d0f0a3aa295367785fdcc2c5bbf0ded984ac9230754f37496a6a7", - "action": "add" - } - }, - "ServiceConfig": { - "1": { - "version": 1, - "hash": "28af8a296f5ff63de50438277eaa1f4380682e6aca9f2ca28320d7a444825e88", - "action": "add" - } - }, - "LibConfig": { - "1": { - "version": 1, - "hash": "ee8f0e3f6aae81948d72e30226645e8eb5d312a6770411a1edca748168c467c0", - "action": "add" - } - }, - "APIEndpoint": { - "1": { - "version": 1, - "hash": "cfa6f314481a5bf3c448c33bf2312a9c33cbcf03cdc96864ad9a108f62b09346", - "action": "add" - } - }, - "LibEndpoint": { - "1": { - "version": 1, - "hash": "a585c83a33a019d363ae5a0c6d4197193654307c19a4829dfbf8a8cfd2c1842a", - "action": "add" - } - }, - "SignedSyftAPICall": { - "1": { - "version": 1, - "hash": "2f959455f7130f4e59360b8aa58f19785b76eaa0f8a5a9188a6cbf32b31311ca", - "action": "add" - } - }, - "SyftAPICall": { - "1": { - "version": 1, - "hash": "59e89e7b9ea30deaed64d1ffd9bc0769b999d3082b305428432c1f5be36c6343", - "action": "add" - } - }, - "SyftAPIData": { - "1": { - "version": 1, - "hash": "820b279c581cafd9bb5009702d4e3db22ec3a3156676426304b9038dad260a24", - "action": "add" - } - }, - "SyftAPI": { - "1": { - "version": 1, - "hash": "cc13ab058ee36748c14b0d4bd9b9e894c7566fff09cfa4170b3eece520169f15", - "action": "add" - } - }, - "User": { - "1": { - "version": 1, - "hash": "2df4b68182c558dba5485a8a6867acf2a5c341b249ad67373a504098aa8c4343", - "action": "add" - } - }, - "UserUpdate": { - "1": { - "version": 1, - "hash": "1bf6707c69b809c804fb939c7c37d787c2f6889508a4bec37d24221af2eb777a", - "action": "add" - } - }, - "UserCreate": { - "1": { - "version": 1, - "hash": "49d6087e2309ba59987f3126e286e74b3a66492a08ad82fa507ea17d52ce78e3", - "action": "add" - } - }, - "UserSearch": { - "1": { - "version": 1, - "hash": "9ac946338cca68d00d1696a57943442f062628ec3daf53077d0bdd3f72cd9fa0", - "action": "add" - } - }, - "UserView": { - "1": { - "version": 1, - "hash": "0b52d758e31d5889c9cd88afb467aae4a74e34a5276924e07012243c34d300fe", - "action": "add" - } - }, - "UserViewPage": { - "1": { - "version": 1, - "hash": "1cd6528d02ec180f080d5c35f0da760d8a59af9da7baaa9c17c1c7cedcc858fa", - "action": "add" - } - }, - "UserPrivateKey": { - "1": { - "version": 1, - "hash": "4817d8147aba94373f320dcd90e65f097cf6e5a2ef353aa8520e23128d522b5d", - "action": "add" - } - }, - "DateTime": { - "1": { - "version": 1, - "hash": "394abb554114ead4d63c36e3fe83ac018dead4b21a8465174009577c46d54c58", - "action": "add" - } - }, - "ReplyNotification": { - "1": { - "version": 1, - "hash": "84102dfc59d711b03c2f3d3a6ecaca000b6835f1bbdd9af801057f7aacb5f1d0", - "action": "add" - } - }, - "Notification": { - "1": { - "version": 1, - "hash": "af4cb232bff390c431e399975f048b34da7e940ace8b23b940a3b398c91c5326", - "action": "add" - } - }, - "CreateNotification": { - "1": { - "version": 1, - "hash": "7e426c946b7d5db6f9427960ec16042f3018091d835ca5966f3568c324a2ab53", - "action": "add" - } - }, - "NotificationPreferences": { - "1": { - "version": 1, - "hash": "a42f06b367e7c6cbabcbf3cfcc84d1ca0873e457d972ebd060e87c9d6185f62b", - "action": "add" - } - }, - "NotifierSettings": { - "1": { - "version": 1, - "hash": "65c8ab814d35fac32f68d3000756692592cc59940f30e3af3dcdfa2328755b9d", - "action": "add" - } - }, - "SyftImageRegistry": { - "1": { - "version": 1, - "hash": "67e18903e41cba1afe136adf29d404b63ec04fea6e928abb2533ec4fa52b246b", - "action": "add" - } - }, - "SyftWorkerImage": { - "1": { - "version": 1, - "hash": "44da7badfbe573d5403d3ab78c077f17dbefc560b81fdf927b671815be047441", - "action": "add" - } - }, - "SyftWorker": { - "1": { - "version": 1, - "hash": "9d897f6039eabe48dfa8e8d5c5cdcb283b0375b4c64571b457777eaaf3fb1920", - "action": "add" - } - }, - "WorkerPool": { - "1": { - "version": 1, - "hash": "16efc5dd2596ae744fd611c8f46af9eaec1bd5729eb20e85e9fd2f31df402564", - "action": "add" - } - }, - "MarkdownDescription": { - "1": { - "version": 1, - "hash": "31a73f8824cad1636a55d14b6a1074cdb071d0d4e16e86baaa3d4f63a7e80134", - "action": "add" - } - }, - "HTMLObject": { - "1": { - "version": 1, - "hash": "97f2e93f5ceaa88015047186f66a17ff13df2a6b7925b41331f9e19d5a515a9f", - "action": "add" - } - }, - "ServerSettingsUpdate": { - "1": { - "version": 1, - "hash": "1e4260ad879ae80728c3ffae2cd1d48759abd51f9d0960d4b25855cdbb4c506b", - "action": "add" - } - }, - "ServerSettings": { - "1": { - "version": 1, - "hash": "5a1e7470cbeaaae5b80ac9beecb743734f7e4e42d429a09ea8defa569a5ddff1", - "action": "add" - } - }, - "HTTPConnection": { - "1": { - "version": 1, - "hash": "bf10f81646c71069c76292b1237b4a3de1e507264392c5c591d067636ce6fb46", - "action": "add" - } - }, - "PythonConnection": { - "1": { - "version": 1, - "hash": "28010778b5e3463ff6960a0e2224818de00bc7b5e6f892192e02e399ccbe18b5", - "action": "add" - } - }, - "ActionDataEmpty": { - "1": { - "version": 1, - "hash": "e0e4a5cf18d05b6b747addc048515c6f2a5f35f0766ebaee96d898cb971e1c5b", - "action": "add" - } - }, - "ObjectNotReady": { - "1": { - "version": 1, - "hash": "8cf471e205cd0893d6aae5f0227d14db7df1c9698da08a3ab991f59132d17fe9", - "action": "add" - } - }, - "ActionDataLink": { - "1": { - "version": 1, - "hash": "3469478343439e411b761c270eec63eb3d533e459ad72d0965158c3a6cdf3b9a", - "action": "add" - } - }, - "Action": { - "1": { - "version": 1, - "hash": "021826d7c6f69bd0283d025d40661f3ffbeba8810ca94de01344f6afbdae62cd", - "action": "add" - } - }, - "ActionObject": { - "1": { - "version": 1, - "hash": "0a5f4bc343cb114a251f06686ecdbb59d74bfb3d29a098b176699deb35a1e683", - "action": "add" - } - }, - "AnyActionObject": { - "1": { - "version": 1, - "hash": "b3c44c7788c59c03fa1baeec656c2ca6e633f4cbd4b23ff7ece6ee94c38449f0", - "action": "add" - } - }, - "CustomEndpointActionObject": { - "1": { - "version": 1, - "hash": "c7addbaf2777707f3e91e5c1e092343476cd22efc4ec8617f39ccf76e61a5a14", - "action": "add" - } - }, - "DataSubject": { - "1": { - "version": 1, - "hash": "582cdf9e82b5d6915b7f09f7c0d5f08328b11a2ce9b0198e5083f1672c2e2bf5", - "action": "add" - } - }, - "DataSubjectCreate": { - "1": { - "version": 1, - "hash": "5a8423c2690d55f425bfeecc87cd4a797a75d88ebb5fbda754d4f269b62d2ceb", - "action": "add" - } - }, - "DataSubjectMemberRelationship": { - "1": { - "version": 1, - "hash": "0810483ea76ea10c8f286c6035dc0b2085291f345183be50c179f3a05a577110", - "action": "add" - } - }, - "Contributor": { - "1": { - "version": 1, - "hash": "30c32bd44098f00e0b15496be441763b6e50af8b12d3d2bef33aca6287193876", - "action": "add" - } - }, - "Asset": { - "1": { - "version": 1, - "hash": "000abc78719611c106295cf12b1690b7e5411dc1bb9db9d4afd22956da90d1f4", - "action": "add" - } - }, - "CreateAsset": { - "1": { - "version": 1, - "hash": "357d52576cb12b24fb3980342bb49a562b065c0e4419e87d34176340628c7309", - "action": "add" - } - }, - "Dataset": { - "1": { - "version": 1, - "hash": "0ca6b0b4a3aebb2c8f351668075b44951bb20d1e23a779b82109124f334ce3a4", - "action": "add" - } - }, - "DatasetPageView": { - "1": { - "version": 1, - "hash": "aa0dd69637281b80d5523b4409a2c7e89db114c9fe79c858063c6dadff8977d1", - "action": "add" - } - }, - "CreateDataset": { - "1": { - "version": 1, - "hash": "7e02dfa89540c3dbebacbb13810d95cdc4e36db31d56cffed7ab54abe25716c9", - "action": "add" - } - }, - "SyftLog": { - "1": { - "version": 1, - "hash": "1bcd71e5bf3f0db3bba0996f33b6b2bde3489b9c71f11e6b30c3495c76a8f53f", - "action": "add" - } - }, - "JobItem": { - "1": { - "version": 1, - "hash": "0b32277b7d3b9bdc14a2a51cc9005f8254e7f7b6ec059ddcccbcd681a807afb6", - "action": "add" - } - }, - "ExecutionOutput": { - "1": { - "version": 1, - "hash": "e36c71685edf5276a3427cb6749550486d3a177c1dcf73dd337ab2a73c0ce6b5", - "action": "add" - } - }, - "TwinObject": { - "1": { - "version": 1, - "hash": "4f31243fb348dbb083579afd6f638d75af010cb53d19bfba59b74afff41ccbbb", - "action": "add" - } - }, - "PolicyRule": { - "1": { - "version": 1, - "hash": "44d1ca1db97be46f66558aa1a729ff31bf8e113c6a913b11aedf9d6b6ad5b7b5", - "action": "add" - } - }, - "CreatePolicyRule": { - "1": { - "version": 1, - "hash": "342bb723526d445151a0435f57d251f4c1219f8ae7cca3e8e9fce52e2ee1b8b1", - "action": "add" - } - }, - "CreatePolicyRuleConstant": { - "1": { - "version": 1, - "hash": "78b54832cb0468a87013bc36bc11d4759874ca1b5065a1b711f1e5ef5d94c2df", - "action": "add" - } - }, - "Matches": { - "1": { - "version": 1, - "hash": "dd6d91ddb2ec5eaf60be2b0899ecfdb9a15f7904aa39d2f4d9bb2d7b793040e6", - "action": "add" - } - }, - "PreFill": { - "1": { - "version": 1, - "hash": "c7aefb11dc4c4569dcd1e6988371047a32a8be1b32ad46d12adba419a19769ad", - "action": "add" - } - }, - "UserOwned": { - "1": { - "version": 1, - "hash": "c8738dc3d8c2a5ef461b85a0467c3dff53dab16b54a4d12b44b1477906aef51d", - "action": "add" - } - }, - "MixedInputPolicy": { - "1": { - "version": 1, - "hash": "37bb12d950518d9579c8ec7c4cc22ac731ea82caf8c1370dd0b0a82b46462dde", - "action": "add" - } - }, - "ExactMatch": { - "1": { - "version": 1, - "hash": "5eb37edbf5e451d942e599247f3eaed923c1fe9d91eefdba02bf06503f6cc08d", - "action": "add" - } - }, - "OutputHistory": { - "1": { - "version": 1, - "hash": "9366db79d131f8c65e5a4ff12c90e2aa0c11e302debe06e46eeb93b26e2aaf61", - "action": "add" - } - }, - "OutputPolicyExecuteCount": { - "1": { - "version": 1, - "hash": "2a77e5ed5c7b0391147562651ad4061e20b11745c191fbc34cb549da37ba72dd", - "action": "add" - } - }, - "OutputPolicyExecuteOnce": { - "1": { - "version": 1, - "hash": "5589c00d127d9eb1f5ccf3a16def8219737784d57bb3bf9be5cb6d83325ef436", - "action": "add" - } - }, - "EmptyInputPolicy": { - "1": { - "version": 1, - "hash": "7ef81cfd223be0064600e1503f8b04bafc16385e27730e9319466e68a077c68b", - "action": "add" - } - }, - "UserPolicy": { - "1": { - "version": 1, - "hash": "74373bb71a334f4dcf77623ae10ff5b1c7e5b3006f65f2051ffb1e01f422f982", - "action": "add" - } - }, - "SubmitUserPolicy": { - "1": { - "version": 1, - "hash": "ec4e808eb39613bcdbbbf9ffb3267612084a9d99880a2f3bee3ef32d46329c02", - "action": "add" - } - }, - "UserCodeStatusCollection": { - "1": { - "version": 1, - "hash": "735ecf2d4abb1e7d19b2e751d880f32b01ce267ba10e417ef1b440be3d94d8f1", - "action": "add" - } - }, - "UserCode": { - "1": { - "version": 1, - "hash": "3bcd14413b9c4fbde7c5612c2ed713518340280b5cff89cf2aaaf1c77c4037a8", - "action": "add" - } - }, - "SubmitUserCode": { - "1": { - "version": 1, - "hash": "d2bb8cfe12f070b4adafded78ce01900c5409bd83f055f94b1e285745ef65a76", - "action": "add" - } - }, - "UserCodeExecutionResult": { - "1": { - "version": 1, - "hash": "1f4cbc62caac4dd193f427306405dc7a099ae744bea5830cf57149ce71c1e589", - "action": "add" - } - }, - "UserCodeExecutionOutput": { - "1": { - "version": 1, - "hash": "c1d53300a39dbbb437d7d5a1257bd175a067b1065f4099a0938fac7540035258", - "action": "add" - } - }, - "CodeHistory": { - "1": { - "version": 1, - "hash": "e3ef5346f108257828f364d22b12d9311812c9cf843200afef5dc4d9302f9b21", - "action": "add" - } - }, - "CodeHistoryView": { - "1": { - "version": 1, - "hash": "8b8b97d334b51d1ce0a9efab722411ff25caa3f12be319105954497e0a306eb2", - "action": "add" - } - }, - "CodeHistoriesDict": { - "1": { - "version": 1, - "hash": "01d7dcd4b21525a06e4484d8699a4a34a5c84f1f6026ec55e32eb30412742601", - "action": "add" - } - }, - "UsersCodeHistoriesDict": { - "1": { - "version": 1, - "hash": "4ed8b83973258ea19a1f91feb2590ff73b801be86f4296cc3db48f6929ff784c", - "action": "add" - } - }, - "BlobFile": { - "1": { - "version": 1, - "hash": "d99239100f1cb0b73c69b2ad7cab01a06909cc3a4976ba2b3b67cf6fe5e2f516", - "action": "add" - } - }, - "BlobFileOBject": { - "1": { - "version": 1, - "hash": "6c40dab2c8d2220d4fff7cc653d76cc026a856db7e2b5713b6341e255adc7ea2", - "action": "add" - } - }, - "SecureFilePathLocation": { - "1": { - "version": 1, - "hash": "ea5978b98d7773d221665b450454c9130c103a5c850669a0acd620607cd614b7", - "action": "add" - } - }, - "SeaweedSecureFilePathLocation": { - "1": { - "version": 1, - "hash": "3fc9bfc8c1b1cf660c9747e8c1fe3eb2220e78d4e3b5d6b5c5f29a07a77ebf3e", - "action": "add" - } - }, - "AzureSecureFilePathLocation": { - "1": { - "version": 1, - "hash": "090a9e962eeb655586ee966c5651d8996363969818a38f9a486fd64d33047e05", - "action": "add" - } - }, - "BlobStorageEntry": { - "1": { - "version": 1, - "hash": "afdc6a1d8a24b1ee1ed9d3e79f5bac64b4f0d9d36800f07f10be0b896470345f", - "action": "add" - } - }, - "BlobStorageMetadata": { - "1": { - "version": 1, - "hash": "9d4b61ac4ea1910c2f7c767a50a6a52544a24663548f069e79bd906f11b538e4", - "action": "add" - } - }, - "CreateBlobStorageEntry": { - "1": { - "version": 1, - "hash": "ffc3cbfeade67d074dc5bf7d655a1eb8c83630076028a72b3cc4548f3b413e14", - "action": "add" - } - }, - "SyftObjectMigrationState": { - "1": { - "version": 1, - "hash": "ee83315828551f18904bab18e0cac48896493620561215b04cc448e6ce5834af", - "action": "add" - } - }, - "StoreMetadata": { - "1": { - "version": 1, - "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", - "action": "add" - } - }, - "MigrationData": { - "1": { - "version": 1, - "hash": "cb96b8c8413609e1224341d1b0dd1efb08387c0ff7b0ff65eba36c0b104c9ed1", - "action": "add" - } - }, - "BlobRetrieval": { - "1": { - "version": 1, - "hash": "c422c74b89a9349742acaa848566fe18bfef1a83333458b858c074baed37a859", - "action": "add" - } - }, - "SyftObjectRetrieval": { - "1": { - "version": 1, - "hash": "b2b62447445adc4cd0b77ab59d6fa56624dd316fb50281e570daad07556b6db2", - "action": "add" - } - }, - "BlobRetrievalByURL": { - "1": { - "version": 1, - "hash": "4db0e3b7a6334d3835356d8393866711e243e360af25a95f3cc4066f032404b5", - "action": "add" - } - }, - "BlobDeposit": { - "1": { - "version": 1, - "hash": "6eb5cc57dc763126bfc6ec5a2b79d02e77eadf9d9efb1888a5c366b7799c1c24", - "action": "add" - } - }, - "OnDiskBlobDeposit": { - "1": { - "version": 1, - "hash": "817bf1bee4a35bfa1cd25d6779a10d8d180b1b3f1e837952f81f48b9411d1970", - "action": "add" - } - }, - "RemoteConfig": { - "1": { - "version": 1, - "hash": "179d067099a178d748c6d9a0477e8de7c3b55577439669eca7150258f2409567", - "action": "add" - } - }, - "AzureRemoteConfig": { - "1": { - "version": 1, - "hash": "a143811fec0da5fd881e927643ef667c91c78a2c90519cf88da7da20738bd187", - "action": "add" - } - }, - "SeaweedFSBlobDeposit": { - "1": { - "version": 1, - "hash": "febeb2a2ce81aa2c512e4c6b611b582984042aafa0541403d4584662273a166c", - "action": "add" - } - }, - "DictStoreConfig": { - "1": { - "version": 1, - "hash": "2e1365c5535fa51c22eef79f67dd6444789bc829c27881367e3050e06e2ffbfe", - "action": "add" - } - }, - "NumpyArrayObject": { - "1": { - "version": 1, - "hash": "05dd2917b7692b3daf4e7ad083a46fa7ec7a2be8faac8d4a654809189c986443", - "action": "add" - } - }, - "NumpyScalarObject": { - "1": { - "version": 1, - "hash": "8753e5c78270a5cacbf0439447724772f4765351a4a8b58b0a5c416a6b2c8b6e", - "action": "add" - } - }, - "NumpyBoolObject": { - "1": { - "version": 1, - "hash": "331c44f8fa3d0a077f1aaad7313bae2c43b386d04def7b8bedae9fdf7690134d", - "action": "add" - } - }, - "PandasDataframeObject": { - "1": { - "version": 1, - "hash": "5e8018364cea31d5f185a901da4ab89846b02153ee7d041ee8a6d305ece31f90", - "action": "add" - } - }, - "PandasSeriesObject": { - "1": { - "version": 1, - "hash": "b8bd482bf16fc7177e9778292cd42f8835b6ced2ce8dc88908b4b8e6d7c7528f", - "action": "add" - } - }, - "Change": { - "1": { - "version": 1, - "hash": "75fb9a5cd4e76b189ebe130a421d3921a0c251947a48bbb92a2ef1c315dc3c16", - "action": "add" - } - }, - "ChangeStatus": { - "1": { - "version": 1, - "hash": "c914a6f7637b555a51b71e8e197e591f7a2e28121e29b5dd586f87e0383d179d", - "action": "add" - } - }, - "ActionStoreChange": { - "1": { - "version": 1, - "hash": "1a803bb08924b49f3114fd46e0e132f819d4d56be5e03a27e9fe90947ca26e85", - "action": "add" - } - }, - "CreateCustomImageChange": { - "1": { - "version": 1, - "hash": "c3dbea3f49979fdcc517c0d13cd02739ca2fe86b370c42496a224f142ae31562", - "action": "add" - } - }, - "CreateCustomWorkerPoolChange": { - "1": { - "version": 1, - "hash": "0355793dd58b364dcb84fff29714b6a26446bead3ba95c6d75e3200008e580f4", - "action": "add" - } - }, - "Request": { - "1": { - "version": 1, - "hash": "1d69f5f0074114f99aa29c5ee77cb20b9151e5b50e77b026f11c3632a12efadf", - "action": "add" - } - }, - "RequestInfo": { - "1": { - "version": 1, - "hash": "779562547744ebed64548f8021647292604fdf4256bf79685dfa14a1e56cc27b", - "action": "add" - } - }, - "RequestInfoFilter": { - "1": { - "version": 1, - "hash": "bb881a003032f4676321218d7cd09580f4d64fccaa1cf9e118fdcd5c73c3d3a8", - "action": "add" - } - }, - "SubmitRequest": { - "1": { - "version": 1, - "hash": "6c38b6ffd0a6f7442746e68b9ace7b21cb1dca7d2031929db5f9a302a280403f", - "action": "add" - } - }, - "ObjectMutation": { - "1": { - "version": 1, - "hash": "ce88096760ce9334599c8194ec97b0a1470651ad680d9d21b8826a0df0af2a36", - "action": "add" - } - }, - "EnumMutation": { - "1": { - "version": 1, - "hash": "5173fda73df17a344eb663b7692cca48bd46bf1773455439836b852cd165448c", - "action": "add" - } - }, - "UserCodeStatusChange": { - "1": { - "version": 1, - "hash": "89aaf7f1368c782e3a1b9e79988877f6eaa05ab84365f7d321b757fde7fe86e7", - "action": "add" - } - }, - "SyncedUserCodeStatusChange": { - "1": { - "version": 1, - "hash": "d9ad2d341eb645bd50d06330cd30fd4c266f93e37b9f5391d58b78365fc440e6", - "action": "add" - } - }, - "TwinAPIContextView": { - "1": { - "version": 1, - "hash": "e099eef32cb3a8a806cbdc54cc7fca96bed3d60344bd571163ec049db407938b", - "action": "add" - } - }, - "CustomAPIView": { - "1": { - "version": 1, - "hash": "769e96bebd05736ab860591670fb6da19406239b0104ddc71bd092a134335146", - "action": "add" - } - }, - "CustomApiEndpoint": { - "1": { - "version": 1, - "hash": "ec4a217585336d1b59c93c18570443a63f4fbb24d2c088fbacf80bcf389d23e8", - "action": "add" - } - }, - "PrivateAPIEndpoint": { - "1": { - "version": 1, - "hash": "6d7d143432c2811c520ab6dade005ba40173b590e5c676be04f5921b970ef938", - "action": "add" - } - }, - "PublicAPIEndpoint": { - "1": { - "version": 1, - "hash": "3bf51fc33aa8feb1abc9d0ef792e8889da31a57050430e0bd8e17f2065ff8734", - "action": "add" - } - }, - "UpdateTwinAPIEndpoint": { - "1": { - "version": 1, - "hash": "851e59412716e73c7f70a696619e0b375ce136b43f6fe2ea784747091caba5d8", - "action": "add" - } - }, - "CreateTwinAPIEndpoint": { - "1": { - "version": 1, - "hash": "3d0b84dae95ebcc6647b5aabe54e65b3c6bf957665fde57d8037806a4aac13be", - "action": "add" - } - }, - "TwinAPIEndpoint": { - "1": { - "version": 1, - "hash": "d1947b8f9c80d6c9b443e5a9f0758afa8849a5f12b9a511feefd7e4f82c374f4", - "action": "add" - } - }, - "SyncState": { - "1": { - "version": 1, - "hash": "9a3f0bb973858b55bc766c9770c4d9abcc817898f797d94a89938650c0c67868", - "action": "add" - } - }, - "WorkerSettings": { - "1": { - "version": 1, - "hash": "b8ddbe75a95b0312a64b5f25e0fc415aeac5c391975d02b515db8c848482f737", - "action": "add" - } - }, - "HTTPServerRoute": { - "1": { - "version": 1, - "hash": "938245604a9c7e50001299afff5b669b2548364e356fed22a22780497831bf81", - "action": "add" - } - }, - "PythonServerRoute": { - "1": { - "version": 1, - "hash": "a068d8f942d55ecb6d45af88a27c6ebf208584275bf589cbc308df3f774ab9a9", - "action": "add" - } - }, - "VeilidServerRoute": { - "1": { - "version": 1, - "hash": "e676bc165601d2ede69707a4b6168ed4674f3f98887026d098a2dd4da4dfd097", - "action": "add" - } - }, - "ServerPeer": { - "1": { - "version": 1, - "hash": "0d5f252018e324ea0d2dcb5c2ad8bd15707220565fce4f14de7f63a8f9e4391b", - "action": "add" - } - }, - "ServerPeerUpdate": { - "1": { - "version": 1, - "hash": "0b854b57db7a18118c1fd8f31495b2ba4eeb9fbe4f24c631ff112418a94570d3", - "action": "add" - } - }, - "AssociationRequestChange": { - "1": { - "version": 1, - "hash": "0134ac0002879c85fc9ddb06bed6306a8905c8434b0a40d3a96ce24a7bd4da90", - "action": "add" - } - }, - "QueueItem": { - "1": { - "version": 1, - "hash": "1db212c46b6c56ccc5579cfe2141b693f0cd9286e2ede71210393e8455379bf1", - "action": "add" - } - }, - "ActionQueueItem": { - "1": { - "version": 1, - "hash": "396d579dfc2e2b36b9fbed2f204bffcca1bea7ee2db7175045dd3328ebf08718", - "action": "add" - } - }, - "APIEndpointQueueItem": { - "1": { - "version": 1, - "hash": "f04b3990a8d29c116d301e70df54d58f188895307a411dc13a666ff764ffd8dd", - "action": "add" - } - }, - "ZMQClientConfig": { - "1": { - "version": 1, - "hash": "36ee8f75067d5144f0ed062cdc79466caae16b7a128231d89b6b430174843bde", - "action": "add" - } - }, - "SQLiteStoreConfig": { - "1": { - "version": 1, - "hash": "ad062a5f863ae84683867d2a6a5e1d4420c010a64b88bc7b392106e33d71ac03", - "action": "add" - } - }, - "ProjectEvent": { - "1": { - "version": 1, - "hash": "dc0486c52daebd5e98c2b3b03ffd9a9a14bc3d86d8dc0c23e41ebf6c31fe2ffb", - "action": "add" - } - }, - "ProjectThreadMessage": { - "1": { - "version": 1, - "hash": "99256d7592577d1e37df94a06eabc0a287f2d79e144c51fd719315e278edb46d", - "action": "add" - } - }, - "ProjectMessage": { - "1": { - "version": 1, - "hash": "b5004b6354f71b19c81dd5f4b20bf446e0b959f5608a22707e96b944dd8175b0", - "action": "add" - } - }, - "ProjectRequestResponse": { - "1": { - "version": 1, - "hash": "52162a8a779a4a301d8755691bf4cf994c86b9f650f9e8c8a923b44e635b1bc0", - "action": "add" - } - }, - "ProjectRequest": { - "1": { - "version": 1, - "hash": "dc684135d5a5a48e5fc7988598c1e6e0de76cf1c5995f1c283fcf63d0eb4d24f", - "action": "add" - } - }, - "AnswerProjectPoll": { - "1": { - "version": 1, - "hash": "c83d83a5ba6cc034d5061df200b3f1d029aa770b1e13dbef959bb1790323dc6e", - "action": "add" - } - }, - "ProjectPoll": { - "1": { - "version": 1, - "hash": "ecf69b3b324e0bee9c82295796d44c4e8f796496cdc9db6d4302c2f160566466", - "action": "add" - } - }, - "Project": { - "1": { - "version": 1, - "hash": "de86a1163ddbcd1cc3cc2b1b5dfcb85a8ad9f9d4bbc759c2b1f92a0d0a2ff184", - "action": "add" - } - }, - "ProjectSubmit": { - "1": { - "version": 1, - "hash": "7555ba11ee5a814dcd9c45647300020f7359efc1081559940990cbd745936cac", - "action": "add" - } - }, - "Plan": { - "1": { - "version": 1, - "hash": "ed05cb87aec832098fc464ac36cd6bceaab705463d0d2fa1b2d8e1ccc510018c", - "action": "add" - } - } - } + "1": { + "release_name": "0.8.7.json" } } diff --git a/packages/syft/src/syft/protocol/releases/0.8.7.json b/packages/syft/src/syft/protocol/releases/0.8.7.json new file mode 100644 index 00000000000..536491dd205 --- /dev/null +++ b/packages/syft/src/syft/protocol/releases/0.8.7.json @@ -0,0 +1,1077 @@ +{ + "1": { + "object_versions": { + "SyftObjectVersioned": { + "1": { + "version": 1, + "hash": "7c842dcdbb57e2528ffa690ea18c19fff3c8a591811d40cad2b19be3100e2ff4", + "action": "add" + } + }, + "BaseDateTime": { + "1": { + "version": 1, + "hash": "614db484b1950be729902b1861bd3a7b33899176507c61cef11dc0d44611cfd3", + "action": "add" + } + }, + "SyftObject": { + "1": { + "version": 1, + "hash": "bb70d874355988908d3a92a3941d6613a6995a4850be3b6a0147f4d387724406", + "action": "add" + } + }, + "PartialSyftObject": { + "1": { + "version": 1, + "hash": "19a995fcc2833f4fab24584fd99b71a80c2ef1f13c06f83af79e4482846b1656", + "action": "add" + } + }, + "ServerMetadata": { + "1": { + "version": 1, + "hash": "1691c7667eca86b20c4189e90ce4e643dd41fd3682cdb69c6308878f2a6f135c", + "action": "add" + } + }, + "StoreConfig": { + "1": { + "version": 1, + "hash": "a9997fce6a8a0ed2884c58b8eb9382f8554bdd18fff61f8bf0451945bcff12c7", + "action": "add" + } + }, + "MongoDict": { + "1": { + "version": 1, + "hash": "57e36f57eed75e62b29e2bac1295035a9bf2c0e3c56719dac24cb6cc685be00b", + "action": "add" + } + }, + "MongoStoreConfig": { + "1": { + "version": 1, + "hash": "53342b27d34165b7e2699f8e7ad70d13d125875e6a75e8fa18f5796428f41036", + "action": "add" + } + }, + "LinkedObject": { + "1": { + "version": 1, + "hash": "d80f5ac7f51a9383be1a3cb334d56ae50e49733ed3199f3b6b5d6febd9de410b", + "action": "add" + } + }, + "BaseConfig": { + "1": { + "version": 1, + "hash": "10bd7566041d0f0a3aa295367785fdcc2c5bbf0ded984ac9230754f37496a6a7", + "action": "add" + } + }, + "ServiceConfig": { + "1": { + "version": 1, + "hash": "28af8a296f5ff63de50438277eaa1f4380682e6aca9f2ca28320d7a444825e88", + "action": "add" + } + }, + "LibConfig": { + "1": { + "version": 1, + "hash": "ee8f0e3f6aae81948d72e30226645e8eb5d312a6770411a1edca748168c467c0", + "action": "add" + } + }, + "APIEndpoint": { + "1": { + "version": 1, + "hash": "cfa6f314481a5bf3c448c33bf2312a9c33cbcf03cdc96864ad9a108f62b09346", + "action": "add" + } + }, + "LibEndpoint": { + "1": { + "version": 1, + "hash": "a585c83a33a019d363ae5a0c6d4197193654307c19a4829dfbf8a8cfd2c1842a", + "action": "add" + } + }, + "SignedSyftAPICall": { + "1": { + "version": 1, + "hash": "2f959455f7130f4e59360b8aa58f19785b76eaa0f8a5a9188a6cbf32b31311ca", + "action": "add" + } + }, + "SyftAPICall": { + "1": { + "version": 1, + "hash": "59e89e7b9ea30deaed64d1ffd9bc0769b999d3082b305428432c1f5be36c6343", + "action": "add" + } + }, + "SyftAPIData": { + "1": { + "version": 1, + "hash": "820b279c581cafd9bb5009702d4e3db22ec3a3156676426304b9038dad260a24", + "action": "add" + } + }, + "SyftAPI": { + "1": { + "version": 1, + "hash": "cc13ab058ee36748c14b0d4bd9b9e894c7566fff09cfa4170b3eece520169f15", + "action": "add" + } + }, + "User": { + "1": { + "version": 1, + "hash": "2df4b68182c558dba5485a8a6867acf2a5c341b249ad67373a504098aa8c4343", + "action": "add" + } + }, + "UserUpdate": { + "1": { + "version": 1, + "hash": "1bf6707c69b809c804fb939c7c37d787c2f6889508a4bec37d24221af2eb777a", + "action": "add" + } + }, + "UserCreate": { + "1": { + "version": 1, + "hash": "49d6087e2309ba59987f3126e286e74b3a66492a08ad82fa507ea17d52ce78e3", + "action": "add" + } + }, + "UserSearch": { + "1": { + "version": 1, + "hash": "9ac946338cca68d00d1696a57943442f062628ec3daf53077d0bdd3f72cd9fa0", + "action": "add" + } + }, + "UserView": { + "1": { + "version": 1, + "hash": "0b52d758e31d5889c9cd88afb467aae4a74e34a5276924e07012243c34d300fe", + "action": "add" + } + }, + "UserViewPage": { + "1": { + "version": 1, + "hash": "1cd6528d02ec180f080d5c35f0da760d8a59af9da7baaa9c17c1c7cedcc858fa", + "action": "add" + } + }, + "UserPrivateKey": { + "1": { + "version": 1, + "hash": "4817d8147aba94373f320dcd90e65f097cf6e5a2ef353aa8520e23128d522b5d", + "action": "add" + } + }, + "DateTime": { + "1": { + "version": 1, + "hash": "394abb554114ead4d63c36e3fe83ac018dead4b21a8465174009577c46d54c58", + "action": "add" + } + }, + "ReplyNotification": { + "1": { + "version": 1, + "hash": "84102dfc59d711b03c2f3d3a6ecaca000b6835f1bbdd9af801057f7aacb5f1d0", + "action": "add" + } + }, + "Notification": { + "1": { + "version": 1, + "hash": "af4cb232bff390c431e399975f048b34da7e940ace8b23b940a3b398c91c5326", + "action": "add" + } + }, + "CreateNotification": { + "1": { + "version": 1, + "hash": "7e426c946b7d5db6f9427960ec16042f3018091d835ca5966f3568c324a2ab53", + "action": "add" + } + }, + "NotificationPreferences": { + "1": { + "version": 1, + "hash": "a42f06b367e7c6cbabcbf3cfcc84d1ca0873e457d972ebd060e87c9d6185f62b", + "action": "add" + } + }, + "NotifierSettings": { + "1": { + "version": 1, + "hash": "65c8ab814d35fac32f68d3000756692592cc59940f30e3af3dcdfa2328755b9d", + "action": "add" + } + }, + "SyftImageRegistry": { + "1": { + "version": 1, + "hash": "67e18903e41cba1afe136adf29d404b63ec04fea6e928abb2533ec4fa52b246b", + "action": "add" + } + }, + "SyftWorkerImage": { + "1": { + "version": 1, + "hash": "44da7badfbe573d5403d3ab78c077f17dbefc560b81fdf927b671815be047441", + "action": "add" + } + }, + "SyftWorker": { + "1": { + "version": 1, + "hash": "9d897f6039eabe48dfa8e8d5c5cdcb283b0375b4c64571b457777eaaf3fb1920", + "action": "add" + } + }, + "WorkerPool": { + "1": { + "version": 1, + "hash": "16efc5dd2596ae744fd611c8f46af9eaec1bd5729eb20e85e9fd2f31df402564", + "action": "add" + } + }, + "MarkdownDescription": { + "1": { + "version": 1, + "hash": "31a73f8824cad1636a55d14b6a1074cdb071d0d4e16e86baaa3d4f63a7e80134", + "action": "add" + } + }, + "HTMLObject": { + "1": { + "version": 1, + "hash": "97f2e93f5ceaa88015047186f66a17ff13df2a6b7925b41331f9e19d5a515a9f", + "action": "add" + } + }, + "ServerSettingsUpdate": { + "1": { + "version": 1, + "hash": "1e4260ad879ae80728c3ffae2cd1d48759abd51f9d0960d4b25855cdbb4c506b", + "action": "add" + } + }, + "ServerSettings": { + "1": { + "version": 1, + "hash": "5a1e7470cbeaaae5b80ac9beecb743734f7e4e42d429a09ea8defa569a5ddff1", + "action": "add" + } + }, + "HTTPConnection": { + "1": { + "version": 1, + "hash": "bf10f81646c71069c76292b1237b4a3de1e507264392c5c591d067636ce6fb46", + "action": "add" + } + }, + "PythonConnection": { + "1": { + "version": 1, + "hash": "28010778b5e3463ff6960a0e2224818de00bc7b5e6f892192e02e399ccbe18b5", + "action": "add" + } + }, + "ActionDataEmpty": { + "1": { + "version": 1, + "hash": "e0e4a5cf18d05b6b747addc048515c6f2a5f35f0766ebaee96d898cb971e1c5b", + "action": "add" + } + }, + "ObjectNotReady": { + "1": { + "version": 1, + "hash": "8cf471e205cd0893d6aae5f0227d14db7df1c9698da08a3ab991f59132d17fe9", + "action": "add" + } + }, + "ActionDataLink": { + "1": { + "version": 1, + "hash": "3469478343439e411b761c270eec63eb3d533e459ad72d0965158c3a6cdf3b9a", + "action": "add" + } + }, + "Action": { + "1": { + "version": 1, + "hash": "021826d7c6f69bd0283d025d40661f3ffbeba8810ca94de01344f6afbdae62cd", + "action": "add" + } + }, + "ActionObject": { + "1": { + "version": 1, + "hash": "0a5f4bc343cb114a251f06686ecdbb59d74bfb3d29a098b176699deb35a1e683", + "action": "add" + } + }, + "AnyActionObject": { + "1": { + "version": 1, + "hash": "b3c44c7788c59c03fa1baeec656c2ca6e633f4cbd4b23ff7ece6ee94c38449f0", + "action": "add" + } + }, + "CustomEndpointActionObject": { + "1": { + "version": 1, + "hash": "c7addbaf2777707f3e91e5c1e092343476cd22efc4ec8617f39ccf76e61a5a14", + "action": "add" + } + }, + "DataSubject": { + "1": { + "version": 1, + "hash": "582cdf9e82b5d6915b7f09f7c0d5f08328b11a2ce9b0198e5083f1672c2e2bf5", + "action": "add" + } + }, + "DataSubjectCreate": { + "1": { + "version": 1, + "hash": "5a8423c2690d55f425bfeecc87cd4a797a75d88ebb5fbda754d4f269b62d2ceb", + "action": "add" + } + }, + "DataSubjectMemberRelationship": { + "1": { + "version": 1, + "hash": "0810483ea76ea10c8f286c6035dc0b2085291f345183be50c179f3a05a577110", + "action": "add" + } + }, + "Contributor": { + "1": { + "version": 1, + "hash": "30c32bd44098f00e0b15496be441763b6e50af8b12d3d2bef33aca6287193876", + "action": "add" + } + }, + "Asset": { + "1": { + "version": 1, + "hash": "000abc78719611c106295cf12b1690b7e5411dc1bb9db9d4afd22956da90d1f4", + "action": "add" + } + }, + "CreateAsset": { + "1": { + "version": 1, + "hash": "357d52576cb12b24fb3980342bb49a562b065c0e4419e87d34176340628c7309", + "action": "add" + } + }, + "Dataset": { + "1": { + "version": 1, + "hash": "0ca6b0b4a3aebb2c8f351668075b44951bb20d1e23a779b82109124f334ce3a4", + "action": "add" + } + }, + "DatasetPageView": { + "1": { + "version": 1, + "hash": "aa0dd69637281b80d5523b4409a2c7e89db114c9fe79c858063c6dadff8977d1", + "action": "add" + } + }, + "CreateDataset": { + "1": { + "version": 1, + "hash": "7e02dfa89540c3dbebacbb13810d95cdc4e36db31d56cffed7ab54abe25716c9", + "action": "add" + } + }, + "SyftLog": { + "1": { + "version": 1, + "hash": "1bcd71e5bf3f0db3bba0996f33b6b2bde3489b9c71f11e6b30c3495c76a8f53f", + "action": "add" + } + }, + "JobItem": { + "1": { + "version": 1, + "hash": "0b32277b7d3b9bdc14a2a51cc9005f8254e7f7b6ec059ddcccbcd681a807afb6", + "action": "add" + } + }, + "ExecutionOutput": { + "1": { + "version": 1, + "hash": "e36c71685edf5276a3427cb6749550486d3a177c1dcf73dd337ab2a73c0ce6b5", + "action": "add" + } + }, + "TwinObject": { + "1": { + "version": 1, + "hash": "4f31243fb348dbb083579afd6f638d75af010cb53d19bfba59b74afff41ccbbb", + "action": "add" + } + }, + "PolicyRule": { + "1": { + "version": 1, + "hash": "44d1ca1db97be46f66558aa1a729ff31bf8e113c6a913b11aedf9d6b6ad5b7b5", + "action": "add" + } + }, + "CreatePolicyRule": { + "1": { + "version": 1, + "hash": "342bb723526d445151a0435f57d251f4c1219f8ae7cca3e8e9fce52e2ee1b8b1", + "action": "add" + } + }, + "CreatePolicyRuleConstant": { + "1": { + "version": 1, + "hash": "78b54832cb0468a87013bc36bc11d4759874ca1b5065a1b711f1e5ef5d94c2df", + "action": "add" + } + }, + "Matches": { + "1": { + "version": 1, + "hash": "dd6d91ddb2ec5eaf60be2b0899ecfdb9a15f7904aa39d2f4d9bb2d7b793040e6", + "action": "add" + } + }, + "PreFill": { + "1": { + "version": 1, + "hash": "c7aefb11dc4c4569dcd1e6988371047a32a8be1b32ad46d12adba419a19769ad", + "action": "add" + } + }, + "UserOwned": { + "1": { + "version": 1, + "hash": "c8738dc3d8c2a5ef461b85a0467c3dff53dab16b54a4d12b44b1477906aef51d", + "action": "add" + } + }, + "MixedInputPolicy": { + "1": { + "version": 1, + "hash": "37bb12d950518d9579c8ec7c4cc22ac731ea82caf8c1370dd0b0a82b46462dde", + "action": "add" + } + }, + "ExactMatch": { + "1": { + "version": 1, + "hash": "5eb37edbf5e451d942e599247f3eaed923c1fe9d91eefdba02bf06503f6cc08d", + "action": "add" + } + }, + "OutputHistory": { + "1": { + "version": 1, + "hash": "9366db79d131f8c65e5a4ff12c90e2aa0c11e302debe06e46eeb93b26e2aaf61", + "action": "add" + } + }, + "OutputPolicyExecuteCount": { + "1": { + "version": 1, + "hash": "2a77e5ed5c7b0391147562651ad4061e20b11745c191fbc34cb549da37ba72dd", + "action": "add" + } + }, + "OutputPolicyExecuteOnce": { + "1": { + "version": 1, + "hash": "5589c00d127d9eb1f5ccf3a16def8219737784d57bb3bf9be5cb6d83325ef436", + "action": "add" + } + }, + "EmptyInputPolicy": { + "1": { + "version": 1, + "hash": "7ef81cfd223be0064600e1503f8b04bafc16385e27730e9319466e68a077c68b", + "action": "add" + } + }, + "UserPolicy": { + "1": { + "version": 1, + "hash": "74373bb71a334f4dcf77623ae10ff5b1c7e5b3006f65f2051ffb1e01f422f982", + "action": "add" + } + }, + "SubmitUserPolicy": { + "1": { + "version": 1, + "hash": "ec4e808eb39613bcdbbbf9ffb3267612084a9d99880a2f3bee3ef32d46329c02", + "action": "add" + } + }, + "UserCodeStatusCollection": { + "1": { + "version": 1, + "hash": "735ecf2d4abb1e7d19b2e751d880f32b01ce267ba10e417ef1b440be3d94d8f1", + "action": "add" + } + }, + "UserCode": { + "1": { + "version": 1, + "hash": "3bcd14413b9c4fbde7c5612c2ed713518340280b5cff89cf2aaaf1c77c4037a8", + "action": "add" + } + }, + "SubmitUserCode": { + "1": { + "version": 1, + "hash": "d2bb8cfe12f070b4adafded78ce01900c5409bd83f055f94b1e285745ef65a76", + "action": "add" + } + }, + "UserCodeExecutionResult": { + "1": { + "version": 1, + "hash": "1f4cbc62caac4dd193f427306405dc7a099ae744bea5830cf57149ce71c1e589", + "action": "add" + } + }, + "UserCodeExecutionOutput": { + "1": { + "version": 1, + "hash": "c1d53300a39dbbb437d7d5a1257bd175a067b1065f4099a0938fac7540035258", + "action": "add" + } + }, + "CodeHistory": { + "1": { + "version": 1, + "hash": "e3ef5346f108257828f364d22b12d9311812c9cf843200afef5dc4d9302f9b21", + "action": "add" + } + }, + "CodeHistoryView": { + "1": { + "version": 1, + "hash": "8b8b97d334b51d1ce0a9efab722411ff25caa3f12be319105954497e0a306eb2", + "action": "add" + } + }, + "CodeHistoriesDict": { + "1": { + "version": 1, + "hash": "01d7dcd4b21525a06e4484d8699a4a34a5c84f1f6026ec55e32eb30412742601", + "action": "add" + } + }, + "UsersCodeHistoriesDict": { + "1": { + "version": 1, + "hash": "4ed8b83973258ea19a1f91feb2590ff73b801be86f4296cc3db48f6929ff784c", + "action": "add" + } + }, + "BlobFile": { + "1": { + "version": 1, + "hash": "d99239100f1cb0b73c69b2ad7cab01a06909cc3a4976ba2b3b67cf6fe5e2f516", + "action": "add" + } + }, + "BlobFileOBject": { + "1": { + "version": 1, + "hash": "6c40dab2c8d2220d4fff7cc653d76cc026a856db7e2b5713b6341e255adc7ea2", + "action": "add" + } + }, + "SecureFilePathLocation": { + "1": { + "version": 1, + "hash": "ea5978b98d7773d221665b450454c9130c103a5c850669a0acd620607cd614b7", + "action": "add" + } + }, + "SeaweedSecureFilePathLocation": { + "1": { + "version": 1, + "hash": "3fc9bfc8c1b1cf660c9747e8c1fe3eb2220e78d4e3b5d6b5c5f29a07a77ebf3e", + "action": "add" + } + }, + "AzureSecureFilePathLocation": { + "1": { + "version": 1, + "hash": "090a9e962eeb655586ee966c5651d8996363969818a38f9a486fd64d33047e05", + "action": "add" + } + }, + "BlobStorageEntry": { + "1": { + "version": 1, + "hash": "afdc6a1d8a24b1ee1ed9d3e79f5bac64b4f0d9d36800f07f10be0b896470345f", + "action": "add" + } + }, + "BlobStorageMetadata": { + "1": { + "version": 1, + "hash": "9d4b61ac4ea1910c2f7c767a50a6a52544a24663548f069e79bd906f11b538e4", + "action": "add" + } + }, + "CreateBlobStorageEntry": { + "1": { + "version": 1, + "hash": "ffc3cbfeade67d074dc5bf7d655a1eb8c83630076028a72b3cc4548f3b413e14", + "action": "add" + } + }, + "SyftObjectMigrationState": { + "1": { + "version": 1, + "hash": "ee83315828551f18904bab18e0cac48896493620561215b04cc448e6ce5834af", + "action": "add" + } + }, + "StoreMetadata": { + "1": { + "version": 1, + "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", + "action": "add" + } + }, + "MigrationData": { + "1": { + "version": 1, + "hash": "cb96b8c8413609e1224341d1b0dd1efb08387c0ff7b0ff65eba36c0b104c9ed1", + "action": "add" + } + }, + "BlobRetrieval": { + "1": { + "version": 1, + "hash": "c422c74b89a9349742acaa848566fe18bfef1a83333458b858c074baed37a859", + "action": "add" + } + }, + "SyftObjectRetrieval": { + "1": { + "version": 1, + "hash": "b2b62447445adc4cd0b77ab59d6fa56624dd316fb50281e570daad07556b6db2", + "action": "add" + } + }, + "BlobRetrievalByURL": { + "1": { + "version": 1, + "hash": "4db0e3b7a6334d3835356d8393866711e243e360af25a95f3cc4066f032404b5", + "action": "add" + } + }, + "BlobDeposit": { + "1": { + "version": 1, + "hash": "6eb5cc57dc763126bfc6ec5a2b79d02e77eadf9d9efb1888a5c366b7799c1c24", + "action": "add" + } + }, + "OnDiskBlobDeposit": { + "1": { + "version": 1, + "hash": "817bf1bee4a35bfa1cd25d6779a10d8d180b1b3f1e837952f81f48b9411d1970", + "action": "add" + } + }, + "RemoteConfig": { + "1": { + "version": 1, + "hash": "179d067099a178d748c6d9a0477e8de7c3b55577439669eca7150258f2409567", + "action": "add" + } + }, + "AzureRemoteConfig": { + "1": { + "version": 1, + "hash": "a143811fec0da5fd881e927643ef667c91c78a2c90519cf88da7da20738bd187", + "action": "add" + } + }, + "SeaweedFSBlobDeposit": { + "1": { + "version": 1, + "hash": "febeb2a2ce81aa2c512e4c6b611b582984042aafa0541403d4584662273a166c", + "action": "add" + } + }, + "DictStoreConfig": { + "1": { + "version": 1, + "hash": "2e1365c5535fa51c22eef79f67dd6444789bc829c27881367e3050e06e2ffbfe", + "action": "add" + } + }, + "NumpyArrayObject": { + "1": { + "version": 1, + "hash": "05dd2917b7692b3daf4e7ad083a46fa7ec7a2be8faac8d4a654809189c986443", + "action": "add" + } + }, + "NumpyScalarObject": { + "1": { + "version": 1, + "hash": "8753e5c78270a5cacbf0439447724772f4765351a4a8b58b0a5c416a6b2c8b6e", + "action": "add" + } + }, + "NumpyBoolObject": { + "1": { + "version": 1, + "hash": "331c44f8fa3d0a077f1aaad7313bae2c43b386d04def7b8bedae9fdf7690134d", + "action": "add" + } + }, + "PandasDataframeObject": { + "1": { + "version": 1, + "hash": "5e8018364cea31d5f185a901da4ab89846b02153ee7d041ee8a6d305ece31f90", + "action": "add" + } + }, + "PandasSeriesObject": { + "1": { + "version": 1, + "hash": "b8bd482bf16fc7177e9778292cd42f8835b6ced2ce8dc88908b4b8e6d7c7528f", + "action": "add" + } + }, + "Change": { + "1": { + "version": 1, + "hash": "75fb9a5cd4e76b189ebe130a421d3921a0c251947a48bbb92a2ef1c315dc3c16", + "action": "add" + } + }, + "ChangeStatus": { + "1": { + "version": 1, + "hash": "c914a6f7637b555a51b71e8e197e591f7a2e28121e29b5dd586f87e0383d179d", + "action": "add" + } + }, + "ActionStoreChange": { + "1": { + "version": 1, + "hash": "1a803bb08924b49f3114fd46e0e132f819d4d56be5e03a27e9fe90947ca26e85", + "action": "add" + } + }, + "CreateCustomImageChange": { + "1": { + "version": 1, + "hash": "c3dbea3f49979fdcc517c0d13cd02739ca2fe86b370c42496a224f142ae31562", + "action": "add" + } + }, + "CreateCustomWorkerPoolChange": { + "1": { + "version": 1, + "hash": "0355793dd58b364dcb84fff29714b6a26446bead3ba95c6d75e3200008e580f4", + "action": "add" + } + }, + "Request": { + "1": { + "version": 1, + "hash": "1d69f5f0074114f99aa29c5ee77cb20b9151e5b50e77b026f11c3632a12efadf", + "action": "add" + } + }, + "RequestInfo": { + "1": { + "version": 1, + "hash": "779562547744ebed64548f8021647292604fdf4256bf79685dfa14a1e56cc27b", + "action": "add" + } + }, + "RequestInfoFilter": { + "1": { + "version": 1, + "hash": "bb881a003032f4676321218d7cd09580f4d64fccaa1cf9e118fdcd5c73c3d3a8", + "action": "add" + } + }, + "SubmitRequest": { + "1": { + "version": 1, + "hash": "6c38b6ffd0a6f7442746e68b9ace7b21cb1dca7d2031929db5f9a302a280403f", + "action": "add" + } + }, + "ObjectMutation": { + "1": { + "version": 1, + "hash": "ce88096760ce9334599c8194ec97b0a1470651ad680d9d21b8826a0df0af2a36", + "action": "add" + } + }, + "EnumMutation": { + "1": { + "version": 1, + "hash": "5173fda73df17a344eb663b7692cca48bd46bf1773455439836b852cd165448c", + "action": "add" + } + }, + "UserCodeStatusChange": { + "1": { + "version": 1, + "hash": "89aaf7f1368c782e3a1b9e79988877f6eaa05ab84365f7d321b757fde7fe86e7", + "action": "add" + } + }, + "SyncedUserCodeStatusChange": { + "1": { + "version": 1, + "hash": "d9ad2d341eb645bd50d06330cd30fd4c266f93e37b9f5391d58b78365fc440e6", + "action": "add" + } + }, + "TwinAPIContextView": { + "1": { + "version": 1, + "hash": "e099eef32cb3a8a806cbdc54cc7fca96bed3d60344bd571163ec049db407938b", + "action": "add" + } + }, + "CustomAPIView": { + "1": { + "version": 1, + "hash": "769e96bebd05736ab860591670fb6da19406239b0104ddc71bd092a134335146", + "action": "add" + } + }, + "CustomApiEndpoint": { + "1": { + "version": 1, + "hash": "ec4a217585336d1b59c93c18570443a63f4fbb24d2c088fbacf80bcf389d23e8", + "action": "add" + } + }, + "PrivateAPIEndpoint": { + "1": { + "version": 1, + "hash": "6d7d143432c2811c520ab6dade005ba40173b590e5c676be04f5921b970ef938", + "action": "add" + } + }, + "PublicAPIEndpoint": { + "1": { + "version": 1, + "hash": "3bf51fc33aa8feb1abc9d0ef792e8889da31a57050430e0bd8e17f2065ff8734", + "action": "add" + } + }, + "UpdateTwinAPIEndpoint": { + "1": { + "version": 1, + "hash": "851e59412716e73c7f70a696619e0b375ce136b43f6fe2ea784747091caba5d8", + "action": "add" + } + }, + "CreateTwinAPIEndpoint": { + "1": { + "version": 1, + "hash": "3d0b84dae95ebcc6647b5aabe54e65b3c6bf957665fde57d8037806a4aac13be", + "action": "add" + } + }, + "TwinAPIEndpoint": { + "1": { + "version": 1, + "hash": "d1947b8f9c80d6c9b443e5a9f0758afa8849a5f12b9a511feefd7e4f82c374f4", + "action": "add" + } + }, + "SyncState": { + "1": { + "version": 1, + "hash": "9a3f0bb973858b55bc766c9770c4d9abcc817898f797d94a89938650c0c67868", + "action": "add" + } + }, + "WorkerSettings": { + "1": { + "version": 1, + "hash": "b8ddbe75a95b0312a64b5f25e0fc415aeac5c391975d02b515db8c848482f737", + "action": "add" + } + }, + "HTTPServerRoute": { + "1": { + "version": 1, + "hash": "938245604a9c7e50001299afff5b669b2548364e356fed22a22780497831bf81", + "action": "add" + } + }, + "PythonServerRoute": { + "1": { + "version": 1, + "hash": "a068d8f942d55ecb6d45af88a27c6ebf208584275bf589cbc308df3f774ab9a9", + "action": "add" + } + }, + "VeilidServerRoute": { + "1": { + "version": 1, + "hash": "e676bc165601d2ede69707a4b6168ed4674f3f98887026d098a2dd4da4dfd097", + "action": "add" + } + }, + "ServerPeer": { + "1": { + "version": 1, + "hash": "0d5f252018e324ea0d2dcb5c2ad8bd15707220565fce4f14de7f63a8f9e4391b", + "action": "add" + } + }, + "ServerPeerUpdate": { + "1": { + "version": 1, + "hash": "0b854b57db7a18118c1fd8f31495b2ba4eeb9fbe4f24c631ff112418a94570d3", + "action": "add" + } + }, + "AssociationRequestChange": { + "1": { + "version": 1, + "hash": "0134ac0002879c85fc9ddb06bed6306a8905c8434b0a40d3a96ce24a7bd4da90", + "action": "add" + } + }, + "QueueItem": { + "1": { + "version": 1, + "hash": "1db212c46b6c56ccc5579cfe2141b693f0cd9286e2ede71210393e8455379bf1", + "action": "add" + } + }, + "ActionQueueItem": { + "1": { + "version": 1, + "hash": "396d579dfc2e2b36b9fbed2f204bffcca1bea7ee2db7175045dd3328ebf08718", + "action": "add" + } + }, + "APIEndpointQueueItem": { + "1": { + "version": 1, + "hash": "f04b3990a8d29c116d301e70df54d58f188895307a411dc13a666ff764ffd8dd", + "action": "add" + } + }, + "ZMQClientConfig": { + "1": { + "version": 1, + "hash": "36ee8f75067d5144f0ed062cdc79466caae16b7a128231d89b6b430174843bde", + "action": "add" + } + }, + "SQLiteStoreConfig": { + "1": { + "version": 1, + "hash": "ad062a5f863ae84683867d2a6a5e1d4420c010a64b88bc7b392106e33d71ac03", + "action": "add" + } + }, + "ProjectEvent": { + "1": { + "version": 1, + "hash": "dc0486c52daebd5e98c2b3b03ffd9a9a14bc3d86d8dc0c23e41ebf6c31fe2ffb", + "action": "add" + } + }, + "ProjectThreadMessage": { + "1": { + "version": 1, + "hash": "99256d7592577d1e37df94a06eabc0a287f2d79e144c51fd719315e278edb46d", + "action": "add" + } + }, + "ProjectMessage": { + "1": { + "version": 1, + "hash": "b5004b6354f71b19c81dd5f4b20bf446e0b959f5608a22707e96b944dd8175b0", + "action": "add" + } + }, + "ProjectRequestResponse": { + "1": { + "version": 1, + "hash": "52162a8a779a4a301d8755691bf4cf994c86b9f650f9e8c8a923b44e635b1bc0", + "action": "add" + } + }, + "ProjectRequest": { + "1": { + "version": 1, + "hash": "dc684135d5a5a48e5fc7988598c1e6e0de76cf1c5995f1c283fcf63d0eb4d24f", + "action": "add" + } + }, + "AnswerProjectPoll": { + "1": { + "version": 1, + "hash": "c83d83a5ba6cc034d5061df200b3f1d029aa770b1e13dbef959bb1790323dc6e", + "action": "add" + } + }, + "ProjectPoll": { + "1": { + "version": 1, + "hash": "ecf69b3b324e0bee9c82295796d44c4e8f796496cdc9db6d4302c2f160566466", + "action": "add" + } + }, + "Project": { + "1": { + "version": 1, + "hash": "de86a1163ddbcd1cc3cc2b1b5dfcb85a8ad9f9d4bbc759c2b1f92a0d0a2ff184", + "action": "add" + } + }, + "ProjectSubmit": { + "1": { + "version": 1, + "hash": "7555ba11ee5a814dcd9c45647300020f7359efc1081559940990cbd745936cac", + "action": "add" + } + }, + "Plan": { + "1": { + "version": 1, + "hash": "ed05cb87aec832098fc464ac36cd6bceaab705463d0d2fa1b2d8e1ccc510018c", + "action": "add" + } + } + } + } +} \ No newline at end of file From bb2ee514487f5bc430d9b1386805cce6d2a31474 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Fri, 19 Jul 2024 18:47:23 +0530 Subject: [PATCH 110/117] bump to beta version --- .bumpversion.cfg | 2 +- VERSION | 2 +- packages/grid/VERSION | 2 +- packages/grid/backend/grid/images/worker_cpu.dockerfile | 2 +- packages/grid/devspace.yaml | 2 +- packages/grid/frontend/package.json | 2 +- packages/grid/helm/syft/Chart.yaml | 4 ++-- packages/grid/helm/syft/values.yaml | 2 +- packages/syft/setup.cfg | 2 +- packages/syft/src/syft/VERSION | 2 +- packages/syft/src/syft/__init__.py | 2 +- packages/syftcli/manifest.yml | 8 ++++---- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 8259ef220b8..bd749e3c97f 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.7 +current_version = 0.8.8-beta.0 tag = False tag_name = {new_version} commit = True diff --git a/VERSION b/VERSION index 689e705e14c..f6fdfd48ade 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7" +__version__ = "0.8.8-beta.0" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/VERSION b/packages/grid/VERSION index 689e705e14c..f6fdfd48ade 100644 --- a/packages/grid/VERSION +++ b/packages/grid/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7" +__version__ = "0.8.8-beta.0" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/backend/grid/images/worker_cpu.dockerfile b/packages/grid/backend/grid/images/worker_cpu.dockerfile index 16dd6a25499..8f02c55ffed 100644 --- a/packages/grid/backend/grid/images/worker_cpu.dockerfile +++ b/packages/grid/backend/grid/images/worker_cpu.dockerfile @@ -5,7 +5,7 @@ # NOTE: This dockerfile will be built inside a syft-backend container in PROD # Hence COPY will not work the same way in DEV vs. PROD -ARG SYFT_VERSION_TAG="0.8.7" +ARG SYFT_VERSION_TAG="0.8.8-beta.0" FROM openmined/syft-backend:${SYFT_VERSION_TAG} # should match base image python version diff --git a/packages/grid/devspace.yaml b/packages/grid/devspace.yaml index 6855edffe54..caade0cd6b9 100644 --- a/packages/grid/devspace.yaml +++ b/packages/grid/devspace.yaml @@ -28,7 +28,7 @@ vars: DOCKER_IMAGE_RATHOLE: openmined/syft-rathole DOCKER_IMAGE_ENCLAVE_ATTESTATION: openmined/syft-enclave-attestation CONTAINER_REGISTRY: "docker.io" - VERSION: "0.8.7" + VERSION: "0.8.8-beta.0" PLATFORM: $(uname -m | grep -q 'arm64' && echo "arm64" || echo "amd64") # This is a list of `images` that DevSpace can build for this project diff --git a/packages/grid/frontend/package.json b/packages/grid/frontend/package.json index db69dc97b53..cb757ffd1f4 100644 --- a/packages/grid/frontend/package.json +++ b/packages/grid/frontend/package.json @@ -1,6 +1,6 @@ { "name": "syft-ui", - "version": "0.8.7", + "version": "0.8.8-beta.0", "private": true, "scripts": { "dev": "pnpm i && vite dev --host --port 80", diff --git a/packages/grid/helm/syft/Chart.yaml b/packages/grid/helm/syft/Chart.yaml index 8c10e70d217..9d356f6a0c3 100644 --- a/packages/grid/helm/syft/Chart.yaml +++ b/packages/grid/helm/syft/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: syft description: Perform numpy-like analysis on data that remains in someone elses server type: application -version: "0.8.7" -appVersion: "0.8.7" +version: "0.8.8-beta.0" +appVersion: "0.8.8-beta.0" home: https://github.com/OpenMined/PySyft/ icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png diff --git a/packages/grid/helm/syft/values.yaml b/packages/grid/helm/syft/values.yaml index c2437c45ea1..9fd0fd153f1 100644 --- a/packages/grid/helm/syft/values.yaml +++ b/packages/grid/helm/syft/values.yaml @@ -1,7 +1,7 @@ global: # Affects only backend, frontend, and seaweedfs containers registry: docker.io - version: 0.8.7 + version: 0.8.8-beta.0 # Force default secret values for development. DO NOT SET THIS TO FALSE IN PRODUCTION randomizedSecrets: true diff --git a/packages/syft/setup.cfg b/packages/syft/setup.cfg index 222735cfefb..7f3732964ae 100644 --- a/packages/syft/setup.cfg +++ b/packages/syft/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = syft -version = attr: "0.8.7" +version = attr: "0.8.8-beta.0" description = Perform numpy-like analysis on data that remains in someone elses server author = OpenMined author_email = info@openmined.org diff --git a/packages/syft/src/syft/VERSION b/packages/syft/src/syft/VERSION index 689e705e14c..f6fdfd48ade 100644 --- a/packages/syft/src/syft/VERSION +++ b/packages/syft/src/syft/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.7" +__version__ = "0.8.8-beta.0" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index 238d7dc27ee..ad52c9084ab 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.8.7" +__version__ = "0.8.8-beta.0" # stdlib from collections.abc import Callable diff --git a/packages/syftcli/manifest.yml b/packages/syftcli/manifest.yml index 48f44e9bf0d..5a71d3e2f30 100644 --- a/packages/syftcli/manifest.yml +++ b/packages/syftcli/manifest.yml @@ -1,11 +1,11 @@ manifestVersion: 1.0 -syftVersion: 0.8.7 -dockerTag: 0.8.7 +syftVersion: 0.8.8-beta.0 +dockerTag: 0.8.8-beta.0 images: - - docker.io/openmined/syft-frontend:0.8.7 - - docker.io/openmined/syft-backend:0.8.7 + - docker.io/openmined/syft-frontend:0.8.8-beta.0 + - docker.io/openmined/syft-backend:0.8.8-beta.0 - docker.io/library/mongo:7.0.4 - docker.io/traefik:v2.11.0 From 283b070aa0b3f068a9dbb552b86e0d96240c6950 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Fri, 19 Jul 2024 19:14:16 +0530 Subject: [PATCH 111/117] fix linting --- packages/syft/src/syft/protocol/releases/0.8.7.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/syft/src/syft/protocol/releases/0.8.7.json b/packages/syft/src/syft/protocol/releases/0.8.7.json index 536491dd205..f1ea6b84443 100644 --- a/packages/syft/src/syft/protocol/releases/0.8.7.json +++ b/packages/syft/src/syft/protocol/releases/0.8.7.json @@ -1074,4 +1074,4 @@ } } } -} \ No newline at end of file +} From 38801e3c0fd34fa0f69350560bae9ba3be971357 Mon Sep 17 00:00:00 2001 From: alfred-openmined-bot <145415986+alfred-openmined-bot@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:58:53 +0000 Subject: [PATCH 112/117] [syft]bump version --- .bumpversion.cfg | 2 +- VERSION | 2 +- packages/grid/VERSION | 2 +- .../backend/grid/images/worker_cpu.dockerfile | 2 +- packages/grid/devspace.yaml | 2 +- packages/grid/frontend/package.json | 2 +- packages/grid/helm/repo/index.yaml | 197 +-- packages/grid/helm/repo/syft-0.8.8-beta.1.tgz | Bin 0 -> 9977 bytes packages/grid/helm/syft/Chart.yaml | 4 +- packages/grid/helm/syft/templates/NOTES.txt | 1053 +---------------- packages/grid/helm/syft/values.yaml | 2 +- packages/syft/PYPI.md | 88 +- packages/syft/setup.cfg | 2 +- packages/syft/src/syft/VERSION | 2 +- packages/syft/src/syft/__init__.py | 2 +- packages/syftcli/manifest.yml | 8 +- 16 files changed, 166 insertions(+), 1204 deletions(-) create mode 100644 packages/grid/helm/repo/syft-0.8.8-beta.1.tgz diff --git a/.bumpversion.cfg b/.bumpversion.cfg index bd749e3c97f..2ac552c2537 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.8-beta.0 +current_version = 0.8.8-beta.1 tag = False tag_name = {new_version} commit = True diff --git a/VERSION b/VERSION index f6fdfd48ade..8742f2ae357 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.8-beta.0" +__version__ = "0.8.8-beta.1" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/VERSION b/packages/grid/VERSION index f6fdfd48ade..8742f2ae357 100644 --- a/packages/grid/VERSION +++ b/packages/grid/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.8-beta.0" +__version__ = "0.8.8-beta.1" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/grid/backend/grid/images/worker_cpu.dockerfile b/packages/grid/backend/grid/images/worker_cpu.dockerfile index 8f02c55ffed..ce0ed514280 100644 --- a/packages/grid/backend/grid/images/worker_cpu.dockerfile +++ b/packages/grid/backend/grid/images/worker_cpu.dockerfile @@ -5,7 +5,7 @@ # NOTE: This dockerfile will be built inside a syft-backend container in PROD # Hence COPY will not work the same way in DEV vs. PROD -ARG SYFT_VERSION_TAG="0.8.8-beta.0" +ARG SYFT_VERSION_TAG="0.8.8-beta.1" FROM openmined/syft-backend:${SYFT_VERSION_TAG} # should match base image python version diff --git a/packages/grid/devspace.yaml b/packages/grid/devspace.yaml index caade0cd6b9..07985f06baa 100644 --- a/packages/grid/devspace.yaml +++ b/packages/grid/devspace.yaml @@ -28,7 +28,7 @@ vars: DOCKER_IMAGE_RATHOLE: openmined/syft-rathole DOCKER_IMAGE_ENCLAVE_ATTESTATION: openmined/syft-enclave-attestation CONTAINER_REGISTRY: "docker.io" - VERSION: "0.8.8-beta.0" + VERSION: "0.8.8-beta.1" PLATFORM: $(uname -m | grep -q 'arm64' && echo "arm64" || echo "amd64") # This is a list of `images` that DevSpace can build for this project diff --git a/packages/grid/frontend/package.json b/packages/grid/frontend/package.json index cb757ffd1f4..06a5c96b4a7 100644 --- a/packages/grid/frontend/package.json +++ b/packages/grid/frontend/package.json @@ -1,6 +1,6 @@ { "name": "syft-ui", - "version": "0.8.8-beta.0", + "version": "0.8.8-beta.1", "private": true, "scripts": { "dev": "pnpm i && vite dev --host --port 80", diff --git a/packages/grid/helm/repo/index.yaml b/packages/grid/helm/repo/index.yaml index 8935c5e3425..fcedb66dbeb 100644 --- a/packages/grid/helm/repo/index.yaml +++ b/packages/grid/helm/repo/index.yaml @@ -1,9 +1,22 @@ apiVersion: v1 entries: syft: + - apiVersion: v2 + appVersion: 0.8.8-beta.1 + created: "2024-07-19T14:56:58.347810182Z" + description: Perform numpy-like analysis on data that remains in someone elses + server + digest: ec027b50b8182ef656be14ddca9537785c37712a4be8cb940f30ac029b63de2d + home: https://github.com/OpenMined/PySyft/ + icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png + name: syft + type: application + urls: + - https://openmined.github.io/PySyft/helm/syft-0.8.8-beta.1.tgz + version: 0.8.8-beta.1 - apiVersion: v2 appVersion: 0.8.7 - created: "2024-07-19T11:31:50.870912504Z" + created: "2024-07-19T14:56:58.3470709Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7ea7f63d1c6d0948860547f8aa39343fc5ef399c8e62d9d7edd4473cf44d8186 @@ -16,7 +29,7 @@ entries: version: 0.8.7 - apiVersion: v2 appVersion: 0.8.7-beta.16 - created: "2024-07-19T11:31:50.864303995Z" + created: "2024-07-19T14:56:58.340216525Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 75190eae57b64c2c47ab4a7fe3c6e94f35eb8045807a843ec8d7b26585c9e840 @@ -29,7 +42,7 @@ entries: version: 0.8.7-beta.16 - apiVersion: v2 appVersion: 0.8.7-beta.15 - created: "2024-07-19T11:31:50.86341797Z" + created: "2024-07-19T14:56:58.339374411Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 56879d9a9f10febce88676d3d20621d74d17f9e33f5df6ae1e9bc3078c216f0c @@ -42,7 +55,7 @@ entries: version: 0.8.7-beta.15 - apiVersion: v2 appVersion: 0.8.7-beta.14 - created: "2024-07-19T11:31:50.862578481Z" + created: "2024-07-19T14:56:58.338523221Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e7cbca1d603ba11e09ae2a3089cfdafaa08cfa07c553c4f0fb8b42f8d3028f7 @@ -55,7 +68,7 @@ entries: version: 0.8.7-beta.14 - apiVersion: v2 appVersion: 0.8.7-beta.13 - created: "2024-07-19T11:31:50.861706392Z" + created: "2024-07-19T14:56:58.337608702Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1dbe3ecdfec57bf25020cbcff783fab908f0eb0640ad684470b2fd1da1928005 @@ -68,7 +81,7 @@ entries: version: 0.8.7-beta.13 - apiVersion: v2 appVersion: 0.8.7-beta.12 - created: "2024-07-19T11:31:50.861001584Z" + created: "2024-07-19T14:56:58.335962013Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e92b2f3a522dabb3a79ff762a7042ae16d2bf3a53eebbb2885a69b9f834d109c @@ -81,7 +94,7 @@ entries: version: 0.8.7-beta.12 - apiVersion: v2 appVersion: 0.8.7-beta.11 - created: "2024-07-19T11:31:50.860279135Z" + created: "2024-07-19T14:56:58.335262055Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 099f6cbd44b699ee2410a4be012ed1a8a65bcacb06a43057b2779d7fe34fc0ad @@ -94,7 +107,7 @@ entries: version: 0.8.7-beta.11 - apiVersion: v2 appVersion: 0.8.7-beta.10 - created: "2024-07-19T11:31:50.85908115Z" + created: "2024-07-19T14:56:58.334556426Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 00773cb241522e281c1915339fc362e047650e08958a736e93d6539f44cb5e25 @@ -107,7 +120,7 @@ entries: version: 0.8.7-beta.10 - apiVersion: v2 appVersion: 0.8.7-beta.9 - created: "2024-07-19T11:31:50.870075941Z" + created: "2024-07-19T14:56:58.346189183Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a3f8e85d9ddef7a644b959fcc2fcb0fc08f7b6abae1045e893d0d62fa4ae132e @@ -120,7 +133,7 @@ entries: version: 0.8.7-beta.9 - apiVersion: v2 appVersion: 0.8.7-beta.8 - created: "2024-07-19T11:31:50.869419064Z" + created: "2024-07-19T14:56:58.345525713Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a422ac88d8fd1fb80d5004d5eb6e95fa9efc7f6a87da12e5ac04829da7f04c4d @@ -133,7 +146,7 @@ entries: version: 0.8.7-beta.8 - apiVersion: v2 appVersion: 0.8.7-beta.7 - created: "2024-07-19T11:31:50.86875891Z" + created: "2024-07-19T14:56:58.344835814Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0dc313a1092e6256a7c8aad002c8ec380b3add2c289d680db1e238a336399b7a @@ -146,7 +159,7 @@ entries: version: 0.8.7-beta.7 - apiVersion: v2 appVersion: 0.8.7-beta.6 - created: "2024-07-19T11:31:50.868118734Z" + created: "2024-07-19T14:56:58.343389133Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 052a2ec1102d2a4c9915f95647abd4a6012f56fa05a106f4952ee9b55bf7bae8 @@ -159,7 +172,7 @@ entries: version: 0.8.7-beta.6 - apiVersion: v2 appVersion: 0.8.7-beta.5 - created: "2024-07-19T11:31:50.867454893Z" + created: "2024-07-19T14:56:58.342754858Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1728af756907c3fcbe87c2fd2de014a2d963c22a4c2eb6af6596b525a9b9a18a @@ -172,7 +185,7 @@ entries: version: 0.8.7-beta.5 - apiVersion: v2 appVersion: 0.8.7-beta.4 - created: "2024-07-19T11:31:50.86618484Z" + created: "2024-07-19T14:56:58.342126354Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 387a57a3904a05ed61e92ee48605ef6fd5044ff7e822e0924e0d4c485e2c88d2 @@ -185,7 +198,7 @@ entries: version: 0.8.7-beta.4 - apiVersion: v2 appVersion: 0.8.7-beta.3 - created: "2024-07-19T11:31:50.865555304Z" + created: "2024-07-19T14:56:58.341496597Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 3668002b7a4118516b2ecd61d6275f60d83fc12841587ab8f62e1c1200731c67 @@ -198,7 +211,7 @@ entries: version: 0.8.7-beta.3 - apiVersion: v2 appVersion: 0.8.7-beta.2 - created: "2024-07-19T11:31:50.864903516Z" + created: "2024-07-19T14:56:58.340854798Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e62217ffcadee2b8896ab0543f9ccc42f2df898fd979438ac9376d780b802af7 @@ -211,7 +224,7 @@ entries: version: 0.8.7-beta.2 - apiVersion: v2 appVersion: 0.8.7-beta.1 - created: "2024-07-19T11:31:50.858186779Z" + created: "2024-07-19T14:56:58.333860827Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 553981fe1d5c980e6903b3ff2f1b9b97431f6dd8aee91e3976bcc5594285235e @@ -224,7 +237,7 @@ entries: version: 0.8.7-beta.1 - apiVersion: v2 appVersion: 0.8.6 - created: "2024-07-19T11:31:50.857670664Z" + created: "2024-07-19T14:56:58.333318874Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ddbbe6fea1702e57404875eb3019a3b1a341017bdbb5fbc6ce418507e5c15756 @@ -237,7 +250,7 @@ entries: version: 0.8.6 - apiVersion: v2 appVersion: 0.8.6-beta.1 - created: "2024-07-19T11:31:50.857126818Z" + created: "2024-07-19T14:56:58.332765961Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: cc2c81ef6796ac853dce256e6bf8a6af966c21803e6534ea21920af681c62e61 @@ -250,7 +263,7 @@ entries: version: 0.8.6-beta.1 - apiVersion: v2 appVersion: 0.8.5 - created: "2024-07-19T11:31:50.856579716Z" + created: "2024-07-19T14:56:58.332190095Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: db5d90d44006209fd5ecdebd88f5fd56c70f7c76898343719a0ff8da46da948a @@ -263,7 +276,7 @@ entries: version: 0.8.5 - apiVersion: v2 appVersion: 0.8.5-post.2 - created: "2024-07-19T11:31:50.855819024Z" + created: "2024-07-19T14:56:58.331422871Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ea3f7269b55f773fa165d7008c054b7cf3ec4c62eb40a96f08cd3a9b77fd2165 @@ -276,7 +289,7 @@ entries: version: 0.8.5-post.2 - apiVersion: v2 appVersion: 0.8.5-post.1 - created: "2024-07-19T11:31:50.855235143Z" + created: "2024-07-19T14:56:58.330873344Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9deb844d3dc2d8480c60f8c631dcc7794adfb39cec3aa3b1ce22ea26fdf87d02 @@ -289,7 +302,7 @@ entries: version: 0.8.5-post.1 - apiVersion: v2 appVersion: 0.8.5-beta.10 - created: "2024-07-19T11:31:50.847482922Z" + created: "2024-07-19T14:56:58.32280441Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9cfe01e8f57eca462261a24a805b41509be2de9a0fee76e331d124ed98c4bc49 @@ -302,7 +315,7 @@ entries: version: 0.8.5-beta.10 - apiVersion: v2 appVersion: 0.8.5-beta.9 - created: "2024-07-19T11:31:50.854433245Z" + created: "2024-07-19T14:56:58.330065615Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 057f1733f2bc966e15618f62629315c8207773ef6211c79c4feb557dae15c32b @@ -315,7 +328,7 @@ entries: version: 0.8.5-beta.9 - apiVersion: v2 appVersion: 0.8.5-beta.8 - created: "2024-07-19T11:31:50.853659569Z" + created: "2024-07-19T14:56:58.328428308Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 921cbce836c3032ef62b48cc82b5b4fcbe44fb81d473cf4d69a4bf0f806eb298 @@ -328,7 +341,7 @@ entries: version: 0.8.5-beta.8 - apiVersion: v2 appVersion: 0.8.5-beta.7 - created: "2024-07-19T11:31:50.852858872Z" + created: "2024-07-19T14:56:58.327665092Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 75482e955b2b9853a80bd653afb1d56535f78f3bfb7726798522307eb3effbbd @@ -341,7 +354,7 @@ entries: version: 0.8.5-beta.7 - apiVersion: v2 appVersion: 0.8.5-beta.6 - created: "2024-07-19T11:31:50.851323498Z" + created: "2024-07-19T14:56:58.326895754Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6a2dfaf65ca855e1b3d7b966d4ff291e6fcbe761e2fc2a78033211ccd3a75de0 @@ -354,7 +367,7 @@ entries: version: 0.8.5-beta.6 - apiVersion: v2 appVersion: 0.8.5-beta.5 - created: "2024-07-19T11:31:50.85053768Z" + created: "2024-07-19T14:56:58.32611216Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fead03823bef04d66901d563aa755c68ab277f72b126aaa6f0dce76a6f3bdb6d @@ -367,7 +380,7 @@ entries: version: 0.8.5-beta.5 - apiVersion: v2 appVersion: 0.8.5-beta.4 - created: "2024-07-19T11:31:50.849776748Z" + created: "2024-07-19T14:56:58.325326592Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 93e4539d5726a7fd0d6a3e93d1c17c6a358a923ddc01d102eab22f37377502ab @@ -380,7 +393,7 @@ entries: version: 0.8.5-beta.4 - apiVersion: v2 appVersion: 0.8.5-beta.3 - created: "2024-07-19T11:31:50.849016577Z" + created: "2024-07-19T14:56:58.324515387Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: f91e9390edf3441469048f5da646099af98f8b6d199409d0e2c1e6da3a51f054 @@ -393,7 +406,7 @@ entries: version: 0.8.5-beta.3 - apiVersion: v2 appVersion: 0.8.5-beta.2 - created: "2024-07-19T11:31:50.848255005Z" + created: "2024-07-19T14:56:58.323742512Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 59159c3aa4888038edc3c0135c83402363d7a0639fe62966a1e9d4928a364fa8 @@ -406,7 +419,7 @@ entries: version: 0.8.5-beta.2 - apiVersion: v2 appVersion: 0.8.5-beta.1 - created: "2024-07-19T11:31:50.846690621Z" + created: "2024-07-19T14:56:58.321207396Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 65aeb74c52ed8ba5474af500b4c1188a570ee4cb1f2a2da356b3488d28356ed9 @@ -418,7 +431,7 @@ entries: version: 0.8.5-beta.1 - apiVersion: v2 appVersion: 0.8.4 - created: "2024-07-19T11:31:50.846309569Z" + created: "2024-07-19T14:56:58.320815093Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 08afea8e3a9eef225b7e611f0bc1216c140053ef8e51439b02337faeac621fd0 @@ -430,7 +443,7 @@ entries: version: 0.8.4 - apiVersion: v2 appVersion: 0.8.4-beta.31 - created: "2024-07-19T11:31:50.843012308Z" + created: "2024-07-19T14:56:58.318335309Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: fabf3e2f37e53fa623f5d3d99b00feae06e278e5cd63bce419089946312ab1fc @@ -442,7 +455,7 @@ entries: version: 0.8.4-beta.31 - apiVersion: v2 appVersion: 0.8.4-beta.30 - created: "2024-07-19T11:31:50.842602152Z" + created: "2024-07-19T14:56:58.317920574Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6e8f792709f73ec14eab48a268bdf50a4505b340bd142cddd7c7bfffd94009ad @@ -454,7 +467,7 @@ entries: version: 0.8.4-beta.30 - apiVersion: v2 appVersion: 0.8.4-beta.29 - created: "2024-07-19T11:31:50.841841901Z" + created: "2024-07-19T14:56:58.317145135Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 4c985d6a9b3456769c4013f9e85e7374c0f963d2d27627e61f914f5537de1971 @@ -466,7 +479,7 @@ entries: version: 0.8.4-beta.29 - apiVersion: v2 appVersion: 0.8.4-beta.28 - created: "2024-07-19T11:31:50.841432055Z" + created: "2024-07-19T14:56:58.316677401Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: bd2aa3c92c768c47c502e31a326f341addcb34e64d22cdcbf5cc3f19689d859c @@ -478,7 +491,7 @@ entries: version: 0.8.4-beta.28 - apiVersion: v2 appVersion: 0.8.4-beta.27 - created: "2024-07-19T11:31:50.841019464Z" + created: "2024-07-19T14:56:58.316246256Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: e8ad0869993af39d7adda8cb868dc0b24cfb63b4bb9820dc579939c1007a60ba @@ -490,7 +503,7 @@ entries: version: 0.8.4-beta.27 - apiVersion: v2 appVersion: 0.8.4-beta.26 - created: "2024-07-19T11:31:50.840606453Z" + created: "2024-07-19T14:56:58.315611849Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 30dccf630aa25a86a03c67572fe5411687d8ce6d58def448ea10efdba2b85e3a @@ -502,7 +515,7 @@ entries: version: 0.8.4-beta.26 - apiVersion: v2 appVersion: 0.8.4-beta.25 - created: "2024-07-19T11:31:50.84018796Z" + created: "2024-07-19T14:56:58.31464389Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b6e2043bcf5a0335967d770c7939f5a7832955359a7d871c90b265660ff26e5f @@ -514,7 +527,7 @@ entries: version: 0.8.4-beta.25 - apiVersion: v2 appVersion: 0.8.4-beta.24 - created: "2024-07-19T11:31:50.839770661Z" + created: "2024-07-19T14:56:58.314227853Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b19efa95394d50bb8d76da6ec306de5d3bb9ea55371fafea95a1282a697fa33e @@ -526,7 +539,7 @@ entries: version: 0.8.4-beta.24 - apiVersion: v2 appVersion: 0.8.4-beta.23 - created: "2024-07-19T11:31:50.839319548Z" + created: "2024-07-19T14:56:58.313802949Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 5c5d05c15bff548574896118ce92335ae10c5b78f5307fe9b2618e5a5aa71a5c @@ -538,7 +551,7 @@ entries: version: 0.8.4-beta.23 - apiVersion: v2 appVersion: 0.8.4-beta.22 - created: "2024-07-19T11:31:50.838906726Z" + created: "2024-07-19T14:56:58.313369619Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0160dbce938198132ca9cd2a5cb362816344687291f5b6d7cf6de8f2855e9414 @@ -550,7 +563,7 @@ entries: version: 0.8.4-beta.22 - apiVersion: v2 appVersion: 0.8.4-beta.21 - created: "2024-07-19T11:31:50.838488465Z" + created: "2024-07-19T14:56:58.312919969Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7dce153d2fcae7513e9c132e139b2721fd975ea3cc43a370e34dbeb2a1b7f683 @@ -562,7 +575,7 @@ entries: version: 0.8.4-beta.21 - apiVersion: v2 appVersion: 0.8.4-beta.20 - created: "2024-07-19T11:31:50.838054995Z" + created: "2024-07-19T14:56:58.312464337Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c51189a187bbf24135382e25cb00964e0330dfcd3b2f0c884581a6686f05dd28 @@ -574,7 +587,7 @@ entries: version: 0.8.4-beta.20 - apiVersion: v2 appVersion: 0.8.4-beta.19 - created: "2024-07-19T11:31:50.836251023Z" + created: "2024-07-19T14:56:58.311437449Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 8219575dedb42fa2ddbf2768a4e9afbfacbc2dff7e953d77c7b10a41b78dc687 @@ -586,7 +599,7 @@ entries: version: 0.8.4-beta.19 - apiVersion: v2 appVersion: 0.8.4-beta.18 - created: "2024-07-19T11:31:50.835840196Z" + created: "2024-07-19T14:56:58.311028264Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 6418cde559cf12f1f7fea5a2b123bba950e50eeb3be002441827d2ab7f9e4ef7 @@ -598,7 +611,7 @@ entries: version: 0.8.4-beta.18 - apiVersion: v2 appVersion: 0.8.4-beta.16 - created: "2024-07-19T11:31:50.835335573Z" + created: "2024-07-19T14:56:58.310617857Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 9c9840a7c9476dbb08e0ac83926330718fe50c89879752dd8f92712b036109c0 @@ -610,7 +623,7 @@ entries: version: 0.8.4-beta.16 - apiVersion: v2 appVersion: 0.8.4-beta.15 - created: "2024-07-19T11:31:50.834903756Z" + created: "2024-07-19T14:56:58.310207801Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0955fd22da028315e30c68132cbfa4bdc82bae622039bcfce0de339707bb82eb @@ -622,7 +635,7 @@ entries: version: 0.8.4-beta.15 - apiVersion: v2 appVersion: 0.8.4-beta.14 - created: "2024-07-19T11:31:50.834498058Z" + created: "2024-07-19T14:56:58.309788287Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 56208571956abe20ed7a5cc1867cab2667ed792c63e53d0e8bb70a9b438b7bf6 @@ -634,7 +647,7 @@ entries: version: 0.8.4-beta.14 - apiVersion: v2 appVersion: 0.8.4-beta.13 - created: "2024-07-19T11:31:50.834147453Z" + created: "2024-07-19T14:56:58.309401124Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: d7222c72412b6ee5833fbb07d2549be179cdfc7ccd89e0ad947d112fce799b83 @@ -646,7 +659,7 @@ entries: version: 0.8.4-beta.13 - apiVersion: v2 appVersion: 0.8.4-beta.12 - created: "2024-07-19T11:31:50.833794303Z" + created: "2024-07-19T14:56:58.30884261Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: af08c723756e397962b2d5190dedfd50797b771c5caf58b93a6f65d8fa24785c @@ -658,7 +671,7 @@ entries: version: 0.8.4-beta.12 - apiVersion: v2 appVersion: 0.8.4-beta.11 - created: "2024-07-19T11:31:50.833442736Z" + created: "2024-07-19T14:56:58.307847643Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: a0235835ba57d185a83dd8a26281fa37b2077c3a37fe3a1c50585005695927e3 @@ -670,7 +683,7 @@ entries: version: 0.8.4-beta.11 - apiVersion: v2 appVersion: 0.8.4-beta.10 - created: "2024-07-19T11:31:50.833093503Z" + created: "2024-07-19T14:56:58.307492028Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 910ddfeba0c5e66651500dd11404afff092adc0f768ed68e0d93b04b83aa4388 @@ -682,7 +695,7 @@ entries: version: 0.8.4-beta.10 - apiVersion: v2 appVersion: 0.8.4-beta.9 - created: "2024-07-19T11:31:50.845890837Z" + created: "2024-07-19T14:56:58.320372255Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: c25ca8a9f072d6a5d02232448deaef5668aca05f24dfffbba3ebe30a4f75bb26 @@ -694,7 +707,7 @@ entries: version: 0.8.4-beta.9 - apiVersion: v2 appVersion: 0.8.4-beta.8 - created: "2024-07-19T11:31:50.845544449Z" + created: "2024-07-19T14:56:58.320034174Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 7249a39d4137e457b369384ba0a365c271c780d93a8327ce25083df763c39999 @@ -706,7 +719,7 @@ entries: version: 0.8.4-beta.8 - apiVersion: v2 appVersion: 0.8.4-beta.7 - created: "2024-07-19T11:31:50.845192041Z" + created: "2024-07-19T14:56:58.319694469Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: ee750c7c8d6ea05bd447375e624fdd7f66dd87680ab81f7b7e73df7379a9024a @@ -718,7 +731,7 @@ entries: version: 0.8.4-beta.7 - apiVersion: v2 appVersion: 0.8.4-beta.6 - created: "2024-07-19T11:31:50.844820808Z" + created: "2024-07-19T14:56:58.319357309Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 0e046be9f73df7444a995608c59af16fab9030b139b2acb4d6db6185b8eb5337 @@ -730,7 +743,7 @@ entries: version: 0.8.4-beta.6 - apiVersion: v2 appVersion: 0.8.4-beta.5 - created: "2024-07-19T11:31:50.844183016Z" + created: "2024-07-19T14:56:58.319019878Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b56e9a23d46810eccdb4cf5272cc05126da3f6db314e541959c3efb5f260620b @@ -742,7 +755,7 @@ entries: version: 0.8.4-beta.5 - apiVersion: v2 appVersion: 0.8.4-beta.4 - created: "2024-07-19T11:31:50.843366771Z" + created: "2024-07-19T14:56:58.318679462Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: 1d5808ecaf55391f3b27ae6236400066508acbd242e33db24a1ab4bffa77409e @@ -754,7 +767,7 @@ entries: version: 0.8.4-beta.4 - apiVersion: v2 appVersion: 0.8.4-beta.3 - created: "2024-07-19T11:31:50.842190062Z" + created: "2024-07-19T14:56:58.317502693Z" description: Perform numpy-like analysis on data that remains in someone elses server digest: b64efa8529d82be56c6ab60487ed24420a5614d96d2509c1f93c1003eda71a54 @@ -766,7 +779,7 @@ entries: version: 0.8.4-beta.3 - apiVersion: v2 appVersion: 0.8.4-beta.2 - created: "2024-07-19T11:31:50.837597029Z" + created: "2024-07-19T14:56:58.312032441Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -782,7 +795,7 @@ entries: version: 0.8.4-beta.2 - apiVersion: v2 appVersion: 0.8.4-beta.1 - created: "2024-07-19T11:31:50.832739211Z" + created: "2024-07-19T14:56:58.307135381Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -798,7 +811,7 @@ entries: version: 0.8.4-beta.1 - apiVersion: v2 appVersion: 0.8.3 - created: "2024-07-19T11:31:50.832188242Z" + created: "2024-07-19T14:56:58.306577399Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -814,7 +827,7 @@ entries: version: 0.8.3 - apiVersion: v2 appVersion: 0.8.3-beta.6 - created: "2024-07-19T11:31:50.83151842Z" + created: "2024-07-19T14:56:58.305874355Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -830,7 +843,7 @@ entries: version: 0.8.3-beta.6 - apiVersion: v2 appVersion: 0.8.3-beta.5 - created: "2024-07-19T11:31:50.830892461Z" + created: "2024-07-19T14:56:58.305291015Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -846,7 +859,7 @@ entries: version: 0.8.3-beta.5 - apiVersion: v2 appVersion: 0.8.3-beta.4 - created: "2024-07-19T11:31:50.830265389Z" + created: "2024-07-19T14:56:58.304655327Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -862,7 +875,7 @@ entries: version: 0.8.3-beta.4 - apiVersion: v2 appVersion: 0.8.3-beta.2 - created: "2024-07-19T11:31:50.828791015Z" + created: "2024-07-19T14:56:58.303980717Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -878,7 +891,7 @@ entries: version: 0.8.3-beta.2 - apiVersion: v2 appVersion: 0.8.3-beta.1 - created: "2024-07-19T11:31:50.828238753Z" + created: "2024-07-19T14:56:58.303412455Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -894,7 +907,7 @@ entries: version: 0.8.3-beta.1 - apiVersion: v2 appVersion: 0.8.2 - created: "2024-07-19T11:31:50.827683125Z" + created: "2024-07-19T14:56:58.30279948Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -910,7 +923,7 @@ entries: version: 0.8.2 - apiVersion: v2 appVersion: 0.8.2-beta.60 - created: "2024-07-19T11:31:50.827006892Z" + created: "2024-07-19T14:56:58.301649389Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -926,7 +939,7 @@ entries: version: 0.8.2-beta.60 - apiVersion: v2 appVersion: 0.8.2-beta.59 - created: "2024-07-19T11:31:50.826367747Z" + created: "2024-07-19T14:56:58.300629353Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -942,7 +955,7 @@ entries: version: 0.8.2-beta.59 - apiVersion: v2 appVersion: 0.8.2-beta.58 - created: "2024-07-19T11:31:50.825726789Z" + created: "2024-07-19T14:56:58.29998532Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -958,7 +971,7 @@ entries: version: 0.8.2-beta.58 - apiVersion: v2 appVersion: 0.8.2-beta.57 - created: "2024-07-19T11:31:50.825076865Z" + created: "2024-07-19T14:56:58.299342107Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -974,7 +987,7 @@ entries: version: 0.8.2-beta.57 - apiVersion: v2 appVersion: 0.8.2-beta.56 - created: "2024-07-19T11:31:50.824390102Z" + created: "2024-07-19T14:56:58.298687655Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -990,7 +1003,7 @@ entries: version: 0.8.2-beta.56 - apiVersion: v2 appVersion: 0.8.2-beta.52 - created: "2024-07-19T11:31:50.823388048Z" + created: "2024-07-19T14:56:58.29803773Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1006,7 +1019,7 @@ entries: version: 0.8.2-beta.52 - apiVersion: v2 appVersion: 0.8.2-beta.51 - created: "2024-07-19T11:31:50.82224956Z" + created: "2024-07-19T14:56:58.297386273Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1022,7 +1035,7 @@ entries: version: 0.8.2-beta.51 - apiVersion: v2 appVersion: 0.8.2-beta.50 - created: "2024-07-19T11:31:50.821603203Z" + created: "2024-07-19T14:56:58.296691274Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1038,7 +1051,7 @@ entries: version: 0.8.2-beta.50 - apiVersion: v2 appVersion: 0.8.2-beta.49 - created: "2024-07-19T11:31:50.820953538Z" + created: "2024-07-19T14:56:58.296017024Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1054,7 +1067,7 @@ entries: version: 0.8.2-beta.49 - apiVersion: v2 appVersion: 0.8.2-beta.48 - created: "2024-07-19T11:31:50.820299005Z" + created: "2024-07-19T14:56:58.294571215Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1070,7 +1083,7 @@ entries: version: 0.8.2-beta.48 - apiVersion: v2 appVersion: 0.8.2-beta.47 - created: "2024-07-19T11:31:50.819452133Z" + created: "2024-07-19T14:56:58.29392136Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1086,7 +1099,7 @@ entries: version: 0.8.2-beta.47 - apiVersion: v2 appVersion: 0.8.2-beta.46 - created: "2024-07-19T11:31:50.818869394Z" + created: "2024-07-19T14:56:58.293360222Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1102,7 +1115,7 @@ entries: version: 0.8.2-beta.46 - apiVersion: v2 appVersion: 0.8.2-beta.45 - created: "2024-07-19T11:31:50.818312904Z" + created: "2024-07-19T14:56:58.29272757Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1118,7 +1131,7 @@ entries: version: 0.8.2-beta.45 - apiVersion: v2 appVersion: 0.8.2-beta.44 - created: "2024-07-19T11:31:50.817734012Z" + created: "2024-07-19T14:56:58.292167753Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1134,7 +1147,7 @@ entries: version: 0.8.2-beta.44 - apiVersion: v2 appVersion: 0.8.2-beta.43 - created: "2024-07-19T11:31:50.816780482Z" + created: "2024-07-19T14:56:58.29156656Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1150,7 +1163,7 @@ entries: version: 0.8.2-beta.43 - apiVersion: v2 appVersion: 0.8.2-beta.41 - created: "2024-07-19T11:31:50.815718578Z" + created: "2024-07-19T14:56:58.290892741Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1166,7 +1179,7 @@ entries: version: 0.8.2-beta.41 - apiVersion: v2 appVersion: 0.8.2-beta.40 - created: "2024-07-19T11:31:50.815028208Z" + created: "2024-07-19T14:56:58.290205707Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1182,7 +1195,7 @@ entries: version: 0.8.2-beta.40 - apiVersion: v2 appVersion: 0.8.2-beta.39 - created: "2024-07-19T11:31:50.814473792Z" + created: "2024-07-19T14:56:58.289588094Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1198,7 +1211,7 @@ entries: version: 0.8.2-beta.39 - apiVersion: v2 appVersion: 0.8.2-beta.38 - created: "2024-07-19T11:31:50.81391087Z" + created: "2024-07-19T14:56:58.288217332Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1214,7 +1227,7 @@ entries: version: 0.8.2-beta.38 - apiVersion: v2 appVersion: 0.8.2-beta.37 - created: "2024-07-19T11:31:50.813330866Z" + created: "2024-07-19T14:56:58.28764328Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1230,7 +1243,7 @@ entries: version: 0.8.2-beta.37 - apiVersion: v2 appVersion: 0.8.1 - created: "2024-07-19T11:31:50.812722189Z" + created: "2024-07-19T14:56:58.287047436Z" dependencies: - name: component-chart repository: https://charts.devspace.sh @@ -1244,4 +1257,4 @@ entries: urls: - https://openmined.github.io/PySyft/helm/syft-0.8.1.tgz version: 0.8.1 -generated: "2024-07-19T11:31:50.81199537Z" +generated: "2024-07-19T14:56:58.286141493Z" diff --git a/packages/grid/helm/repo/syft-0.8.8-beta.1.tgz b/packages/grid/helm/repo/syft-0.8.8-beta.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..a26811b1d1030e0ff9ec277618353ffd8a37242a GIT binary patch literal 9977 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 Di!j@A literal 0 HcmV?d00001 diff --git a/packages/grid/helm/syft/Chart.yaml b/packages/grid/helm/syft/Chart.yaml index 9d356f6a0c3..4b8824050fa 100644 --- a/packages/grid/helm/syft/Chart.yaml +++ b/packages/grid/helm/syft/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: syft description: Perform numpy-like analysis on data that remains in someone elses server type: application -version: "0.8.8-beta.0" -appVersion: "0.8.8-beta.0" +version: "0.8.8-beta.1" +appVersion: "0.8.8-beta.1" home: https://github.com/OpenMined/PySyft/ icon: https://raw.githubusercontent.com/OpenMined/PySyft/dev/docs/img/title_syft_light.png diff --git a/packages/grid/helm/syft/templates/NOTES.txt b/packages/grid/helm/syft/templates/NOTES.txt index 679523d63fb..c22083b41e8 100644 --- a/packages/grid/helm/syft/templates/NOTES.txt +++ b/packages/grid/helm/syft/templates/NOTES.txt @@ -9,1058 +9,7 @@ Following class versions are either added/removed. - { - "BaseDateTime": { - "1": { - "version": 1, - "hash": "614db484b1950be729902b1861bd3a7b33899176507c61cef11dc0d44611cfd3", - "action": "add" - } - }, - "PartialSyftObject": { - "1": { - "version": 1, - "hash": "19a995fcc2833f4fab24584fd99b71a80c2ef1f13c06f83af79e4482846b1656", - "action": "add" - } - }, - "ServerMetadata": { - "1": { - "version": 1, - "hash": "1691c7667eca86b20c4189e90ce4e643dd41fd3682cdb69c6308878f2a6f135c", - "action": "add" - } - }, - "StoreConfig": { - "1": { - "version": 1, - "hash": "a9997fce6a8a0ed2884c58b8eb9382f8554bdd18fff61f8bf0451945bcff12c7", - "action": "add" - } - }, - "MongoDict": { - "1": { - "version": 1, - "hash": "57e36f57eed75e62b29e2bac1295035a9bf2c0e3c56719dac24cb6cc685be00b", - "action": "add" - } - }, - "MongoStoreConfig": { - "1": { - "version": 1, - "hash": "53342b27d34165b7e2699f8e7ad70d13d125875e6a75e8fa18f5796428f41036", - "action": "add" - } - }, - "LinkedObject": { - "1": { - "version": 1, - "hash": "d80f5ac7f51a9383be1a3cb334d56ae50e49733ed3199f3b6b5d6febd9de410b", - "action": "add" - } - }, - "BaseConfig": { - "1": { - "version": 1, - "hash": "10bd7566041d0f0a3aa295367785fdcc2c5bbf0ded984ac9230754f37496a6a7", - "action": "add" - } - }, - "ServiceConfig": { - "1": { - "version": 1, - "hash": "28af8a296f5ff63de50438277eaa1f4380682e6aca9f2ca28320d7a444825e88", - "action": "add" - } - }, - "LibConfig": { - "1": { - "version": 1, - "hash": "ee8f0e3f6aae81948d72e30226645e8eb5d312a6770411a1edca748168c467c0", - "action": "add" - } - }, - "APIEndpoint": { - "1": { - "version": 1, - "hash": "cfa6f314481a5bf3c448c33bf2312a9c33cbcf03cdc96864ad9a108f62b09346", - "action": "add" - } - }, - "LibEndpoint": { - "1": { - "version": 1, - "hash": "a585c83a33a019d363ae5a0c6d4197193654307c19a4829dfbf8a8cfd2c1842a", - "action": "add" - } - }, - "SignedSyftAPICall": { - "1": { - "version": 1, - "hash": "2f959455f7130f4e59360b8aa58f19785b76eaa0f8a5a9188a6cbf32b31311ca", - "action": "add" - } - }, - "SyftAPICall": { - "1": { - "version": 1, - "hash": "59e89e7b9ea30deaed64d1ffd9bc0769b999d3082b305428432c1f5be36c6343", - "action": "add" - } - }, - "SyftAPIData": { - "1": { - "version": 1, - "hash": "820b279c581cafd9bb5009702d4e3db22ec3a3156676426304b9038dad260a24", - "action": "add" - } - }, - "SyftAPI": { - "1": { - "version": 1, - "hash": "cc13ab058ee36748c14b0d4bd9b9e894c7566fff09cfa4170b3eece520169f15", - "action": "add" - } - }, - "User": { - "1": { - "version": 1, - "hash": "2df4b68182c558dba5485a8a6867acf2a5c341b249ad67373a504098aa8c4343", - "action": "add" - } - }, - "UserUpdate": { - "1": { - "version": 1, - "hash": "1bf6707c69b809c804fb939c7c37d787c2f6889508a4bec37d24221af2eb777a", - "action": "add" - } - }, - "UserCreate": { - "1": { - "version": 1, - "hash": "49d6087e2309ba59987f3126e286e74b3a66492a08ad82fa507ea17d52ce78e3", - "action": "add" - } - }, - "UserSearch": { - "1": { - "version": 1, - "hash": "9ac946338cca68d00d1696a57943442f062628ec3daf53077d0bdd3f72cd9fa0", - "action": "add" - } - }, - "UserView": { - "1": { - "version": 1, - "hash": "0b52d758e31d5889c9cd88afb467aae4a74e34a5276924e07012243c34d300fe", - "action": "add" - } - }, - "UserViewPage": { - "1": { - "version": 1, - "hash": "1cd6528d02ec180f080d5c35f0da760d8a59af9da7baaa9c17c1c7cedcc858fa", - "action": "add" - } - }, - "UserPrivateKey": { - "1": { - "version": 1, - "hash": "4817d8147aba94373f320dcd90e65f097cf6e5a2ef353aa8520e23128d522b5d", - "action": "add" - } - }, - "DateTime": { - "1": { - "version": 1, - "hash": "394abb554114ead4d63c36e3fe83ac018dead4b21a8465174009577c46d54c58", - "action": "add" - } - }, - "ReplyNotification": { - "1": { - "version": 1, - "hash": "84102dfc59d711b03c2f3d3a6ecaca000b6835f1bbdd9af801057f7aacb5f1d0", - "action": "add" - } - }, - "Notification": { - "1": { - "version": 1, - "hash": "af4cb232bff390c431e399975f048b34da7e940ace8b23b940a3b398c91c5326", - "action": "add" - } - }, - "CreateNotification": { - "1": { - "version": 1, - "hash": "7e426c946b7d5db6f9427960ec16042f3018091d835ca5966f3568c324a2ab53", - "action": "add" - } - }, - "NotificationPreferences": { - "1": { - "version": 1, - "hash": "a42f06b367e7c6cbabcbf3cfcc84d1ca0873e457d972ebd060e87c9d6185f62b", - "action": "add" - } - }, - "NotifierSettings": { - "1": { - "version": 1, - "hash": "65c8ab814d35fac32f68d3000756692592cc59940f30e3af3dcdfa2328755b9d", - "action": "add" - } - }, - "SyftImageRegistry": { - "1": { - "version": 1, - "hash": "67e18903e41cba1afe136adf29d404b63ec04fea6e928abb2533ec4fa52b246b", - "action": "add" - } - }, - "SyftWorkerImage": { - "1": { - "version": 1, - "hash": "44da7badfbe573d5403d3ab78c077f17dbefc560b81fdf927b671815be047441", - "action": "add" - } - }, - "SyftWorker": { - "1": { - "version": 1, - "hash": "9d897f6039eabe48dfa8e8d5c5cdcb283b0375b4c64571b457777eaaf3fb1920", - "action": "add" - } - }, - "WorkerPool": { - "1": { - "version": 1, - "hash": "16efc5dd2596ae744fd611c8f46af9eaec1bd5729eb20e85e9fd2f31df402564", - "action": "add" - } - }, - "MarkdownDescription": { - "1": { - "version": 1, - "hash": "31a73f8824cad1636a55d14b6a1074cdb071d0d4e16e86baaa3d4f63a7e80134", - "action": "add" - } - }, - "HTMLObject": { - "1": { - "version": 1, - "hash": "97f2e93f5ceaa88015047186f66a17ff13df2a6b7925b41331f9e19d5a515a9f", - "action": "add" - } - }, - "ServerSettingsUpdate": { - "1": { - "version": 1, - "hash": "1e4260ad879ae80728c3ffae2cd1d48759abd51f9d0960d4b25855cdbb4c506b", - "action": "add" - } - }, - "ServerSettings": { - "1": { - "version": 1, - "hash": "5a1e7470cbeaaae5b80ac9beecb743734f7e4e42d429a09ea8defa569a5ddff1", - "action": "add" - } - }, - "HTTPConnection": { - "1": { - "version": 1, - "hash": "bf10f81646c71069c76292b1237b4a3de1e507264392c5c591d067636ce6fb46", - "action": "add" - } - }, - "PythonConnection": { - "1": { - "version": 1, - "hash": "28010778b5e3463ff6960a0e2224818de00bc7b5e6f892192e02e399ccbe18b5", - "action": "add" - } - }, - "ActionDataEmpty": { - "1": { - "version": 1, - "hash": "e0e4a5cf18d05b6b747addc048515c6f2a5f35f0766ebaee96d898cb971e1c5b", - "action": "add" - } - }, - "ObjectNotReady": { - "1": { - "version": 1, - "hash": "8cf471e205cd0893d6aae5f0227d14db7df1c9698da08a3ab991f59132d17fe9", - "action": "add" - } - }, - "ActionDataLink": { - "1": { - "version": 1, - "hash": "3469478343439e411b761c270eec63eb3d533e459ad72d0965158c3a6cdf3b9a", - "action": "add" - } - }, - "Action": { - "1": { - "version": 1, - "hash": "021826d7c6f69bd0283d025d40661f3ffbeba8810ca94de01344f6afbdae62cd", - "action": "add" - } - }, - "ActionObject": { - "1": { - "version": 1, - "hash": "0a5f4bc343cb114a251f06686ecdbb59d74bfb3d29a098b176699deb35a1e683", - "action": "add" - } - }, - "AnyActionObject": { - "1": { - "version": 1, - "hash": "b3c44c7788c59c03fa1baeec656c2ca6e633f4cbd4b23ff7ece6ee94c38449f0", - "action": "add" - } - }, - "CustomEndpointActionObject": { - "1": { - "version": 1, - "hash": "c7addbaf2777707f3e91e5c1e092343476cd22efc4ec8617f39ccf76e61a5a14", - "action": "add" - } - }, - "DataSubject": { - "1": { - "version": 1, - "hash": "582cdf9e82b5d6915b7f09f7c0d5f08328b11a2ce9b0198e5083f1672c2e2bf5", - "action": "add" - } - }, - "DataSubjectCreate": { - "1": { - "version": 1, - "hash": "5a8423c2690d55f425bfeecc87cd4a797a75d88ebb5fbda754d4f269b62d2ceb", - "action": "add" - } - }, - "DataSubjectMemberRelationship": { - "1": { - "version": 1, - "hash": "0810483ea76ea10c8f286c6035dc0b2085291f345183be50c179f3a05a577110", - "action": "add" - } - }, - "Contributor": { - "1": { - "version": 1, - "hash": "30c32bd44098f00e0b15496be441763b6e50af8b12d3d2bef33aca6287193876", - "action": "add" - } - }, - "Asset": { - "1": { - "version": 1, - "hash": "000abc78719611c106295cf12b1690b7e5411dc1bb9db9d4afd22956da90d1f4", - "action": "add" - } - }, - "CreateAsset": { - "1": { - "version": 1, - "hash": "357d52576cb12b24fb3980342bb49a562b065c0e4419e87d34176340628c7309", - "action": "add" - } - }, - "Dataset": { - "1": { - "version": 1, - "hash": "0ca6b0b4a3aebb2c8f351668075b44951bb20d1e23a779b82109124f334ce3a4", - "action": "add" - } - }, - "DatasetPageView": { - "1": { - "version": 1, - "hash": "aa0dd69637281b80d5523b4409a2c7e89db114c9fe79c858063c6dadff8977d1", - "action": "add" - } - }, - "CreateDataset": { - "1": { - "version": 1, - "hash": "7e02dfa89540c3dbebacbb13810d95cdc4e36db31d56cffed7ab54abe25716c9", - "action": "add" - } - }, - "SyftLog": { - "1": { - "version": 1, - "hash": "1bcd71e5bf3f0db3bba0996f33b6b2bde3489b9c71f11e6b30c3495c76a8f53f", - "action": "add" - } - }, - "JobItem": { - "1": { - "version": 1, - "hash": "0b32277b7d3b9bdc14a2a51cc9005f8254e7f7b6ec059ddcccbcd681a807afb6", - "action": "add" - } - }, - "ExecutionOutput": { - "1": { - "version": 1, - "hash": "e36c71685edf5276a3427cb6749550486d3a177c1dcf73dd337ab2a73c0ce6b5", - "action": "add" - } - }, - "TwinObject": { - "1": { - "version": 1, - "hash": "4f31243fb348dbb083579afd6f638d75af010cb53d19bfba59b74afff41ccbbb", - "action": "add" - } - }, - "PolicyRule": { - "1": { - "version": 1, - "hash": "44d1ca1db97be46f66558aa1a729ff31bf8e113c6a913b11aedf9d6b6ad5b7b5", - "action": "add" - } - }, - "CreatePolicyRule": { - "1": { - "version": 1, - "hash": "342bb723526d445151a0435f57d251f4c1219f8ae7cca3e8e9fce52e2ee1b8b1", - "action": "add" - } - }, - "CreatePolicyRuleConstant": { - "1": { - "version": 1, - "hash": "78b54832cb0468a87013bc36bc11d4759874ca1b5065a1b711f1e5ef5d94c2df", - "action": "add" - } - }, - "Matches": { - "1": { - "version": 1, - "hash": "dd6d91ddb2ec5eaf60be2b0899ecfdb9a15f7904aa39d2f4d9bb2d7b793040e6", - "action": "add" - } - }, - "PreFill": { - "1": { - "version": 1, - "hash": "c7aefb11dc4c4569dcd1e6988371047a32a8be1b32ad46d12adba419a19769ad", - "action": "add" - } - }, - "UserOwned": { - "1": { - "version": 1, - "hash": "c8738dc3d8c2a5ef461b85a0467c3dff53dab16b54a4d12b44b1477906aef51d", - "action": "add" - } - }, - "MixedInputPolicy": { - "1": { - "version": 1, - "hash": "37bb12d950518d9579c8ec7c4cc22ac731ea82caf8c1370dd0b0a82b46462dde", - "action": "add" - } - }, - "ExactMatch": { - "1": { - "version": 1, - "hash": "5eb37edbf5e451d942e599247f3eaed923c1fe9d91eefdba02bf06503f6cc08d", - "action": "add" - } - }, - "OutputHistory": { - "1": { - "version": 1, - "hash": "9366db79d131f8c65e5a4ff12c90e2aa0c11e302debe06e46eeb93b26e2aaf61", - "action": "add" - } - }, - "OutputPolicyExecuteCount": { - "1": { - "version": 1, - "hash": "2a77e5ed5c7b0391147562651ad4061e20b11745c191fbc34cb549da37ba72dd", - "action": "add" - } - }, - "OutputPolicyExecuteOnce": { - "1": { - "version": 1, - "hash": "5589c00d127d9eb1f5ccf3a16def8219737784d57bb3bf9be5cb6d83325ef436", - "action": "add" - } - }, - "EmptyInputPolicy": { - "1": { - "version": 1, - "hash": "7ef81cfd223be0064600e1503f8b04bafc16385e27730e9319466e68a077c68b", - "action": "add" - } - }, - "UserPolicy": { - "1": { - "version": 1, - "hash": "74373bb71a334f4dcf77623ae10ff5b1c7e5b3006f65f2051ffb1e01f422f982", - "action": "add" - } - }, - "SubmitUserPolicy": { - "1": { - "version": 1, - "hash": "ec4e808eb39613bcdbbbf9ffb3267612084a9d99880a2f3bee3ef32d46329c02", - "action": "add" - } - }, - "UserCodeStatusCollection": { - "1": { - "version": 1, - "hash": "735ecf2d4abb1e7d19b2e751d880f32b01ce267ba10e417ef1b440be3d94d8f1", - "action": "add" - } - }, - "UserCode": { - "1": { - "version": 1, - "hash": "3bcd14413b9c4fbde7c5612c2ed713518340280b5cff89cf2aaaf1c77c4037a8", - "action": "add" - } - }, - "SubmitUserCode": { - "1": { - "version": 1, - "hash": "d2bb8cfe12f070b4adafded78ce01900c5409bd83f055f94b1e285745ef65a76", - "action": "add" - } - }, - "UserCodeExecutionResult": { - "1": { - "version": 1, - "hash": "1f4cbc62caac4dd193f427306405dc7a099ae744bea5830cf57149ce71c1e589", - "action": "add" - } - }, - "UserCodeExecutionOutput": { - "1": { - "version": 1, - "hash": "c1d53300a39dbbb437d7d5a1257bd175a067b1065f4099a0938fac7540035258", - "action": "add" - } - }, - "CodeHistory": { - "1": { - "version": 1, - "hash": "e3ef5346f108257828f364d22b12d9311812c9cf843200afef5dc4d9302f9b21", - "action": "add" - } - }, - "CodeHistoryView": { - "1": { - "version": 1, - "hash": "8b8b97d334b51d1ce0a9efab722411ff25caa3f12be319105954497e0a306eb2", - "action": "add" - } - }, - "CodeHistoriesDict": { - "1": { - "version": 1, - "hash": "01d7dcd4b21525a06e4484d8699a4a34a5c84f1f6026ec55e32eb30412742601", - "action": "add" - } - }, - "UsersCodeHistoriesDict": { - "1": { - "version": 1, - "hash": "4ed8b83973258ea19a1f91feb2590ff73b801be86f4296cc3db48f6929ff784c", - "action": "add" - } - }, - "BlobFile": { - "1": { - "version": 1, - "hash": "d99239100f1cb0b73c69b2ad7cab01a06909cc3a4976ba2b3b67cf6fe5e2f516", - "action": "add" - } - }, - "BlobFileOBject": { - "1": { - "version": 1, - "hash": "6c40dab2c8d2220d4fff7cc653d76cc026a856db7e2b5713b6341e255adc7ea2", - "action": "add" - } - }, - "SecureFilePathLocation": { - "1": { - "version": 1, - "hash": "ea5978b98d7773d221665b450454c9130c103a5c850669a0acd620607cd614b7", - "action": "add" - } - }, - "SeaweedSecureFilePathLocation": { - "1": { - "version": 1, - "hash": "3fc9bfc8c1b1cf660c9747e8c1fe3eb2220e78d4e3b5d6b5c5f29a07a77ebf3e", - "action": "add" - } - }, - "AzureSecureFilePathLocation": { - "1": { - "version": 1, - "hash": "090a9e962eeb655586ee966c5651d8996363969818a38f9a486fd64d33047e05", - "action": "add" - } - }, - "BlobStorageEntry": { - "1": { - "version": 1, - "hash": "afdc6a1d8a24b1ee1ed9d3e79f5bac64b4f0d9d36800f07f10be0b896470345f", - "action": "add" - } - }, - "BlobStorageMetadata": { - "1": { - "version": 1, - "hash": "9d4b61ac4ea1910c2f7c767a50a6a52544a24663548f069e79bd906f11b538e4", - "action": "add" - } - }, - "CreateBlobStorageEntry": { - "1": { - "version": 1, - "hash": "ffc3cbfeade67d074dc5bf7d655a1eb8c83630076028a72b3cc4548f3b413e14", - "action": "add" - } - }, - "SyftObjectMigrationState": { - "1": { - "version": 1, - "hash": "ee83315828551f18904bab18e0cac48896493620561215b04cc448e6ce5834af", - "action": "add" - } - }, - "StoreMetadata": { - "1": { - "version": 1, - "hash": "8de9a22a2765ef976bc161cb0704347d30350c085da8c8ffa876065cfca3e5fd", - "action": "add" - } - }, - "MigrationData": { - "1": { - "version": 1, - "hash": "cb96b8c8413609e1224341d1b0dd1efb08387c0ff7b0ff65eba36c0b104c9ed1", - "action": "add" - } - }, - "BlobRetrieval": { - "1": { - "version": 1, - "hash": "c422c74b89a9349742acaa848566fe18bfef1a83333458b858c074baed37a859", - "action": "add" - } - }, - "SyftObjectRetrieval": { - "1": { - "version": 1, - "hash": "b2b62447445adc4cd0b77ab59d6fa56624dd316fb50281e570daad07556b6db2", - "action": "add" - } - }, - "BlobRetrievalByURL": { - "1": { - "version": 1, - "hash": "4db0e3b7a6334d3835356d8393866711e243e360af25a95f3cc4066f032404b5", - "action": "add" - } - }, - "BlobDeposit": { - "1": { - "version": 1, - "hash": "6eb5cc57dc763126bfc6ec5a2b79d02e77eadf9d9efb1888a5c366b7799c1c24", - "action": "add" - } - }, - "OnDiskBlobDeposit": { - "1": { - "version": 1, - "hash": "817bf1bee4a35bfa1cd25d6779a10d8d180b1b3f1e837952f81f48b9411d1970", - "action": "add" - } - }, - "RemoteConfig": { - "1": { - "version": 1, - "hash": "179d067099a178d748c6d9a0477e8de7c3b55577439669eca7150258f2409567", - "action": "add" - } - }, - "AzureRemoteConfig": { - "1": { - "version": 1, - "hash": "a143811fec0da5fd881e927643ef667c91c78a2c90519cf88da7da20738bd187", - "action": "add" - } - }, - "SeaweedFSBlobDeposit": { - "1": { - "version": 1, - "hash": "febeb2a2ce81aa2c512e4c6b611b582984042aafa0541403d4584662273a166c", - "action": "add" - } - }, - "DictStoreConfig": { - "1": { - "version": 1, - "hash": "2e1365c5535fa51c22eef79f67dd6444789bc829c27881367e3050e06e2ffbfe", - "action": "add" - } - }, - "NumpyArrayObject": { - "1": { - "version": 1, - "hash": "05dd2917b7692b3daf4e7ad083a46fa7ec7a2be8faac8d4a654809189c986443", - "action": "add" - } - }, - "NumpyScalarObject": { - "1": { - "version": 1, - "hash": "8753e5c78270a5cacbf0439447724772f4765351a4a8b58b0a5c416a6b2c8b6e", - "action": "add" - } - }, - "NumpyBoolObject": { - "1": { - "version": 1, - "hash": "331c44f8fa3d0a077f1aaad7313bae2c43b386d04def7b8bedae9fdf7690134d", - "action": "add" - } - }, - "PandasDataframeObject": { - "1": { - "version": 1, - "hash": "5e8018364cea31d5f185a901da4ab89846b02153ee7d041ee8a6d305ece31f90", - "action": "add" - } - }, - "PandasSeriesObject": { - "1": { - "version": 1, - "hash": "b8bd482bf16fc7177e9778292cd42f8835b6ced2ce8dc88908b4b8e6d7c7528f", - "action": "add" - } - }, - "Change": { - "1": { - "version": 1, - "hash": "75fb9a5cd4e76b189ebe130a421d3921a0c251947a48bbb92a2ef1c315dc3c16", - "action": "add" - } - }, - "ChangeStatus": { - "1": { - "version": 1, - "hash": "c914a6f7637b555a51b71e8e197e591f7a2e28121e29b5dd586f87e0383d179d", - "action": "add" - } - }, - "ActionStoreChange": { - "1": { - "version": 1, - "hash": "1a803bb08924b49f3114fd46e0e132f819d4d56be5e03a27e9fe90947ca26e85", - "action": "add" - } - }, - "CreateCustomImageChange": { - "1": { - "version": 1, - "hash": "c3dbea3f49979fdcc517c0d13cd02739ca2fe86b370c42496a224f142ae31562", - "action": "add" - } - }, - "CreateCustomWorkerPoolChange": { - "1": { - "version": 1, - "hash": "0355793dd58b364dcb84fff29714b6a26446bead3ba95c6d75e3200008e580f4", - "action": "add" - } - }, - "Request": { - "1": { - "version": 1, - "hash": "1d69f5f0074114f99aa29c5ee77cb20b9151e5b50e77b026f11c3632a12efadf", - "action": "add" - } - }, - "RequestInfo": { - "1": { - "version": 1, - "hash": "779562547744ebed64548f8021647292604fdf4256bf79685dfa14a1e56cc27b", - "action": "add" - } - }, - "RequestInfoFilter": { - "1": { - "version": 1, - "hash": "bb881a003032f4676321218d7cd09580f4d64fccaa1cf9e118fdcd5c73c3d3a8", - "action": "add" - } - }, - "SubmitRequest": { - "1": { - "version": 1, - "hash": "6c38b6ffd0a6f7442746e68b9ace7b21cb1dca7d2031929db5f9a302a280403f", - "action": "add" - } - }, - "ObjectMutation": { - "1": { - "version": 1, - "hash": "ce88096760ce9334599c8194ec97b0a1470651ad680d9d21b8826a0df0af2a36", - "action": "add" - } - }, - "EnumMutation": { - "1": { - "version": 1, - "hash": "5173fda73df17a344eb663b7692cca48bd46bf1773455439836b852cd165448c", - "action": "add" - } - }, - "UserCodeStatusChange": { - "1": { - "version": 1, - "hash": "89aaf7f1368c782e3a1b9e79988877f6eaa05ab84365f7d321b757fde7fe86e7", - "action": "add" - } - }, - "SyncedUserCodeStatusChange": { - "1": { - "version": 1, - "hash": "d9ad2d341eb645bd50d06330cd30fd4c266f93e37b9f5391d58b78365fc440e6", - "action": "add" - } - }, - "TwinAPIContextView": { - "1": { - "version": 1, - "hash": "e099eef32cb3a8a806cbdc54cc7fca96bed3d60344bd571163ec049db407938b", - "action": "add" - } - }, - "CustomAPIView": { - "1": { - "version": 1, - "hash": "769e96bebd05736ab860591670fb6da19406239b0104ddc71bd092a134335146", - "action": "add" - } - }, - "CustomApiEndpoint": { - "1": { - "version": 1, - "hash": "ec4a217585336d1b59c93c18570443a63f4fbb24d2c088fbacf80bcf389d23e8", - "action": "add" - } - }, - "PrivateAPIEndpoint": { - "1": { - "version": 1, - "hash": "6d7d143432c2811c520ab6dade005ba40173b590e5c676be04f5921b970ef938", - "action": "add" - } - }, - "PublicAPIEndpoint": { - "1": { - "version": 1, - "hash": "3bf51fc33aa8feb1abc9d0ef792e8889da31a57050430e0bd8e17f2065ff8734", - "action": "add" - } - }, - "UpdateTwinAPIEndpoint": { - "1": { - "version": 1, - "hash": "851e59412716e73c7f70a696619e0b375ce136b43f6fe2ea784747091caba5d8", - "action": "add" - } - }, - "CreateTwinAPIEndpoint": { - "1": { - "version": 1, - "hash": "3d0b84dae95ebcc6647b5aabe54e65b3c6bf957665fde57d8037806a4aac13be", - "action": "add" - } - }, - "TwinAPIEndpoint": { - "1": { - "version": 1, - "hash": "d1947b8f9c80d6c9b443e5a9f0758afa8849a5f12b9a511feefd7e4f82c374f4", - "action": "add" - } - }, - "SyncState": { - "1": { - "version": 1, - "hash": "9a3f0bb973858b55bc766c9770c4d9abcc817898f797d94a89938650c0c67868", - "action": "add" - } - }, - "WorkerSettings": { - "1": { - "version": 1, - "hash": "b8ddbe75a95b0312a64b5f25e0fc415aeac5c391975d02b515db8c848482f737", - "action": "add" - } - }, - "HTTPServerRoute": { - "1": { - "version": 1, - "hash": "938245604a9c7e50001299afff5b669b2548364e356fed22a22780497831bf81", - "action": "add" - } - }, - "PythonServerRoute": { - "1": { - "version": 1, - "hash": "a068d8f942d55ecb6d45af88a27c6ebf208584275bf589cbc308df3f774ab9a9", - "action": "add" - } - }, - "VeilidServerRoute": { - "1": { - "version": 1, - "hash": "e676bc165601d2ede69707a4b6168ed4674f3f98887026d098a2dd4da4dfd097", - "action": "add" - } - }, - "ServerPeer": { - "1": { - "version": 1, - "hash": "0d5f252018e324ea0d2dcb5c2ad8bd15707220565fce4f14de7f63a8f9e4391b", - "action": "add" - } - }, - "ServerPeerUpdate": { - "1": { - "version": 1, - "hash": "0b854b57db7a18118c1fd8f31495b2ba4eeb9fbe4f24c631ff112418a94570d3", - "action": "add" - } - }, - "AssociationRequestChange": { - "1": { - "version": 1, - "hash": "0134ac0002879c85fc9ddb06bed6306a8905c8434b0a40d3a96ce24a7bd4da90", - "action": "add" - } - }, - "QueueItem": { - "1": { - "version": 1, - "hash": "1db212c46b6c56ccc5579cfe2141b693f0cd9286e2ede71210393e8455379bf1", - "action": "add" - } - }, - "ActionQueueItem": { - "1": { - "version": 1, - "hash": "396d579dfc2e2b36b9fbed2f204bffcca1bea7ee2db7175045dd3328ebf08718", - "action": "add" - } - }, - "APIEndpointQueueItem": { - "1": { - "version": 1, - "hash": "f04b3990a8d29c116d301e70df54d58f188895307a411dc13a666ff764ffd8dd", - "action": "add" - } - }, - "ZMQClientConfig": { - "1": { - "version": 1, - "hash": "36ee8f75067d5144f0ed062cdc79466caae16b7a128231d89b6b430174843bde", - "action": "add" - } - }, - "SQLiteStoreConfig": { - "1": { - "version": 1, - "hash": "ad062a5f863ae84683867d2a6a5e1d4420c010a64b88bc7b392106e33d71ac03", - "action": "add" - } - }, - "ProjectThreadMessage": { - "1": { - "version": 1, - "hash": "99256d7592577d1e37df94a06eabc0a287f2d79e144c51fd719315e278edb46d", - "action": "add" - } - }, - "ProjectMessage": { - "1": { - "version": 1, - "hash": "b5004b6354f71b19c81dd5f4b20bf446e0b959f5608a22707e96b944dd8175b0", - "action": "add" - } - }, - "ProjectRequestResponse": { - "1": { - "version": 1, - "hash": "52162a8a779a4a301d8755691bf4cf994c86b9f650f9e8c8a923b44e635b1bc0", - "action": "add" - } - }, - "ProjectRequest": { - "1": { - "version": 1, - "hash": "dc684135d5a5a48e5fc7988598c1e6e0de76cf1c5995f1c283fcf63d0eb4d24f", - "action": "add" - } - }, - "AnswerProjectPoll": { - "1": { - "version": 1, - "hash": "c83d83a5ba6cc034d5061df200b3f1d029aa770b1e13dbef959bb1790323dc6e", - "action": "add" - } - }, - "ProjectPoll": { - "1": { - "version": 1, - "hash": "ecf69b3b324e0bee9c82295796d44c4e8f796496cdc9db6d4302c2f160566466", - "action": "add" - } - }, - "Project": { - "1": { - "version": 1, - "hash": "de86a1163ddbcd1cc3cc2b1b5dfcb85a8ad9f9d4bbc759c2b1f92a0d0a2ff184", - "action": "add" - } - }, - "ProjectSubmit": { - "1": { - "version": 1, - "hash": "7555ba11ee5a814dcd9c45647300020f7359efc1081559940990cbd745936cac", - "action": "add" - } - }, - "Plan": { - "1": { - "version": 1, - "hash": "ed05cb87aec832098fc464ac36cd6bceaab705463d0d2fa1b2d8e1ccc510018c", - "action": "add" - } - } -} + {} This means the existing data will be automatically be migrated to their latest class versions during the upgrade. diff --git a/packages/grid/helm/syft/values.yaml b/packages/grid/helm/syft/values.yaml index 9fd0fd153f1..7d4d8110010 100644 --- a/packages/grid/helm/syft/values.yaml +++ b/packages/grid/helm/syft/values.yaml @@ -1,7 +1,7 @@ global: # Affects only backend, frontend, and seaweedfs containers registry: docker.io - version: 0.8.8-beta.0 + version: 0.8.8-beta.1 # Force default secret values for development. DO NOT SET THIS TO FALSE IN PRODUCTION randomizedSecrets: true diff --git a/packages/syft/PYPI.md b/packages/syft/PYPI.md index 978e89a4051..8d5905be388 100644 --- a/packages/syft/PYPI.md +++ b/packages/syft/PYPI.md @@ -1,7 +1,7 @@


-Syft Logo +Syft Logo Perform data science on `data` that remains in `someone else's` server @@ -52,21 +52,21 @@ datasite_client = sy.login( ## PySyft in 10 minutes -📝 API Example Notebooks - -- 00-load-data.ipynb -- 01-submit-code.ipynb -- 02-review-code-and-approve.ipynb -- 03-data-scientist-download-result.ipynb -- 04-pytorch-example.ipynb -- 05-custom-policy.ipynb -- 06-multiple-code-requests.ipynb -- 07-datasite-register-control-flow.ipynb -- 08-code-version.ipynb -- 09-blob-storage.ipynb -- 10-container-images.ipynb -- 11-container-images-k8s.ipynb -- 12-custom-api-endpoint.ipynb +📝 API Example Notebooks + +- 00-load-data.ipynb +- 01-submit-code.ipynb +- 02-review-code-and-approve.ipynb +- 03-data-scientist-download-result.ipynb +- 04-pytorch-example.ipynb +- 05-custom-policy.ipynb +- 06-multiple-code-requests.ipynb +- 07-datasite-register-control-flow.ipynb +- 08-code-version.ipynb +- 09-blob-storage.ipynb +- 10-container-images.ipynb +- 11-container-images-k8s.ipynb +- 12-custom-api-endpoint.ipynb ## Deploy Kubernetes Helm Chart @@ -168,7 +168,7 @@ PySyft (Beta): `pip install -U syft --pre` # What is Syft? -Syft +Syft `Syft` is OpenMined's `open source` stack that provides `secure` and `private` Data Science in Python. Syft decouples `private data` from model training, using techniques like [Federated Learning](https://ai.googleblog.com/2017/04/federated-learning-collaborative.html), [Differential Privacy](https://en.wikipedia.org/wiki/Differential_privacy), and [Encrypted Computation](https://en.wikipedia.org/wiki/Homomorphic_encryption). This is done with a `numpy`-like interface and integration with `Deep Learning` frameworks, so that you as a `Data Scientist` can maintain your current workflow while using these new `privacy-enhancing techniques`. @@ -186,19 +186,19 @@ No more cold calls to get `access` to a dataset. No more weeks of `wait times` t
- +

Data Owner

-
+

Data Scientist

- +

Data Engineer

@@ -206,11 +206,11 @@ No more cold calls to get `access` to a dataset. No more weeks of `wait times` t -- Deploy a Datasite Server -- Upload Private Data -- Create Accounts +- Deploy a Datasite Server +- Upload Private Data +- Create Accounts - Manage Privacy Budget -- Join a Network +- Join a Network - Learn how PETs streamline Data Policies @@ -298,9 +298,9 @@ Provides services to a group of `Data Owners` and `Data Scientists`, such as dat
- + - +
@@ -308,7 +308,7 @@ Provides services to a group of `Data Owners` and `Data Scientists`, such as dat
- +

🎥 PETs: Remote Data Science Unleashed - R gov 2021
@@ -327,9 +327,9 @@ Provides services to a group of `Data Owners` and `Data Scientists`, such as dat

- + - +
@@ -343,18 +343,18 @@ Provides services to a group of `Data Owners` and `Data Scientists`, such as dat
- +
- +
- +
@@ -364,51 +364,51 @@ Provides services to a group of `Data Owners` and `Data Scientists`, such as dat OpenMined and Syft appreciates all contributors, if you would like to fix a bug or suggest a new feature, please see our [guidelines](https://openmined.github.io/PySyft/developer_guide/index.html).
-Contributors +Contributors # Supporters diff --git a/packages/syft/setup.cfg b/packages/syft/setup.cfg index 7f3732964ae..3dbcfbe8520 100644 --- a/packages/syft/setup.cfg +++ b/packages/syft/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = syft -version = attr: "0.8.8-beta.0" +version = attr: "0.8.8-beta.1" description = Perform numpy-like analysis on data that remains in someone elses server author = OpenMined author_email = info@openmined.org diff --git a/packages/syft/src/syft/VERSION b/packages/syft/src/syft/VERSION index f6fdfd48ade..8742f2ae357 100644 --- a/packages/syft/src/syft/VERSION +++ b/packages/syft/src/syft/VERSION @@ -1,5 +1,5 @@ # Mono Repo Global Version -__version__ = "0.8.8-beta.0" +__version__ = "0.8.8-beta.1" # elsewhere we can call this file: `python VERSION` and simply take the stdout # stdlib diff --git a/packages/syft/src/syft/__init__.py b/packages/syft/src/syft/__init__.py index ad52c9084ab..230a50330d0 100644 --- a/packages/syft/src/syft/__init__.py +++ b/packages/syft/src/syft/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.8.8-beta.0" +__version__ = "0.8.8-beta.1" # stdlib from collections.abc import Callable diff --git a/packages/syftcli/manifest.yml b/packages/syftcli/manifest.yml index 5a71d3e2f30..56f0eedc87d 100644 --- a/packages/syftcli/manifest.yml +++ b/packages/syftcli/manifest.yml @@ -1,11 +1,11 @@ manifestVersion: 1.0 -syftVersion: 0.8.8-beta.0 -dockerTag: 0.8.8-beta.0 +syftVersion: 0.8.8-beta.1 +dockerTag: 0.8.8-beta.1 images: - - docker.io/openmined/syft-frontend:0.8.8-beta.0 - - docker.io/openmined/syft-backend:0.8.8-beta.0 + - docker.io/openmined/syft-frontend:0.8.8-beta.1 + - docker.io/openmined/syft-backend:0.8.8-beta.1 - docker.io/library/mongo:7.0.4 - docker.io/traefik:v2.11.0 From c104277f6d1108fa8db6a25dabaf90eb7546524a Mon Sep 17 00:00:00 2001 From: Brendan Schell Date: Fri, 19 Jul 2024 12:39:26 -0400 Subject: [PATCH 113/117] update client.me to client.account --- packages/syft/src/syft/client/client.py | 4 +- .../syft/src/syft/service/project/project.py | 4 +- packages/syft/tests/syft/action_test.py | 4 +- .../syft/tests/syft/users/user_code_test.py | 4 +- packages/syft/tests/syft/users/user_test.py | 64 +++++++++---------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/packages/syft/src/syft/client/client.py b/packages/syft/src/syft/client/client.py index dbeb0d12a49..243a3d5dc9a 100644 --- a/packages/syft/src/syft/client/client.py +++ b/packages/syft/src/syft/client/client.py @@ -830,7 +830,7 @@ def peers(self) -> list[ServerPeer] | SyftError | None: return None @property - def me(self) -> UserView | SyftError | None: + def account(self) -> UserView | SyftError | None: if self.api.has_service("user"): return self.api.services.user.get_current_user() return None @@ -909,7 +909,7 @@ def login( if password == get_default_root_password(): message = ( "You are using a default password. Please change the password " - "using `[your_client].me.set_password([new_password])`." + "using `[your_client].account.set_password([new_password])`." ) prompt_warning_message(message) diff --git a/packages/syft/src/syft/service/project/project.py b/packages/syft/src/syft/service/project/project.py index 415f46fefb4..6854503ff8a 100644 --- a/packages/syft/src/syft/service/project/project.py +++ b/packages/syft/src/syft/service/project/project.py @@ -1198,8 +1198,8 @@ def __init__(self, *args: Any, **kwargs: Any): self.users = [UserIdentity.from_client(client) for client in self.clients] # Assign logged in user name as project creator - if isinstance(self.clients[0].me, UserView): - self.username = self.clients[0].me.name + if isinstance(self.clients[0].account, UserView): + self.username = self.clients[0].account.name else: self.username = "" diff --git a/packages/syft/tests/syft/action_test.py b/packages/syft/tests/syft/action_test.py index 47868bc1baa..3e963cf6602 100644 --- a/packages/syft/tests/syft/action_test.py +++ b/packages/syft/tests/syft/action_test.py @@ -57,10 +57,10 @@ def test_new_admin_has_action_object_permission( admin = root_client.login(email=email, password=pw) - root_client.api.services.user.update(uid=admin.me.id, role=ServiceRole.ADMIN) + root_client.api.services.user.update(uid=admin.account.id, role=ServiceRole.ADMIN) if delete_original_admin: - res = root_client.api.services.user.delete(root_client.me.id) + res = root_client.api.services.user.delete(root_client.account.id) assert not isinstance(res, SyftError) assert admin.api.services.action.get(obj.id) == obj diff --git a/packages/syft/tests/syft/users/user_code_test.py b/packages/syft/tests/syft/users/user_code_test.py index 796b6a99753..32b70f42d37 100644 --- a/packages/syft/tests/syft/users/user_code_test.py +++ b/packages/syft/tests/syft/users/user_code_test.py @@ -67,10 +67,10 @@ def test_new_admin_can_list_user_code( admin = root_client.login(email=email, password=pw) - root_client.api.services.user.update(uid=admin.me.id, role=ServiceRole.ADMIN) + root_client.api.services.user.update(uid=admin.account.id, role=ServiceRole.ADMIN) if delete_original_admin: - res = root_client.api.services.user.delete(root_client.me.id) + res = root_client.api.services.user.delete(root_client.account.id) assert not isinstance(res, SyftError) user_code_stash = worker.get_service("usercodeservice").stash diff --git a/packages/syft/tests/syft/users/user_test.py b/packages/syft/tests/syft/users/user_test.py index 8799ce39d5e..00d1743fd71 100644 --- a/packages/syft/tests/syft/users/user_test.py +++ b/packages/syft/tests/syft/users/user_test.py @@ -240,21 +240,21 @@ def test_guest_user_update_to_root_email_failed( default_root_email: str = get_default_root_email() for client in [root_client, do_client, guest_client, ds_client]: res = client.api.services.user.update( - uid=client.me.id, email=default_root_email + uid=client.account.id, email=default_root_email ) assert isinstance(res, SyftError) assert res.message == "User already exists" def test_user_view_set_password(worker: Worker, root_client: DatasiteClient) -> None: - root_client.me.set_password("123", confirm=False) - email = root_client.me.email + root_client.account.set_password("123", confirm=False) + email = root_client.account.email # log in again with the wrong password root_client_c = worker.root_client.login(email=email, password="1234") assert isinstance(root_client_c, SyftError) # log in again with the right password root_client_b = worker.root_client.login(email=email, password="123") - assert root_client_b.me == root_client.me + assert root_client_b.account == root_client.account @pytest.mark.parametrize( @@ -264,7 +264,7 @@ def test_user_view_set_password(worker: Worker, root_client: DatasiteClient) -> def test_user_view_set_invalid_email( root_client: DatasiteClient, invalid_email: str ) -> None: - result = root_client.me.set_email(invalid_email) + result = root_client.account.set_email(invalid_email) assert isinstance(result, SyftError) @@ -281,9 +281,9 @@ def test_user_view_set_email_success( valid_email_root: str, valid_email_ds: str, ) -> None: - result = root_client.me.set_email(valid_email_root) + result = root_client.account.set_email(valid_email_root) assert isinstance(result, SyftSuccess) - result2 = ds_client.me.set_email(valid_email_ds) + result2 = ds_client.account.set_email(valid_email_ds) assert isinstance(result2, SyftSuccess) @@ -291,11 +291,11 @@ def test_user_view_set_default_admin_email_failed( ds_client: DatasiteClient, guest_client: DatasiteClient ) -> None: default_root_email = get_default_root_email() - result = ds_client.me.set_email(default_root_email) + result = ds_client.account.set_email(default_root_email) assert isinstance(result, SyftError) assert result.message == "User already exists" - result_2 = guest_client.me.set_email(default_root_email) + result_2 = guest_client.account.set_email(default_root_email) assert isinstance(result_2, SyftError) assert result_2.message == "User already exists" @@ -303,15 +303,15 @@ def test_user_view_set_default_admin_email_failed( def test_user_view_set_duplicated_email( root_client: DatasiteClient, ds_client: DatasiteClient, guest_client: DatasiteClient ) -> None: - result = ds_client.me.set_email(root_client.me.email) - result2 = guest_client.me.set_email(root_client.me.email) + result = ds_client.account.set_email(root_client.account.email) + result2 = guest_client.account.set_email(root_client.account.email) assert isinstance(result, SyftError) assert result.message == "User already exists" assert isinstance(result2, SyftError) assert result2.message == "User already exists" - result3 = guest_client.me.set_email(ds_client.me.email) + result3 = guest_client.account.set_email(ds_client.account.email) assert isinstance(result3, SyftError) assert result3.message == "User already exists" @@ -321,27 +321,27 @@ def test_user_view_update_name_institution_website( ds_client: DatasiteClient, guest_client: DatasiteClient, ) -> None: - result = root_client.me.update( + result = root_client.account.update( name="syft", institution="OpenMined", website="https://syft.org" ) assert isinstance(result, SyftSuccess) - assert root_client.me.name == "syft" - assert root_client.me.institution == "OpenMined" - assert root_client.me.website == "https://syft.org" + assert root_client.account.name == "syft" + assert root_client.account.institution == "OpenMined" + assert root_client.account.website == "https://syft.org" - result2 = ds_client.me.update(name="syft2", institution="OpenMined") + result2 = ds_client.account.update(name="syft2", institution="OpenMined") assert isinstance(result2, SyftSuccess) - assert ds_client.me.name == "syft2" - assert ds_client.me.institution == "OpenMined" + assert ds_client.account.name == "syft2" + assert ds_client.account.institution == "OpenMined" - result3 = guest_client.me.update(name="syft3") + result3 = guest_client.account.update(name="syft3") assert isinstance(result3, SyftSuccess) - assert guest_client.me.name == "syft3" + assert guest_client.account.name == "syft3" def test_user_view_set_role(worker: Worker, guest_client: DatasiteClient) -> None: admin_client = get_mock_client(worker.root_client, ServiceRole.ADMIN) - assert admin_client.me.role == ServiceRole.ADMIN + assert admin_client.account.role == ServiceRole.ADMIN admin_client.register( name="Sheldon Cooper", email="sheldon@caltech.edu", @@ -353,7 +353,7 @@ def test_user_view_set_role(worker: Worker, guest_client: DatasiteClient) -> Non sheldon = admin_client.users[-1] assert ( sheldon.syft_client_verify_key - == admin_client.me.syft_client_verify_key + == admin_client.account.syft_client_verify_key == admin_client.verify_key ) assert sheldon.role == ServiceRole.DATA_SCIENTIST @@ -365,21 +365,21 @@ def test_user_view_set_role(worker: Worker, guest_client: DatasiteClient) -> Non # be able to change his role, even if he is a data owner now ds_client = guest_client.login(email="sheldon@caltech.edu", password="changethis") assert ( - ds_client.me.syft_client_verify_key + ds_client.account.syft_client_verify_key == ds_client.verify_key != admin_client.verify_key ) - assert ds_client.me.role == sheldon.role - assert ds_client.me.role == ServiceRole.DATA_OWNER - assert isinstance(ds_client.me.update(role="guest"), SyftError) - assert isinstance(ds_client.me.update(role="data_scientist"), SyftError) + assert ds_client.account.role == sheldon.role + assert ds_client.account.role == ServiceRole.DATA_OWNER + assert isinstance(ds_client.account.update(role="guest"), SyftError) + assert isinstance(ds_client.account.update(role="data_scientist"), SyftError) # now we set sheldon's role to admin. Only now he can change his role sheldon.update(role="admin") assert sheldon.role == ServiceRole.ADMIN # QA: this is different than when running in the notebook assert len(ds_client.users.get_all()) == len(admin_client.users.get_all()) - assert isinstance(ds_client.me.update(role="guest"), SyftSuccess) - assert isinstance(ds_client.me.update(role="admin"), SyftError) + assert isinstance(ds_client.account.update(role="guest"), SyftSuccess) + assert isinstance(ds_client.account.update(role="admin"), SyftError) def test_user_view_set_role_admin(faker: Faker) -> None: @@ -405,12 +405,12 @@ def test_user_view_set_role_admin(faker: Faker) -> None: datasite_client.users[1].update(role="admin") ds_client = server.login(email="sheldon@caltech.edu", password="changethis") - assert ds_client.me.role == ServiceRole.ADMIN + assert ds_client.account.role == ServiceRole.ADMIN assert len(ds_client.users.get_all()) == len(datasite_client.users.get_all()) datasite_client.users[2].update(role="admin") ds_client_2 = server.login(email="sheldon2@caltech.edu", password="changethis") - assert ds_client_2.me.role == ServiceRole.ADMIN + assert ds_client_2.account.role == ServiceRole.ADMIN assert len(ds_client_2.users.get_all()) == len(datasite_client.users.get_all()) server.python_server.cleanup() From 1d1e5a1ebe217c426d1139be41a6e57ad3f4bd21 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 22 Jul 2024 14:16:44 +0800 Subject: [PATCH 114/117] Bump torch to 2.3.1 --- packages/syft/setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/syft/setup.cfg b/packages/syft/setup.cfg index 3dbcfbe8520..a52dd904495 100644 --- a/packages/syft/setup.cfg +++ b/packages/syft/setup.cfg @@ -88,7 +88,7 @@ data_science = evaluate==0.4.2 recordlinkage==0.16 # backend.dockerfile installs torch separately, so update the version over there as well! - torch==2.2.2 + torch==2.3.1 dev = %(test_plugins)s From e97ac4dd18e09eadad1223be426ad280e6abd335 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 22 Jul 2024 14:55:22 +0800 Subject: [PATCH 115/117] Temporarily disable warning --- tox.ini | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index d0e58bc3f55..81514895f97 100644 --- a/tox.ini +++ b/tox.ini @@ -244,7 +244,10 @@ deps = commands = bandit -r src # restrictedpython 6.2 - safety check -i 70612 + # Temporarily ignore pytorch vulnerability warning here + # https://data.safetycli.com/v/71670/97c + # TODO: Remove `-i 71670` once torch is updated + safety check -i 70612 -i 71670 [testenv:syft.test.unit] description = Syft Unit Tests @@ -1199,4 +1202,4 @@ commands = commands_post = bash -c 'rm -f notebooks/tutorials/version-upgrades/migration.blob' - bash -c 'rm -f notebooks/tutorials/version-upgrades/migration.yaml' \ No newline at end of file + bash -c 'rm -f notebooks/tutorials/version-upgrades/migration.yaml' From 9b2a993507056c1470abcc9f9616dd379605a903 Mon Sep 17 00:00:00 2001 From: rasswanth-s <43314053+rasswanth-s@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:05:03 +0530 Subject: [PATCH 116/117] added feature branch actions --- .github/workflows/cd-feature-branch.yml | 370 ++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 .github/workflows/cd-feature-branch.yml diff --git a/.github/workflows/cd-feature-branch.yml b/.github/workflows/cd-feature-branch.yml new file mode 100644 index 00000000000..378c6a9ad4a --- /dev/null +++ b/.github/workflows/cd-feature-branch.yml @@ -0,0 +1,370 @@ +#TODO: Due to lack of time, this could not be de-duplicated +# from cd-syft.yml, which have a similar structure +name: CD - Feature Branch + +on: + workflow_dispatch: + inputs: + release_version: + description: "Syft Version to Release" + required: true + type: string + + release_id: + description: "A Unique Identifier for the Release, which would be appended as version+release_id, Can contain only [A-Z][a-z][0-9][.]" + required: true + type: string + + release_platform: + description: "Release Platform" + required: true + default: "TEST_PYPI" + type: choice + options: + - TEST_PYPI + # - REAL_PYPI + # - REAL_AND_TEST_PYPI + +# Prevents concurrent runs of the same workflow +# while the previous run is still in progress +concurrency: + group: "CD - Feature Branch" + cancel-in-progress: false + +jobs: + build-and-push-docker-images: + strategy: + matrix: + runner: [sh-arc-linux-x64, sh-arc-linux-arm64] + runs-on: ${{ matrix.runner }} + + outputs: + server_version: ${{ steps.release_metadata.outputs.server_version }} + + steps: + - uses: actions/checkout@v4 + + # actions/setup-python doesn't yet support ARM + - name: Setup Python on x64 + if: ${{ !endsWith(matrix.runner, '-arm64') }} + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + # Currently psutil package requires gcc to be installed on arm + # for building psutil from source + # as linux/aarch64 wheels not avaialble for psutil + # We could remove once we have aarch64 wheels + # https://github.com/giampaolo/psutil/issues/1972 + - name: Install Metadata packages for arm64 + if: ${{ endsWith(matrix.runner, '-arm64') }} + run: | + sudo apt update -y + sudo apt install software-properties-common -y + sudo apt install gcc curl -y + sudo apt-get install python3-dev -y + + - name: Setup Python on arm64 + if: ${{ endsWith(matrix.runner, '-arm64') }} + uses: deadsnakes/action@v3.1.0 + with: + python-version: "3.12" + + - name: Install Git + run: | + sudo apt-get update + sudo apt-get install git -y + + - name: Check python version + run: | + python --version + python3 --version + which python + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install uv==0.2.17 tox tox-uv==1.9.0 bump2version==1.0.1 + uv --version + + - name: Generate Release Metadata + id: release_metadata + run: | + if [[ ${{matrix.runner}} == *"x64"* ]]; then + echo "release_platform=linux/amd64" >> $GITHUB_OUTPUT + echo "short_release_platform=amd64" >> $GITHUB_OUTPUT + else + echo "release_platform=linux/arm64" >> $GITHUB_OUTPUT + echo "short_release_platform=arm64" >> $GITHUB_OUTPUT + fi + echo "server_version=${{ github.event.inputs.release_version }}+${{github.events.inputs.release_id}}.$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_OUTPUT + + - name: Bump to Final Release version + run: | + python scripts/bump_version.py --bump-to-stable ${{ steps.release_metadata.outputs.server_version}} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_LOGIN }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push `syft-backend` image to DockerHub + id: syft-backend-build + uses: docker/build-push-action@v6 + with: + context: ./packages + file: ./packages/grid/backend/backend.dockerfile + platforms: ${{ steps.release_metadata.outputs.release_platform }} + target: backend + outputs: type=image,name=openmined/syft-backend,push-by-digest=true,name-canonical=true,push=true + cache-from: type=registry,ref=openmined/syft-backend:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-backend:cache-${{ steps.release_metadata.outputs.short_release_platform }},mode=max + + - name: Export digest for syft-backend + run: | + mkdir -p /tmp/digests/syft-backend + digest="${{ steps.syft-backend-build.outputs.digest }}" + touch "/tmp/digests/syft-backend/${digest#sha256:}" + + - name: Build and push `syft-frontend` image to DockerHub + id: syft-frontend-build + uses: docker/build-push-action@v6 + with: + context: ./packages/grid/frontend + file: ./packages/grid/frontend/frontend.dockerfile + platforms: ${{ steps.release_metadata.outputs.release_platform }} + outputs: type=image,name=openmined/syft-frontend,push-by-digest=true,name-canonical=true,push=true + target: syft-ui-development + cache-from: type=registry,ref=openmined/syft-frontend:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-frontend:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max + + - name: Export digest for syft-frontend + run: | + mkdir -p /tmp/digests/syft-frontend + digest="${{ steps.syft-frontend-build.outputs.digest }}" + touch "/tmp/digests/syft-frontend/${digest#sha256:}" + + - name: Build and push `syft-seaweedfs` image to DockerHub + id: syft-seaweedfs-build + uses: docker/build-push-action@v6 + with: + context: ./packages/grid/seaweedfs + file: ./packages/grid/seaweedfs/seaweedfs.dockerfile + platforms: ${{ steps.release_metadata.outputs.release_platform }} + outputs: type=image,name=openmined/syft-seaweedfs,push-by-digest=true,name-canonical=true,push=true + cache-from: type=registry,ref=openmined/syft-seaweedfs:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-seaweedfs:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max + + - name: Export digest for syft-seaweedfs + run: | + mkdir -p /tmp/digests/syft-seaweedfs + digest="${{ steps.syft-seaweedfs-build.outputs.digest }}" + touch "/tmp/digests/syft-seaweedfs/${digest#sha256:}" + + # Some of the dependencies of syft-enclave-attestation are not available for arm64 + # Hence, we are building syft-enclave-attestation only for x64 (see the `if` conditional) + - name: Build and push `syft-enclave-attestation` image to DockerHub + if: ${{ endsWith(matrix.runner, '-x64') }} + id: syft-enclave-attestation-build + uses: docker/build-push-action@v6 + with: + context: ./packages/grid/enclave/attestation + file: ./packages/grid/enclave/attestation/attestation.dockerfile + platforms: ${{ steps.release_metadata.outputs.release_platform }} + outputs: type=image,name=openmined/syft-enclave-attestation,push-by-digest=true,name-canonical=true,push=true + cache-from: type=registry,ref=openmined/syft-enclave-attestation:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-enclave-attestation:cache-${{ steps.release_metadata.outputs.short_release_platform}},mode=max + + - name: Export digest for syft-enclave-attestation + if: ${{ endsWith(matrix.runner, '-x64') }} + run: | + mkdir -p /tmp/digests/syft-enclave-attestation + digest="${{ steps.syft-enclave-attestation-build.outputs.digest }}" + touch "/tmp/digests/syft-enclave-attestation/${digest#sha256:}" + + - name: Build and push `syft` image to registry + id: syft-build + uses: docker/build-push-action@v6 + with: + context: ./packages/ + file: ./packages/grid/syft-client/syft.Dockerfile + outputs: type=image,name=openmined/syft-client,push-by-digest=true,name-canonical=true,push=true + platforms: ${{ steps.release_metadata.outputs.release_platform }} + cache-from: type=registry,ref=openmined/syft-client:cache-${{ steps.release_metadata.outputs.short_release_platform }} + cache-to: type=registry,ref=openmined/syft-client:cache-${{ steps.release_metadata.outputs.short_release_platform }},mode=max + + - name: Export digest for `syft` image + run: | + mkdir -p /tmp/digests/syft + digest="${{ steps.syft-build.outputs.digest }}" + touch "/tmp/digests/syft/${digest#sha256:}" + + - name: Upload digests + uses: actions/upload-artifact@v4 + with: + name: digests-${{ steps.release_metadata.outputs.server_version }}-${{ steps.release_metadata.outputs.short_release_platform }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + #Used to merge x64 and arm64 into one docker image + merge-docker-images: + needs: [build-and-push-docker-images] + if: always() && (needs.build-and-push-docker-images.result == 'success') + + runs-on: sh-arc-linux-x64 + + outputs: + server_version: ${{ needs.build-and-push-docker-images.outputs.server_version }} + + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-${{ needs.build-and-push-docker-images.outputs.server_version }}-* + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_LOGIN }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Create manifest list and push for syft-backend + working-directory: /tmp/digests/syft-backend + run: | + docker buildx imagetools create \ + -t openmined/syft-backend:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + $(printf 'openmined/syft-backend@sha256:%s ' *) + + - name: Create manifest list and push for syft-frontend + working-directory: /tmp/digests/syft-frontend + run: | + docker buildx imagetools create \ + -t openmined/syft-frontend:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + $(printf 'openmined/syft-frontend@sha256:%s ' *) + + - name: Create manifest list and push for syft-seaweedfs + working-directory: /tmp/digests/syft-seaweedfs + run: | + docker buildx imagetools create \ + -t openmined/syft-seaweedfs:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + $(printf 'openmined/syft-seaweedfs@sha256:%s ' *) + + - name: Create manifest list and push for syft-enclave-attestation + working-directory: /tmp/digests/syft-enclave-attestation + run: | + docker buildx imagetools create \ + -t openmined/syft-enclave-attestation:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + $(printf 'openmined/syft-enclave-attestation@sha256:%s ' *) + + - name: Create manifest list and push for syft client + working-directory: /tmp/digests/syft + run: | + docker buildx imagetools create \ + -t openmined/syft-client:${{ needs.build-and-push-docker-images.outputs.server_version }} \ + $(printf 'openmined/syft-client@sha256:%s ' *) + + deploy-syft: + needs: [merge-docker-images] + if: always() && needs.merge-docker-images.result == 'success' + + runs-on: ubuntu-latest + + steps: + - name: Permission to home directory + run: | + sudo chown -R $USER:$USER $HOME + + - uses: actions/checkout@v4 + with: + token: ${{ secrets.SYFT_BOT_COMMIT_TOKEN }} + + # free 10GB of space + - name: Remove unnecessary files + run: | + sudo rm -rf /usr/share/dotnet + sudo rm -rf "$AGENT_TOOLSDIRECTORY" + docker image prune --all --force + docker builder prune --all --force + docker system prune --all --force + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install uv==0.2.17 tox tox-uv==1.9.0 setuptools wheel twine bump2version PyYAML + uv --version + + - name: Bump to Final Release version + run: | + python scripts/bump_version.py --bump-to-stable ${{ needs.merge-docker-images.outputs.server_version }} + + - name: Build Helm Chart + shell: bash + run: | + # install k3d + K3D_VERSION=v5.6.3 + wget https://github.com/k3d-io/k3d/releases/download/${K3D_VERSION}/k3d-linux-amd64 + mv k3d-linux-amd64 k3d + chmod +x k3d + export PATH=`pwd`:$PATH + k3d version + + #Install Devspace + DEVSPACE_VERSION=v6.3.12 + curl -sSL https://github.com/loft-sh/devspace/releases/download/${DEVSPACE_VERSION}/devspace-linux-amd64 -o ./devspace + chmod +x devspace + devspace version + + # Install helm + curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + helm version + + tox -e syft.build.helm + tox -e syft.package.helm + + - name: Linting + run: | + tox -e lint || true + + - name: Manual Build and Publish + run: | + tox -e syft.publish + if [[ "${{ github.event.inputs.release_platform }}" == "TEST_PYPI" ]]; then + twine upload -r testpypi -u __token__ -p ${{ secrets.OM_SYFT_TEST_PYPI_TOKEN }} packages/syft/dist/* + fi + + # Checkout to gh-pages and update helm repo + - name: Checkout to gh-pages + uses: actions/checkout@v4 + with: + ref: gh-pages + token: ${{ secrets.SYFT_BOT_COMMIT_TOKEN }} + path: ghpages + + - name: Copy helm repo files from Syft Repo + run: | + rm -rf ghpages/helm/* + cp -R packages/grid/helm/repo/. ghpages/helm/ + + - name: Commit changes to gh-pages + uses: EndBug/add-and-commit@v9 + with: + author_name: ${{ secrets.OM_BOT_NAME }} + author_email: ${{ secrets.OM_BOT_EMAIL }} + message: "Update Helm package from Syft Repo" + add: "helm/" + push: "origin gh-pages" + cwd: "./ghpages/" From 7273785ba6ea003d68d049dd2e39bd72994eb566 Mon Sep 17 00:00:00 2001 From: rasswanth-s <43314053+rasswanth-s@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:11:22 +0530 Subject: [PATCH 117/117] add release branch to workflow --- .github/workflows/cd-feature-branch.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/cd-feature-branch.yml b/.github/workflows/cd-feature-branch.yml index 378c6a9ad4a..0b67328c5c7 100644 --- a/.github/workflows/cd-feature-branch.yml +++ b/.github/workflows/cd-feature-branch.yml @@ -10,6 +10,11 @@ on: required: true type: string + release_branch: + description: "Branch to Release from" + required: true + type: string + release_id: description: "A Unique Identifier for the Release, which would be appended as version+release_id, Can contain only [A-Z][a-z][0-9][.]" required: true @@ -43,6 +48,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.release_branch }} # actions/setup-python doesn't yet support ARM - name: Setup Python on x64 @@ -287,6 +294,7 @@ jobs: - uses: actions/checkout@v4 with: token: ${{ secrets.SYFT_BOT_COMMIT_TOKEN }} + ref: ${{ github.event.inputs.release_branch }} # free 10GB of space - name: Remove unnecessary files
- + - + - + - + - + - + - + - + - + - + - +