diff --git a/packages/grid/backend/grid/core/config.py b/packages/grid/backend/grid/core/config.py index 9f13b7b54fd..9d41011c344 100644 --- a/packages/grid/backend/grid/core/config.py +++ b/packages/grid/backend/grid/core/config.py @@ -2,17 +2,19 @@ import os import secrets from typing import Any -from typing import Dict from typing import List from typing import Optional from typing import Union # third party from pydantic import AnyHttpUrl -from pydantic import BaseSettings from pydantic import EmailStr from pydantic import HttpUrl -from pydantic import validator +from pydantic import field_validator +from pydantic import model_validator +from pydantic_settings import BaseSettings +from pydantic_settings import SettingsConfigDict +from typing_extensions import Self _truthy = {"yes", "y", "true", "t", "on", "1"} _falsy = {"no", "n", "false", "f", "off", "0"} @@ -50,7 +52,8 @@ class Settings(BaseSettings): # "http://localhost:8080", "http://local.dockertoolbox.tiangolo.com"]' BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = [] - @validator("BACKEND_CORS_ORIGINS", pre=True) + @field_validator("BACKEND_CORS_ORIGINS", mode="before") + @classmethod def assemble_cors_origins(cls, v: Union[str, List[str]]) -> Union[List[str], str]: if isinstance(v, str) and not v.startswith("["): return [i.strip() for i in v.split(",")] @@ -62,7 +65,8 @@ def assemble_cors_origins(cls, v: Union[str, List[str]]) -> Union[List[str], str SENTRY_DSN: Optional[HttpUrl] = None - @validator("SENTRY_DSN", pre=True) + @field_validator("SENTRY_DSN", mode="before") + @classmethod def sentry_dsn_can_be_blank(cls, v: str) -> Optional[str]: if v is None or len(v) == 0: return None @@ -76,11 +80,12 @@ def sentry_dsn_can_be_blank(cls, v: str) -> Optional[str]: EMAILS_FROM_EMAIL: Optional[EmailStr] = None EMAILS_FROM_NAME: Optional[str] = None - @validator("EMAILS_FROM_NAME") - def get_project_name(cls, v: Optional[str], values: Dict[str, Any]) -> str: - if not v: - return values["PROJECT_NAME"] - return v + @model_validator(mode="after") + def get_project_name(self) -> Self: + if not self.EMAILS_FROM_NAME: + self.EMAILS_FROM_NAME = self.PROJECT_NAME + + return self EMAIL_RESET_TOKEN_EXPIRE_HOURS: int = 48 EMAIL_TEMPLATES_DIR: str = os.path.expandvars( @@ -88,15 +93,15 @@ def get_project_name(cls, v: Optional[str], values: Dict[str, Any]) -> str: ) EMAILS_ENABLED: bool = False - @validator("EMAILS_ENABLED", pre=True) - def get_emails_enabled(cls, v: bool, values: Dict[str, Any]) -> bool: - return bool( - values.get("SMTP_HOST") - and values.get("SMTP_PORT") - and values.get("EMAILS_FROM_EMAIL") + @model_validator(mode="after") + def get_emails_enabled(self) -> Self: + self.EMAILS_ENABLED = bool( + self.SMTP_HOST and self.SMTP_PORT and self.EMAILS_FROM_EMAIL ) - DEFAULT_ROOT_EMAIL: EmailStr = EmailStr("info@openmined.org") + return self + + DEFAULT_ROOT_EMAIL: EmailStr = "info@openmined.org" DEFAULT_ROOT_PASSWORD: str = "changethis" USERS_OPEN_REGISTRATION: bool = False @@ -149,9 +154,7 @@ def get_emails_enabled(cls, v: bool, values: Dict[str, Any]) -> bool: True if os.getenv("TEST_MODE", "false").lower() == "true" else False ) ASSOCIATION_TIMEOUT: int = 10 - - class Config: - case_sensitive = True + model_config = SettingsConfigDict(case_sensitive=True) settings = Settings() diff --git a/packages/grid/backend/grid/logger/config.py b/packages/grid/backend/grid/logger/config.py index 7c5ea9ddb41..5f2376a9615 100644 --- a/packages/grid/backend/grid/logger/config.py +++ b/packages/grid/backend/grid/logger/config.py @@ -11,7 +11,7 @@ from typing import Union # third party -from pydantic import BaseSettings +from pydantic_settings import BaseSettings # LOGURU_LEVEL type for version>3.8 @@ -40,14 +40,9 @@ class LogConfig(BaseSettings): LOGURU_LEVEL: str = LogLevel.INFO.value LOGURU_SINK: Optional[str] = "/var/log/pygrid/grid.log" - LOGURU_COMPRESSION: Optional[str] - LOGURU_ROTATION: Union[ - Optional[str], - Optional[int], - Optional[time], - Optional[timedelta], - ] - LOGURU_RETENTION: Union[Optional[str], Optional[int], Optional[timedelta]] + LOGURU_COMPRESSION: Optional[str] = None + LOGURU_ROTATION: Union[str, int, time, timedelta, None] = None + LOGURU_RETENTION: Union[str, int, timedelta, None] = None LOGURU_COLORIZE: Optional[bool] = True LOGURU_SERIALIZE: Optional[bool] = False LOGURU_BACKTRACE: Optional[bool] = True diff --git a/packages/hagrid/hagrid/orchestra.py b/packages/hagrid/hagrid/orchestra.py index 8a0e74c06b6..8ee771c0036 100644 --- a/packages/hagrid/hagrid/orchestra.py +++ b/packages/hagrid/hagrid/orchestra.py @@ -9,6 +9,7 @@ import inspect import os import subprocess # nosec +import sys from threading import Thread from typing import Any from typing import Callable @@ -598,7 +599,10 @@ def shutdown( elif "No resource found to remove for project" in land_output: print(f" ✅ {snake_name} Container does not exist") else: - print(f"❌ Unable to remove container: {snake_name} :{land_output}") + print( + f"❌ Unable to remove container: {snake_name} :{land_output}", + file=sys.stderr, + ) @staticmethod def reset(name: str, deployment_type_enum: DeploymentType) -> None: diff --git a/packages/syft/setup.cfg b/packages/syft/setup.cfg index 05aeef53039..20cc255c3da 100644 --- a/packages/syft/setup.cfg +++ b/packages/syft/setup.cfg @@ -37,7 +37,8 @@ syft = pyarrow==14.0.1 # pycapnp is beta version, update to stable version when available pycapnp==2.0.0b2 - pydantic[email]==1.10.13 + pydantic[email]==2.6.0 + pydantic-settings==2.2.1 pymongo==4.6.1 pynacl==1.5.0 pyzmq>=23.2.1,<=25.1.1 diff --git a/packages/syft/src/syft/client/api.py b/packages/syft/src/syft/client/api.py index 5821550b2b9..9cb7cfa741a 100644 --- a/packages/syft/src/syft/client/api.py +++ b/packages/syft/src/syft/client/api.py @@ -117,11 +117,11 @@ class APIEndpoint(SyftObject): module_path: str name: str description: str - doc_string: Optional[str] + doc_string: Optional[str] = None signature: Signature has_self: bool = False - pre_kwargs: Optional[Dict[str, Any]] - warning: Optional[APIEndpointWarning] + pre_kwargs: Optional[Dict[str, Any]] = None + warning: Optional[APIEndpointWarning] = None @serializable() @@ -134,10 +134,10 @@ class LibEndpoint(SyftBaseObject): module_path: str name: str description: str - doc_string: Optional[str] + doc_string: Optional[str] = None signature: Signature has_self: bool = False - pre_kwargs: Optional[Dict[str, Any]] + pre_kwargs: Optional[Dict[str, Any]] = None @serializable(attrs=["signature", "credentials", "serialized_message"]) @@ -207,7 +207,7 @@ class SyftAPIData(SyftBaseObject): __version__ = SYFT_OBJECT_VERSION_1 # fields - data: Any + data: Any = None def sign(self, credentials: SyftSigningKey) -> SignedSyftAPICall: signed_message = credentials.signing_key.sign(_serialize(self, to_bytes=True)) @@ -233,9 +233,9 @@ class RemoteFunction(SyftObject): signature: Signature path: str make_call: Callable - pre_kwargs: Optional[Dict[str, Any]] + pre_kwargs: Optional[Dict[str, Any]] = None communication_protocol: PROTOCOL_TYPE - warning: Optional[APIEndpointWarning] + warning: Optional[APIEndpointWarning] = None @property def __ipython_inspector_signature_override__(self) -> Optional[Signature]: @@ -1078,5 +1078,5 @@ def validate_callable_args_and_kwargs( return _valid_args, _valid_kwargs -RemoteFunction.update_forward_refs() -RemoteUserCodeFunction.update_forward_refs() +RemoteFunction.model_rebuild(force=True) +RemoteUserCodeFunction.model_rebuild(force=True) diff --git a/packages/syft/src/syft/client/client.py b/packages/syft/src/syft/client/client.py index 505b780f318..bd27da9ea51 100644 --- a/packages/syft/src/syft/client/client.py +++ b/packages/syft/src/syft/client/client.py @@ -19,7 +19,7 @@ # third party from argon2 import PasswordHasher -import pydantic +from pydantic import field_validator import requests from requests import Response from requests import Session @@ -135,14 +135,19 @@ class HTTPConnection(NodeConnection): __canonical_name__ = "HTTPConnection" __version__ = SYFT_OBJECT_VERSION_1 - proxy_target_uid: Optional[UID] url: GridURL + proxy_target_uid: Optional[UID] = None routes: Type[Routes] = Routes - session_cache: Optional[Session] + session_cache: Optional[Session] = None - @pydantic.validator("url", pre=True, always=True) - def make_url(cls, v: Union[GridURL, str]) -> GridURL: - return GridURL.from_url(v).as_container_host() + @field_validator("url", mode="before") + @classmethod + def make_url(cls, v: Any) -> Any: + return ( + GridURL.from_url(v).as_container_host() + if isinstance(v, (str, GridURL)) + else v + ) def with_proxy(self, proxy_target_uid: UID) -> Self: return HTTPConnection(url=self.url, proxy_target_uid=proxy_target_uid) @@ -329,7 +334,7 @@ class PythonConnection(NodeConnection): __version__ = SYFT_OBJECT_VERSION_1 node: AbstractNode - proxy_target_uid: Optional[UID] + proxy_target_uid: Optional[UID] = None def with_proxy(self, proxy_target_uid: UID) -> Self: return PythonConnection(node=self.node, proxy_target_uid=proxy_target_uid) diff --git a/packages/syft/src/syft/client/gateway_client.py b/packages/syft/src/syft/client/gateway_client.py index 89cb97a4755..cae8bc076cf 100644 --- a/packages/syft/src/syft/client/gateway_client.py +++ b/packages/syft/src/syft/client/gateway_client.py @@ -154,7 +154,7 @@ class ProxyClient(SyftObject): __version__ = SYFT_OBJECT_VERSION_1 routing_client: GatewayClient - node_type: Optional[NodeType] + node_type: Optional[NodeType] = None def retrieve_nodes(self) -> List[NodePeer]: if self.node_type in [NodeType.DOMAIN, NodeType.ENCLAVE]: diff --git a/packages/syft/src/syft/custom_worker/config.py b/packages/syft/src/syft/custom_worker/config.py index 58f4b3f626b..b35505f6994 100644 --- a/packages/syft/src/syft/custom_worker/config.py +++ b/packages/syft/src/syft/custom_worker/config.py @@ -12,7 +12,7 @@ # third party import docker from packaging import version -from pydantic import validator +from pydantic import field_validator from typing_extensions import Self import yaml @@ -54,7 +54,8 @@ class CustomBuildConfig(SyftBaseModel): # f"Python version must be between {PYTHON_MIN_VER} and {PYTHON_MAX_VER}" # ) - @validator("python_packages") + @field_validator("python_packages") + @classmethod def validate_python_packages(cls, pkgs: List[str]) -> List[str]: for pkg in pkgs: ver_parts: Union[tuple, list] = () @@ -114,7 +115,7 @@ def get_signature(self) -> str: class PrebuiltWorkerConfig(WorkerConfig): # tag that is already built and pushed in some registry tag: str - description: Optional[str] + description: Optional[str] = None def __str__(self) -> str: if self.description: @@ -129,10 +130,11 @@ def set_description(self, description_text: str) -> None: @serializable() class DockerWorkerConfig(WorkerConfig): dockerfile: str - file_name: Optional[str] - description: Optional[str] + file_name: Optional[str] = None + description: Optional[str] = None - @validator("dockerfile") + @field_validator("dockerfile") + @classmethod def validate_dockerfile(cls, dockerfile: str) -> str: if not dockerfile: raise ValueError("Dockerfile cannot be empty") diff --git a/packages/syft/src/syft/custom_worker/k8s.py b/packages/syft/src/syft/custom_worker/k8s.py index 2c953ff1297..067d23d1a3f 100644 --- a/packages/syft/src/syft/custom_worker/k8s.py +++ b/packages/syft/src/syft/custom_worker/k8s.py @@ -63,9 +63,9 @@ class ContainerStatus(BaseModel): ready: bool running: bool waiting: bool - reason: Optional[str] # when waiting=True - message: Optional[str] # when waiting=True - startedAt: Optional[str] # when running=True + reason: Optional[str] = None # when waiting=True + message: Optional[str] = None # when waiting=True + startedAt: Optional[str] = None # when running=True @classmethod def from_status(cls, cstatus: dict) -> Self: diff --git a/packages/syft/src/syft/external/oblv/deployment_client.py b/packages/syft/src/syft/external/oblv/deployment_client.py index a34a01d225c..deecee225a1 100644 --- a/packages/syft/src/syft/external/oblv/deployment_client.py +++ b/packages/syft/src/syft/external/oblv/deployment_client.py @@ -18,7 +18,7 @@ # third party from oblv_ctl import OblvClient -from pydantic import validator +from pydantic import field_validator import requests # relative @@ -46,10 +46,11 @@ class OblvMetadata(EnclaveMetadata): """Contains Metadata to connect to Oblivious Enclave""" - deployment_id: Optional[str] - oblv_client: Optional[OblvClient] + deployment_id: Optional[str] = None + oblv_client: Optional[OblvClient] = None - @validator("deployment_id") + @field_validator("deployment_id") + @classmethod def check_valid_deployment_id(cls, deployment_id: str) -> str: if not deployment_id and not LOCAL_MODE: raise ValueError( @@ -59,7 +60,8 @@ def check_valid_deployment_id(cls, deployment_id: str) -> str: ) return deployment_id - @validator("oblv_client") + @field_validator("oblv_client") + @classmethod def check_valid_oblv_client(cls, oblv_client: OblvClient) -> OblvClient: if not oblv_client and not LOCAL_MODE: raise ValueError( diff --git a/packages/syft/src/syft/node/credentials.py b/packages/syft/src/syft/node/credentials.py index c60c57e1db2..d774f0f4c91 100644 --- a/packages/syft/src/syft/node/credentials.py +++ b/packages/syft/src/syft/node/credentials.py @@ -9,7 +9,7 @@ from nacl.encoding import HexEncoder from nacl.signing import SigningKey from nacl.signing import VerifyKey -import pydantic +from pydantic import field_validator # relative from ..serde.serializable import serializable @@ -54,8 +54,9 @@ def __hash__(self) -> int: class SyftSigningKey(SyftBaseModel): signing_key: SigningKey - @pydantic.validator("signing_key", pre=True, always=True) - def make_signing_key(cls, v: Union[str, SigningKey]) -> SigningKey: + @field_validator("signing_key", mode="before") + @classmethod + def make_signing_key(cls, v: Any) -> Any: return SigningKey(bytes.fromhex(v)) if isinstance(v, str) else v @property diff --git a/packages/syft/src/syft/node/node.py b/packages/syft/src/syft/node/node.py index 176c7f19e89..86af3a29767 100644 --- a/packages/syft/src/syft/node/node.py +++ b/packages/syft/src/syft/node/node.py @@ -1213,8 +1213,8 @@ def handle_api_call_with_unsigned_result( if api_call.path not in user_config_registry: if ServiceConfigRegistry.path_exists(api_call.path): return SyftError( - message=f"As a `{role}`," - f"you have has no access to: {api_call.path}" + message=f"As a `{role}`, " + f"you have no access to: {api_call.path}" ) else: return SyftError( diff --git a/packages/syft/src/syft/node/worker_settings.py b/packages/syft/src/syft/node/worker_settings.py index 05b28f02c0b..dd433468844 100644 --- a/packages/syft/src/syft/node/worker_settings.py +++ b/packages/syft/src/syft/node/worker_settings.py @@ -38,7 +38,7 @@ class WorkerSettingsV1(SyftObject): signing_key: SyftSigningKey document_store_config: StoreConfig action_store_config: StoreConfig - blob_store_config: Optional[BlobStorageConfig] + blob_store_config: Optional[BlobStorageConfig] = None @serializable() @@ -53,8 +53,8 @@ class WorkerSettings(SyftObject): signing_key: SyftSigningKey document_store_config: StoreConfig action_store_config: StoreConfig - blob_store_config: Optional[BlobStorageConfig] - queue_config: Optional[QueueConfig] + blob_store_config: Optional[BlobStorageConfig] = None + queue_config: Optional[QueueConfig] = None @classmethod def from_node(cls, node: AbstractNode) -> Self: diff --git a/packages/syft/src/syft/protocol/protocol_version.json b/packages/syft/src/syft/protocol/protocol_version.json index 34b62666e2e..a24d3320068 100644 --- a/packages/syft/src/syft/protocol/protocol_version.json +++ b/packages/syft/src/syft/protocol/protocol_version.json @@ -1,136 +1,984 @@ { - "1": { - "release_name": "0.8.2.json" - }, - "2": { - "release_name": "0.8.3.json" - }, - "3": { - "release_name": "0.8.4.json" - }, "dev": { "object_versions": { + "PartialSyftObject": { + "1": { + "version": 1, + "hash": "008917584d8e1c09015cdbef02f59c0622f48e0618877c1b44425c8846befc13", + "action": "add" + } + }, + "NodeMetadataUpdate": { + "1": { + "version": 1, + "hash": "569d124c23590360bda240c19b53314ccc6204c5d1ab0d2898976a028e002191", + "action": "add" + } + }, + "NodeMetadata": { + "1": { + "version": 1, + "hash": "6bee018894dfdf697ea624740d0bf051750e0b0d8470ced59646f6d8812068ac", + "action": "add" + }, + "2": { + "version": 2, + "hash": "f856169fea72486cd436875ce4411ef935da11eb7c5af48121adfa00d4c0cdb6", + "action": "add" + }, + "3": { + "version": 3, + "hash": "3cc67abf394a805066a88aef0bea15bde609b9ecbe7ec15172eac5e7a0b7ef7c", + "action": "add" + } + }, + "StoreConfig": { + "1": { + "version": 1, + "hash": "17de8875cf590311ddb042140347ffc79d4a85028e504dad178ca4e1237ec861", + "action": "add" + } + }, + "MongoDict": { + "1": { + "version": 1, + "hash": "640734396edae801e1601fe7777710e67685e552acb0244ad8b4f689599baca9", + "action": "add" + } + }, + "MongoStoreConfig": { + "1": { + "version": 1, + "hash": "a6d48634dbfce836754b60ca1c35db30c86df795ffdbe87bb7758ba4f809f6c1", + "action": "add" + } + }, + "LinkedObject": { + "1": { + "version": 1, + "hash": "824567c6933c095d0e2f6995c8de3581c0fbd2e9e4ead35c8159f7964709c28e", + "action": "add" + } + }, + "BaseConfig": { + "1": { + "version": 1, + "hash": "4e5257080ce615aa4122b02bad8487e4c7d6d0f171ff77abbc9e8cd3e33df89a", + "action": "add" + } + }, + "ServiceConfig": { + "1": { + "version": 1, + "hash": "ca91f59bf045d949d82860f7d52655bfbede4cf6bdc5bae8f847f08a16f05d74", + "action": "add" + } + }, + "LibConfig": { + "1": { + "version": 1, + "hash": "c6ff229aea16874c5d9ae4d1f9e500d13f5cf984bbcee7abd16c5841707a2f78", + "action": "add" + } + }, + "APIEndpoint": { + "1": { + "version": 1, + "hash": "c0e83867b107113e6fed06364ba364c24b2f4af35b15a3869b176318d3be7989", + "action": "add" + } + }, + "LibEndpoint": { + "1": { + "version": 1, + "hash": "153eac6d8990774eebfffaa75a9895e7c4e1a0e09465d5da0baf4c3a3b03369d", + "action": "add" + } + }, + "SignedSyftAPICall": { + "1": { + "version": 1, + "hash": "e66a116de2fa44ebdd0d4c2d7d5a047dedb555fd201a0f431cd8017d9d33a61d", + "action": "add" + } + }, + "SyftAPICall": { + "1": { + "version": 1, + "hash": "014bd1d0933f6070888a313edba239170759de24eae49bf2374c1be4dbe2b4d7", + "action": "add" + } + }, + "SyftAPIData": { + "1": { + "version": 1, + "hash": "db101a75227e34750d7056785a1e87bb2e8ad6604f19c372d0cb6aa437243bf5", + "action": "add" + } + }, + "SyftAPI": { + "1": { + "version": 1, + "hash": "2bba1d9fcf677a58e35bf903de3da22ee4913af138aa3012af9c46b3609579cd", + "action": "add" + } + }, + "User": { + "2": { + "version": 2, + "hash": "ded970c92f202716ed33a2117cf541789f35fad66bd4b1db39da5026b1d7d0e7", + "action": "add" + } + }, + "UserUpdate": { + "2": { + "version": 2, + "hash": "32cba8fbd786c575f92e26c31384d282e68e3ebfe5c4b0a0e793820b1228d246", + "action": "add" + } + }, + "UserCreate": { + "2": { + "version": 2, + "hash": "2540188c5aaea866914dccff459df6e0f4727108a503414bb1567ff6297d4646", + "action": "add" + } + }, + "UserSearch": { + "1": { + "version": 1, + "hash": "69d1e10b81c8a4143cf70e4f911d8562732af2458ebbc455ca64542f11373dd1", + "action": "add" + } + }, + "UserView": { + "2": { + "version": 2, + "hash": "e410de583bb15bc5af57acef7be55ea5fc56b5b0fc169daa3869f4203c4d7473", + "action": "add" + } + }, + "UserViewPage": { + "1": { + "version": 1, + "hash": "16dac6209b19a934d286ef1efa874379e0040c324e71023c57d1bc6d2d367171", + "action": "add" + } + }, + "UserPrivateKey": { + "1": { + "version": 1, + "hash": "7cb196587887f0f3bffb298dd9f3b88509e9b2748792bf8dc03bdd0d6b98714a", + "action": "add" + } + }, + "NodeSettingsUpdate": { + "1": { + "version": 1, + "hash": "b6ddc66ff270a3c2c4760e31e1a55d72ed04ccae2d0115ebe2fba6f2bf9bd119", + "action": "add" + } + }, + "NodeSettings": { + "1": { + "version": 1, + "hash": "b662047bb278f4f5db77c102f94b733c3a929839271b3d6b82ea174a60e2aaf0", + "action": "add" + }, + "2": { + "version": 2, + "hash": "29a82afcb006a044b6ae04c6ea8a067d145d28b4210bb038ea9fa86ebde108c8", + "action": "add" + } + }, + "HTTPConnection": { + "1": { + "version": 1, + "hash": "5ee19eaf55ecbe7945ea45924c036ec0f500114a2f64176620961a8c2ec94cdb", + "action": "add" + } + }, + "PythonConnection": { + "1": { + "version": 1, + "hash": "011946fc9af0a6987f5c7bc9b0208b2fae9d65217531430bced7ba542788da1a", + "action": "add" + } + }, + "DateTime": { + "1": { + "version": 1, + "hash": "7e9d89309a10d2110a7ae4f97d8f25a7914853269e8fa0c531630790c1253f17", + "action": "add" + } + }, + "ActionDataEmpty": { + "1": { + "version": 1, + "hash": "89b5912fe5416f922051b8068be6071a03c87a4ab264959de524f1b86e95f028", + "action": "add" + } + }, + "ObjectNotReady": { + "1": { + "version": 1, + "hash": "88207988639b11eaca686b6e079616d9caecc3dbc2a8112258e0f39ee5c3e113", + "action": "add" + } + }, + "ActionDataLink": { + "1": { + "version": 1, + "hash": "10bf94e99637695f1ba283f0b10e70743a4ebcb9ee75aefb1a05e6d6e1d21a71", + "action": "add" + } + }, + "Action": { + "1": { + "version": 1, + "hash": "5cf71ee35097f17fbb1dd05096f875211d71cf07161205d7f6a9c11fd49d5272", + "action": "add" + }, + "2": { + "version": 2, + "hash": "125da21171e5bdac0b1547d804df98e1de6ed2942ea181c7f7883372fdf23620", + "action": "add" + } + }, "ActionObject": { + "1": { + "version": 1, + "hash": "49079c4481865c54f198fbd3ef41f1babdf71d5878f14ec8556cdace6203b30f", + "action": "add" + }, + "2": { + "version": 2, + "hash": "7876ae48df101386df1e3edb075bae5f0b348f5bce516e1467ea6a3cddf9d4ec", + "action": "add" + }, "3": { "version": 3, - "hash": "9cc29f4b637e7a9407ff5f56e282b5411c2709e8195214c452e44b65f9051d56", + "hash": "0fe8c63c7ebf317c9b3791563eede28ce301dc0a2a1a98b13e657f34ed1e9edb", + "action": "add" + } + }, + "AnyActionObject": { + "1": { + "version": 1, + "hash": "0a181a8950a9e91e06217a2b9bece1bfbb06ba732da4a267ce05b20dd2945b0e", + "action": "add" + }, + "2": { + "version": 2, + "hash": "60e1e4be3fc1486cddd73ae3594af46d40943c48bbe6f81f42322258712120bd", + "action": "add" + }, + "3": { + "version": 3, + "hash": "0ac9122d40743966890247c7444c1033ba52bdbb0d2396daf8767adbe42faaad", + "action": "add" + } + }, + "SyftImageRegistry": { + "1": { + "version": 1, + "hash": "dc83910c91947e3d9eaa3e6f8592237448f0408668c7cca80450b5fcd54722e1", + "action": "add" + } + }, + "SyftWorkerImage": { + "1": { + "version": 1, + "hash": "2a9585b6a286e24f1a9f3f943d0128730cf853edc549184dc1809d19e1eec54b", + "action": "add" + } + }, + "SyftWorker": { + "1": { + "version": 1, + "hash": "0d5b367162f3ce55ab090cc1b49bd30e50d4eb144e8431eadc679bd0e743aa70", + "action": "add" + } + }, + "WorkerPool": { + "1": { + "version": 1, + "hash": "250699eb4c452fc427995353d5c5ad6245fb3e9fdac8814f8348784816a0733b", + "action": "add" + } + }, + "BlobFile": { + "1": { + "version": 1, + "hash": "47ed55183d619c6c624e35412360a41de42833e2c24223c1de1ad12a84fdafc2", + "action": "add" + }, + "3": { + "version": 3, + "hash": "8f1710c754bb3b39f546b97fd69c4826291398b247976bbc41fa873af431bca9", + "action": "add" + } + }, + "BlobFileOBject": { + "1": { + "version": 1, + "hash": "0fbf142f99e18fecc72e145f1d86c592dea1289c60eeef82fcf69c5c74b261fb", + "action": "add" + }, + "2": { + "version": 2, + "hash": "cf3789022517ea88c968672566e7e3ae1dbf35c9f8ac5f09fd1ff7ca79534444", + "action": "add" + } + }, + "SecureFilePathLocation": { + "1": { + "version": 1, + "hash": "7febc066e2ee5a3a4a891720afede3f5c155cacc0557662ac4d04bf67b964c6d", + "action": "add" + } + }, + "SeaweedSecureFilePathLocation": { + "1": { + "version": 1, + "hash": "5724a38b1a92b8a55da3d9cc34a720365a6d0c32683acda630fc44067173e201", + "action": "add" + }, + "2": { + "version": 2, + "hash": "5fd63fed2a4efba8c2b6c7a7b5e9b5939181781c331230896aa130b6fd558739", + "action": "add" + } + }, + "AzureSecureFilePathLocation": { + "1": { + "version": 1, + "hash": "1bb15f3f9d7082779f1c9f58de94011487924cb8a8c9c2ec18fd7c161c27fd0e", + "action": "add" + } + }, + "BlobStorageEntry": { + "1": { + "version": 1, + "hash": "9f1b027cce390ee6f71c7a81e7420bb71a477b29c6c62ba74e781a97bc5434e6", + "action": "add" + }, + "2": { + "version": 2, + "hash": "5472bdd5bdce6d0b561543a6bac70d47bf0c05c141a21450751460cc538d6b55", + "action": "add" + } + }, + "BlobStorageMetadata": { + "1": { + "version": 1, + "hash": "6888943be3f97186190dd26d7eefbdf29b15c6f2fa459e13608065ebcdb799e2", + "action": "add" + }, + "2": { + "version": 2, + "hash": "674f4c52a8444289d5ef389b919008860e2b0e7acbaafa774d58e492d5b6741a", + "action": "add" + } + }, + "CreateBlobStorageEntry": { + "1": { + "version": 1, + "hash": "61a373336e83645f1b6d78a320323d9ea4ee91b3d87b730cb0608fbfa0072262", + "action": "add" + } + }, + "BlobRetrieval": { + "1": { + "version": 1, + "hash": "a8d7e1d6483e7a9b5a130e837fa398862aa6cbb316cc5f4470450d835755fdd9", + "action": "add" + }, + "2": { + "version": 2, + "hash": "4c4fbdb6df5bb9fcbe914a9890bd1c1b6a1b3f382a04cbc8752a5a1b03130111", + "action": "add" + } + }, + "SyftObjectRetrieval": { + "2": { + "version": 2, + "hash": "d9d7a7e1b8843145c9687fd013c9223700285886073547734267e91ac53e0996", + "action": "add" + }, + "3": { + "version": 3, + "hash": "952958e9afae007bef3cb89aa15be95dddc4c310e3a8ce4191576f90ac6fcbc8", + "action": "add" + } + }, + "BlobRetrievalByURL": { + "3": { + "version": 3, + "hash": "0b664100ea08413ca4ef04665ca910c2cf9535539617ea4ba33687d05cdfe747", + "action": "add" + } + }, + "BlobDeposit": { + "1": { + "version": 1, + "hash": "c98e6da658a3be01ead4ea6ee6a4c10046879f0ce0f5fc5f946346671579b229", + "action": "add" + } + }, + "WorkerSettings": { + "1": { + "version": 1, + "hash": "0dcd95422ec8a7c74e45ee68a125084c08f898dc94a13d25fe5a5fd0e4fc5027", + "action": "add" + }, + "2": { + "version": 2, + "hash": "d623a8a0d6c83b26ba49686bd8be10eccb126f54626fef334a85396c3b8a8ed6", + "action": "add" + } + }, + "QueueItem": { + "1": { + "version": 1, + "hash": "5aa94681d9d0715d5b605f9625a54e114927271378cf2ea7245f85c488035e0b", + "action": "add" + }, + "2": { + "version": 2, + "hash": "9503b878de4b5b7a1793580301353523b7d6219ebd27d38abe598061979b7570", + "action": "add" + }, + "3": { + "version": 3, + "hash": "3495f406d2c97050ce86be80c230f49b6b846c63b9a9230cbd6631952f2bad0f", + "action": "add" + } + }, + "ActionQueueItem": { + "1": { + "version": 1, + "hash": "11a43caf9164eb2a5a21f4bcb0ca361d0a5d134bf3c60173f2c502d0d80219de", + "action": "add" + }, + "2": { + "version": 2, + "hash": "6413ed01e949cac169299a43ce40651f9bf8053e408b6942853f8afa8a693b3d", + "action": "add" + } + }, + "ZMQClientConfig": { + "1": { + "version": 1, + "hash": "e6054969b495791569caaf33239039beae3d116e1fe74e9575467c48b9007c45", + "action": "add" + }, + "3": { + "version": 3, + "hash": "91ce5953cced58e12c576aa5174d5ca0c91981b01cf42edd5283d347baa3390b", + "action": "add" + } + }, + "HTTPNodeRoute": { + "1": { + "version": 1, + "hash": "1901b9f53f9970ce2bd8307ba9f7cafc0e7eba1d2ec82e4014c6120e605e3741", + "action": "add" + } + }, + "PythonNodeRoute": { + "1": { + "version": 1, + "hash": "15711e6e7a1ef726c8e8b5c35a6cb2d30b56ba5213cba489524bf63489e136cf", + "action": "add" + } + }, + "EnclaveMetadata": { + "1": { + "version": 1, + "hash": "39f85e475015e6f860ddcc5fea819423eba2db8f4b7d8e004c05a44d6f8444c6", + "action": "add" + } + }, + "DataSubject": { + "1": { + "version": 1, + "hash": "0b8b049d4627727b444c419f5d6a97b7cb97a433088ebf744c854b6a470dadf1", + "action": "add" + } + }, + "DataSubjectCreate": { + "1": { + "version": 1, + "hash": "f8f7f130fc2fcc54c5f984828cd3e2c7004c7d66e6ba7218adfa5b19d8d4b4a6", + "action": "add" + } + }, + "DataSubjectMemberRelationship": { + "1": { + "version": 1, + "hash": "0a820edc9f1a87387acc3c611fe852752fcb3dab7608058f2bc48211be7bfbd2", + "action": "add" + } + }, + "Contributor": { + "1": { + "version": 1, + "hash": "d1d4f25bb87e59c0414501d3335097de66815c164c9ed5a7850ff8bec69fbcdc", + "action": "add" + } + }, + "MarkdownDescription": { + "1": { + "version": 1, + "hash": "519328a3952049f57004013e4fb00840695b24b8575cad983056412c9c9d9ba6", + "action": "add" + } + }, + "Asset": { + "1": { + "version": 1, + "hash": "24350b8d9597df49999918ad42e0eece1328ea30389311f1e0a420be8f39b8a1", + "action": "add" + } + }, + "CreateAsset": { + "1": { + "version": 1, + "hash": "1b4c71569b8da64258672483bd36dc4aa99a32d4cb519659241d15bc898041a6", + "action": "add" + } + }, + "Dataset": { + "1": { + "version": 1, + "hash": "d16d64aa2b3b179f4bcdf88b837d4bda26d7a66d9505f473b56982634deb3808", + "action": "add" + } + }, + "DatasetPageView": { + "1": { + "version": 1, + "hash": "b1de14bb9b6a259648dfc59b6a48fa526116afe50a689c24b8bb36fd0e6a97f8", + "action": "add" + } + }, + "CreateDataset": { + "1": { + "version": 1, + "hash": "1a53db706b173758f47097d9fd47b435228cf73a50315c54741015652805be52", + "action": "add" + } + }, + "JobItem": { + "1": { + "version": 1, + "hash": "7b8723861837b0b7e948b2cf9244159d232185f3407dd6bef108346f941ddf6e", + "action": "add" + }, + "2": { + "version": 2, + "hash": "e99cf5a78c6dd3a0adc37af3472c7c21570a9e747985dff540a2b06d24de6446", + "action": "add" + }, + "3": { + "version": 3, + "hash": "5b93a59e28574691339d22826d5650969336a2e930b93d6b3fe6d5409ca0cfc4", + "action": "add" + } + }, + "JobInfo": { + "1": { + "version": 1, + "hash": "cf26eeac3d9254dfa439917493b816341f8a379a77d182bbecba3b7ed2c1d00a", + "action": "add" + }, + "2": { + "version": 2, + "hash": "5c1f7d5e6a991123a1907c1823be14a75458ba06af1fe5a1b77aaac7fa546c78", + "action": "add" + } + }, + "ExecutionOutput": { + "1": { + "version": 1, + "hash": "833addc66807a638939aac00a4be306c93bd8d80a8f4ce6fcdb16d98e87ceb8b", + "action": "add" + } + }, + "TwinObject": { + "1": { + "version": 1, + "hash": "c42455586b43724a7421becd99122b787a129798daf6081e96954ecaea228099", + "action": "add" + } + }, + "ExactMatch": { + "1": { + "version": 1, + "hash": "e497e2e2380db72766c5e219e8afd13136d8953933d6f1eaf83b14001e887cde", + "action": "add" + } + }, + "OutputHistory": { + "1": { + "version": 1, + "hash": "4ec6e6efd86a972b474251885151bdfe4ef262562174605e8ab6a8abba1aa867", + "action": "add" + } + }, + "OutputPolicyExecuteCount": { + "2": { + "version": 2, + "hash": "ca0ba249f4f32379f5b83279a27df4a21eb23c531a86538c821a10ddf2c799ff", + "action": "add" + } + }, + "OutputPolicyExecuteOnce": { + "2": { + "version": 2, + "hash": "e6b0f23047037734c1cc448771bc2770f5bf6c8b8f80cf46939eb7ba66dd377e", + "action": "add" + } + }, + "UserPolicy": { + "1": { + "version": 1, + "hash": "c69b17b1d96cace8b45da6d9639165f2da4aa7ff156b6fd922ac217bf7856d8a", + "action": "add" + } + }, + "SubmitUserPolicy": { + "1": { + "version": 1, + "hash": "96f7f39279fadc70c569b8d48ed4d6420a8132db51e37466d272fda19953554b", + "action": "add" + } + }, + "UserCodeStatusCollection": { + "1": { + "version": 1, + "hash": "4afcdcebd4b0ba95a8ac65eda9fcaa88129b7c520e8e6b093c6ab5208641a617", "action": "add" } }, - "AnyActionObject": { - "3": { - "version": 3, - "hash": "ad6b897da9bdf2fcacc853fad73b7d7b98c8d0ecb58c35110e236edefd99f561", + "UserCode": { + "1": { + "version": 1, + "hash": "e14c22686cdc7d1fb2b0d01c0aebdea37e62a61b051677c1d30234214f05cd42", "action": "add" - } - }, - "BlobFileOBject": { + }, "2": { "version": 2, - "hash": "eb895881610723d674755033b0f1798219725d5ad70791d25a44f473ddff318b", + "hash": "660e1abc15034f525e91ffdd820c2a2179bfddf83b7b9e3ce7823b2efc515c69", + "action": "add" + }, + "4": { + "version": 4, + "hash": "4acb1fa6856da943966b6a93eb7874000f785b29f12ecbed9025606f8fe51aa4", "action": "add" } }, - "JobInfo": { + "SubmitUserCode": { "2": { "version": 2, - "hash": "5c1f7d5e6a991123a1907c1823be14a75458ba06af1fe5a1b77aaac7fa546c78", + "hash": "9b29e060973a3de8d3564a2b7d2bb5c53745aa445bf257576994b613505d7194", + "action": "add" + }, + "3": { + "version": 3, + "hash": "a29160c16d2e2620800d42cdcd9f3637d063a570c477a5d05217a2e64b4bb396", "action": "add" } }, - "ExecutionOutput": { + "UserCodeExecutionResult": { "1": { "version": 1, - "hash": "833addc66807a638939aac00a4be306c93bd8d80a8f4ce6fcdb16d98e87ceb8b", + "hash": "49c32e85e78b7b189a7f13b7e26115ef94fcb0b60b578adcbe2b95e289f63a6e", "action": "add" } }, - "OutputPolicyExecuteCount": { + "UserCodeExecutionOutput": { "1": { "version": 1, - "hash": "6bb24b3b35e19564c43b838ca3f46ccdeadb6596511917f2d220681a378e439d", - "action": "remove" - }, - "2": { - "version": 2, - "hash": "ca0ba249f4f32379f5b83279a27df4a21eb23c531a86538c821a10ddf2c799ff", + "hash": "94c18d2dec05b39993c1a7a70bca2c991c95bd168005a93e578a810e57ef3164", "action": "add" } }, - "OutputPolicyExecuteOnce": { + "CodeHistory": { + "1": { + "version": 1, + "hash": "a7baae93862ae0aa67675f1617574e31aafb15a9ebff633eb817278a3a867161", + "action": "add" + } + }, + "CodeHistoryView": { + "1": { + "version": 1, + "hash": "0ed1a2a04a962ecbcfa38b0b8a03c1e51e8946a4b80f6bf2557148ce658671ce", + "action": "add" + } + }, + "CodeHistoriesDict": { + "1": { + "version": 1, + "hash": "95288411cd5843834f3273a2fd66a7df2e603e980f4ab1d329f9ab17d5d2f643", + "action": "add" + } + }, + "UsersCodeHistoriesDict": { + "1": { + "version": 1, + "hash": "5e1f389c4565ee8558386dd5c934d81e0c68ab1434f86bb9065976b587ef44d1", + "action": "add" + } + }, + "SyftLog": { "1": { "version": 1, - "hash": "32a40fc9966b277528eebc61c01041f3a5447417731954abdaffbb14dabc76bb", - "action": "remove" + "hash": "bd3f62b8fe4b2718a6380c8f05a93c5c40169fc4ab174db291929298e588429e", + "action": "add" }, "2": { "version": 2, - "hash": "e6b0f23047037734c1cc448771bc2770f5bf6c8b8f80cf46939eb7ba66dd377e", + "hash": "d3ce45794da2e6c4b0cef63b98a553525af50c5d9db42d3d64caef3e7d22b4a9", "action": "add" } }, - "UserCodeStatusCollection": { + "OnDiskBlobDeposit": { "1": { "version": 1, - "hash": "4afcdcebd4b0ba95a8ac65eda9fcaa88129b7c520e8e6b093c6ab5208641a617", + "hash": "5efc230c1ee65c4626d334aa69ed458c796c45265e546a333844c6c2bcd0e6b0", "action": "add" } }, - "UserCode": { - "3": { - "version": 3, - "hash": "90fcae0f556f375ba1e91d2e345f57241660695c6e2b84c8e311df89d09e6c66", - "action": "remove" + "RemoteConfig": { + "1": { + "version": 1, + "hash": "ad7bc4780a8ad52e14ce68601852c93d2fe07bda489809cad7cae786d2461754", + "action": "add" + } + }, + "AzureRemoteConfig": { + "1": { + "version": 1, + "hash": "c05c6caa27db4e385c642536d4b0ecabc0c71e91220d2e6ce21a2761ca68a673", + "action": "add" + } + }, + "SeaweedFSBlobDeposit": { + "1": { + "version": 1, + "hash": "382a9ac178deed2a9591e1ebbb39f265cbe67027fb93a420d473a4c26b7fda11", + "action": "add" }, - "4": { - "version": 4, - "hash": "4acb1fa6856da943966b6a93eb7874000f785b29f12ecbed9025606f8fe51aa4", + "2": { + "version": 2, + "hash": "07d84a95324d95d9c868cd7d1c33c908f77aa468671d76c144586aab672bcbb5", "action": "add" } }, - "UserCodeExecutionOutput": { + "DictStoreConfig": { "1": { "version": 1, - "hash": "94c18d2dec05b39993c1a7a70bca2c991c95bd168005a93e578a810e57ef3164", + "hash": "256e9c623ce0becd555ddd2a55a0c15514e162786b1549388cef98a92a9b18c9", "action": "add" } }, "NumpyArrayObject": { + "1": { + "version": 1, + "hash": "6154a7b13c177ae6584965648bf1bf32e187e8a97f297bce1cdfca63f83a86a5", + "action": "add" + }, + "2": { + "version": 2, + "hash": "4139e24efefd95a64d853c9701d3cc742704217a36e25313ab7f9d3b54027cd4", + "action": "add" + }, "3": { "version": 3, - "hash": "8572cdfb6a9f8b20c276aeebaf12cd26e424703ea624cf52efdbe33a8ab3d4ef", + "hash": "b6c27c63285f55425942296a91bb16010fd359909fb82fcd52efa9e744e5f2a4", "action": "add" } }, "NumpyScalarObject": { + "1": { + "version": 1, + "hash": "713fc4e6e4429ed34e49a0cf156a300ff73b53673af4cba7443bd83887c4ac19", + "action": "add" + }, + "2": { + "version": 2, + "hash": "8cbd24a20bb40b58c68bea330306a51cf6376f077b298f16d185c3e9470150f1", + "action": "add" + }, "3": { "version": 3, - "hash": "d3107530ef42a6f3b234423a3c5efcb13f4b43a5959642a0b1e3c093992d59d1", + "hash": "028e645eea21425a049a56393218c2e89343edf09e9ff70d7fed6561c6508a43", "action": "add" } }, "NumpyBoolObject": { + "1": { + "version": 1, + "hash": "4c4562a531fe6c067b5319c2c9735e4108474eae599ca3f75622df6550f322f1", + "action": "add" + }, + "2": { + "version": 2, + "hash": "1c1c6991d0ed36be43185bd991be33f54c7b5d938b1400a2b59b85e37c00a2b0", + "action": "add" + }, "3": { "version": 3, - "hash": "b9cd5c27630b0c67465d21e1d67a0b2591cd59aa6ac7d60ab1f5f64a746114df", + "hash": "e36b44d1829aff0e127bb1ba7b8e8f6853d6cf94cc86ef11c521019f1eec7e96", "action": "add" } }, "PandasDataframeObject": { + "1": { + "version": 1, + "hash": "0c677a65a31ec6f8b74c8d575edc4013950380cde7bb78e0fe206d16205658ec", + "action": "add" + }, + "2": { + "version": 2, + "hash": "fe98ec3d8e49b9c1302f29fede6c98b01753ecee0e035996eccb158e16f5b3d3", + "action": "add" + }, "3": { "version": 3, - "hash": "f1ec7d6debb6d2d81e752418dd84544995b16d0386da791c4770914a227700d9", + "hash": "90fb7e7e5c7b03f37573012029c6979ccaaa44e720a48a7f829d83c6a41393e5", "action": "add" } }, "PandasSeriesObject": { + "1": { + "version": 1, + "hash": "4b9a9a980fe48bb7692db4d268421894e9e65606fd3633e9a8c752152d8a0aed", + "action": "add" + }, + "2": { + "version": 2, + "hash": "58c33bfb4963a371afc8c18a1368753339b6c2b5731801ab9ef47d6211924f53", + "action": "add" + }, "3": { "version": 3, - "hash": "96f75160ec2a966fc3866cf2e86b151914012514e2b89f618933cdfbb639e528", + "hash": "50d5d68c0b4d57f8ecf594ee9761a6b4a9cd726354a4c8e3ff28e4e0a2fe58a4", + "action": "add" + } + }, + "ReplyNotification": { + "1": { + "version": 1, + "hash": "34b2ad522f7406c2486573467d9c7acef5c1063a0d9f2177c3bda2d8c4f87572", + "action": "add" + } + }, + "Notification": { + "1": { + "version": 1, + "hash": "d13981f721fe2b3e2717640ee07dc716c596e4ecd442461665c3fdab0b85bf0e", + "action": "add" + } + }, + "CreateNotification": { + "1": { + "version": 1, + "hash": "b1f459de374fe674f873a4a5f3fb8a8aabe0d83faad84a933f0a77dd1141159a", + "action": "add" + } + }, + "Change": { + "1": { + "version": 1, + "hash": "aefebd1601cf5bfd4817b0db75300a78299cc4949ead735a90873cbd22c8d4bc", + "action": "add" + } + }, + "ChangeStatus": { + "1": { + "version": 1, + "hash": "627f6f8e42cc285336aa6fd4916285d796140f4ff901487b7cb3907ef0f116a6", + "action": "add" + } + }, + "ActionStoreChange": { + "1": { + "version": 1, + "hash": "17b865e75eb3fb2693924fb00ba87a25260be45d55a4eb2184c4ead22d787cbe", + "action": "add" + } + }, + "CreateCustomImageChange": { + "1": { + "version": 1, + "hash": "bc09dca7995938f3b3a2bd9c8b3c2feffc8484df466144a425cb69cadb2ab635", + "action": "add" + } + }, + "CreateCustomWorkerPoolChange": { + "1": { + "version": 1, + "hash": "86894f8ccc037de61f44f9698fd113ba02c3cf3870a3048c00a46e15dcd1941c", + "action": "add" + } + }, + "Request": { + "1": { + "version": 1, + "hash": "e054307eeb7f13683cde9ce7613d5ca2925a13fff7c345b1c9f729a12c955f90", + "action": "add" + } + }, + "RequestInfo": { + "1": { + "version": 1, + "hash": "b76075c138afc0563ce9ac7f6b1131f048951f7486cd516c02736dc1a2a23639", + "action": "add" + } + }, + "RequestInfoFilter": { + "1": { + "version": 1, + "hash": "7103abdc464ae71bb746410f5730f55dd8ed82268aa32bbb0a69e0070488a669", + "action": "add" + } + }, + "SubmitRequest": { + "1": { + "version": 1, + "hash": "96b4ec12beafd9d8a7c97399cb8a23dade4db16d8f521be3fe7b8fec99db5161", + "action": "add" + } + }, + "ObjectMutation": { + "1": { + "version": 1, + "hash": "0ee3dd38d6df0fe9a19d848e8f3aaaf13a6ba86afe3406c239caed6da185651a", + "action": "add" + } + }, + "EnumMutation": { + "1": { + "version": 1, + "hash": "4c02f956ec9b973064972cc57fc8dd9c525e683f93f804642b4e1bfee1b62e57", "action": "add" } }, "UserCodeStatusChange": { + "1": { + "version": 1, + "hash": "4f5b405cc2b3976ed8f7018df82e873435d9187dff15fa5a23bc85a738969f3f", + "action": "add" + }, + "2": { + "version": 2, + "hash": "d83e0905ae882c824ba8fbbf455cd3881906bf8b2ebbfff07bcf471ef869cedc", + "action": "add" + }, "3": { "version": 3, "hash": "999ab977d4fe5a7b74ee2d90370599ce9caa1b38fd6e6c29bd543d379c4dae31", @@ -150,6 +998,90 @@ "hash": "6da39adb0ecffb4ca7873c0d95ed31c8bf037610cde144662285b921de5d8f04", "action": "add" } + }, + "NodePeer": { + "1": { + "version": 1, + "hash": "7b88de7e38490e2d69f31295137673e7ddabc16ab0e2272ff491f6cea1835d63", + "action": "add" + } + }, + "SyftObjectMigrationState": { + "1": { + "version": 1, + "hash": "d3c8126bc15dae4dd243bb035530e3f56cd9e433d403dd6b5f3b45face6d281f", + "action": "add" + } + }, + "ProjectThreadMessage": { + "1": { + "version": 1, + "hash": "1118e935792e8e54103dbf91fa33edbf192a7767d2b1d4526dfa7d4a643cde2e", + "action": "add" + } + }, + "ProjectMessage": { + "1": { + "version": 1, + "hash": "55a3a5171b6949372b4125cc461bf39bc998565e07703804fca6c7ef99695ae4", + "action": "add" + } + }, + "ProjectRequestResponse": { + "1": { + "version": 1, + "hash": "d4c360e845697a0b24695143d0781626cd344cfde43162c90ae90fe67e00ae21", + "action": "add" + } + }, + "ProjectRequest": { + "1": { + "version": 1, + "hash": "514d189df335c68869eea36befcdcafec74bdc682eaf18871fe879e26da4dbb6", + "action": "add" + } + }, + "AnswerProjectPoll": { + "1": { + "version": 1, + "hash": "ff2e1ac7bb764c99d646b96eb3ebfbf9311599b7e3be07aa4a4eb4810bb6dd12", + "action": "add" + } + }, + "ProjectPoll": { + "1": { + "version": 1, + "hash": "b0ac8f1d9c06997374ddbc33fdf1d0af0da15fdb6899f52d91a8574106558964", + "action": "add" + } + }, + "Project": { + "1": { + "version": 1, + "hash": "ec5b7ac1c92808e266f06b175c6ebcd50be81777ad120c02ce8c6074d0004788", + "action": "add" + } + }, + "ProjectSubmit": { + "1": { + "version": 1, + "hash": "0374b37779497d7e0b2ffeabc38d35bfbae2ee762a7674a5a8af75e7c5545e61", + "action": "add" + } + }, + "SQLiteStoreConfig": { + "1": { + "version": 1, + "hash": "b656b26c14cf4e97aba702dd62a0927aec7f860c12eed512c2c688e1b7109aa5", + "action": "add" + } + }, + "Plan": { + "1": { + "version": 1, + "hash": "1aecbc00bbbb99745a1919f98a48bd27ba020d4968dd7c215e4f422dbfed0d92", + "action": "add" + } } } } diff --git a/packages/syft/src/syft/protocol/releases/.gitkeep b/packages/syft/src/syft/protocol/releases/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/syft/src/syft/protocol/releases/0.8.2.json b/packages/syft/src/syft/protocol/releases/0.8.2.json deleted file mode 100644 index 0ea2060243e..00000000000 --- a/packages/syft/src/syft/protocol/releases/0.8.2.json +++ /dev/null @@ -1,763 +0,0 @@ -{ - "1": { - "object_versions": { - "PartialSyftObject": { - "1": { - "version": 1, - "hash": "008917584d8e1c09015cdbef02f59c0622f48e0618877c1b44425c8846befc13", - "action": "add" - } - }, - "NodeMetadataUpdate": { - "1": { - "version": 1, - "hash": "569d124c23590360bda240c19b53314ccc6204c5d1ab0d2898976a028e002191", - "action": "add" - } - }, - "NodeMetadata": { - "1": { - "version": 1, - "hash": "6bee018894dfdf697ea624740d0bf051750e0b0d8470ced59646f6d8812068ac", - "action": "add" - }, - "2": { - "version": 2, - "hash": "f856169fea72486cd436875ce4411ef935da11eb7c5af48121adfa00d4c0cdb6", - "action": "add" - }, - "3": { - "version": 3, - "hash": "3cc67abf394a805066a88aef0bea15bde609b9ecbe7ec15172eac5e7a0b7ef7c", - "action": "add" - } - }, - "StoreConfig": { - "1": { - "version": 1, - "hash": "17de8875cf590311ddb042140347ffc79d4a85028e504dad178ca4e1237ec861", - "action": "add" - } - }, - "MongoDict": { - "1": { - "version": 1, - "hash": "640734396edae801e1601fe7777710e67685e552acb0244ad8b4f689599baca9", - "action": "add" - } - }, - "MongoStoreConfig": { - "1": { - "version": 1, - "hash": "e52aa382e300b0b69aaa2d80aadb4e3a9a3c02b3c741b71d56f959c4d3891ce5", - "action": "add" - } - }, - "LinkedObject": { - "1": { - "version": 1, - "hash": "824567c6933c095d0e2f6995c8de3581c0fbd2e9e4ead35c8159f7964709c28e", - "action": "add" - } - }, - "BaseConfig": { - "1": { - "version": 1, - "hash": "4e5257080ce615aa4122b02bad8487e4c7d6d0f171ff77abbc9e8cd3e33df89a", - "action": "add" - } - }, - "ServiceConfig": { - "1": { - "version": 1, - "hash": "ca91f59bf045d949d82860f7d52655bfbede4cf6bdc5bae8f847f08a16f05d74", - "action": "add" - } - }, - "LibConfig": { - "1": { - "version": 1, - "hash": "c6ff229aea16874c5d9ae4d1f9e500d13f5cf984bbcee7abd16c5841707a2f78", - "action": "add" - } - }, - "APIEndpoint": { - "1": { - "version": 1, - "hash": "c0e83867b107113e6fed06364ba364c24b2f4af35b15a3869b176318d3be7989", - "action": "add" - } - }, - "LibEndpoint": { - "1": { - "version": 1, - "hash": "153eac6d8990774eebfffaa75a9895e7c4e1a0e09465d5da0baf4c3a3b03369d", - "action": "add" - } - }, - "SignedSyftAPICall": { - "1": { - "version": 1, - "hash": "e66a116de2fa44ebdd0d4c2d7d5a047dedb555fd201a0f431cd8017d9d33a61d", - "action": "add" - } - }, - "SyftAPICall": { - "1": { - "version": 1, - "hash": "014bd1d0933f6070888a313edba239170759de24eae49bf2374c1be4dbe2b4d7", - "action": "add" - } - }, - "SyftAPIData": { - "1": { - "version": 1, - "hash": "db101a75227e34750d7056785a1e87bb2e8ad6604f19c372d0cb6aa437243bf5", - "action": "add" - } - }, - "SyftAPI": { - "1": { - "version": 1, - "hash": "2bba1d9fcf677a58e35bf903de3da22ee4913af138aa3012af9c46b3609579cd", - "action": "add" - } - }, - "User": { - "1": { - "version": 1, - "hash": "078636e64f737e60245b39cf348d30fb006531e80c12b70aa7cf98254e1bb37a", - "action": "add" - } - }, - "UserUpdate": { - "1": { - "version": 1, - "hash": "839dd90aeb611e1dc471c8fd6daf230e913465c0625c6a297079cb7f0a271195", - "action": "add" - } - }, - "UserCreate": { - "1": { - "version": 1, - "hash": "dab78b63544ae91c09f9843c323cb237c0a6fcfeb71c1acf5f738e2fcf5c277f", - "action": "add" - } - }, - "UserSearch": { - "1": { - "version": 1, - "hash": "69d1e10b81c8a4143cf70e4f911d8562732af2458ebbc455ca64542f11373dd1", - "action": "add" - } - }, - "UserView": { - "1": { - "version": 1, - "hash": "63289383fe7e7584652f242a4362ce6e2f0ade52f6416ab6149b326a506b0675", - "action": "add" - } - }, - "UserViewPage": { - "1": { - "version": 1, - "hash": "16dac6209b19a934d286ef1efa874379e0040c324e71023c57d1bc6d2d367171", - "action": "add" - } - }, - "UserPrivateKey": { - "1": { - "version": 1, - "hash": "7cb196587887f0f3bffb298dd9f3b88509e9b2748792bf8dc03bdd0d6b98714a", - "action": "add" - } - }, - "NodeSettingsUpdate": { - "1": { - "version": 1, - "hash": "b6ddc66ff270a3c2c4760e31e1a55d72ed04ccae2d0115ebe2fba6f2bf9bd119", - "action": "add" - } - }, - "NodeSettings": { - "1": { - "version": 1, - "hash": "b662047bb278f4f5db77c102f94b733c3a929839271b3d6b82ea174a60e2aaf0", - "action": "add" - }, - "2": { - "version": 2, - "hash": "29a82afcb006a044b6ae04c6ea8a067d145d28b4210bb038ea9fa86ebde108c8", - "action": "add" - } - }, - "HTTPConnection": { - "1": { - "version": 1, - "hash": "5ee19eaf55ecbe7945ea45924c036ec0f500114a2f64176620961a8c2ec94cdb", - "action": "add" - } - }, - "PythonConnection": { - "1": { - "version": 1, - "hash": "011946fc9af0a6987f5c7bc9b0208b2fae9d65217531430bced7ba542788da1a", - "action": "add" - } - }, - "DateTime": { - "1": { - "version": 1, - "hash": "7e9d89309a10d2110a7ae4f97d8f25a7914853269e8fa0c531630790c1253f17", - "action": "add" - } - }, - "BlobFile": { - "1": { - "version": 1, - "hash": "47ed55183d619c6c624e35412360a41de42833e2c24223c1de1ad12a84fdafc2", - "action": "add" - } - }, - "SecureFilePathLocation": { - "1": { - "version": 1, - "hash": "7febc066e2ee5a3a4a891720afede3f5c155cacc0557662ac4d04bf67b964c6d", - "action": "add" - } - }, - "SeaweedSecureFilePathLocation": { - "1": { - "version": 1, - "hash": "5724a38b1a92b8a55da3d9cc34a720365a6d0c32683acda630fc44067173e201", - "action": "add" - } - }, - "BlobStorageEntry": { - "1": { - "version": 1, - "hash": "9f1b027cce390ee6f71c7a81e7420bb71a477b29c6c62ba74e781a97bc5434e6", - "action": "add" - } - }, - "BlobStorageMetadata": { - "1": { - "version": 1, - "hash": "6888943be3f97186190dd26d7eefbdf29b15c6f2fa459e13608065ebcdb799e2", - "action": "add" - } - }, - "CreateBlobStorageEntry": { - "1": { - "version": 1, - "hash": "61a373336e83645f1b6d78a320323d9ea4ee91b3d87b730cb0608fbfa0072262", - "action": "add" - } - }, - "BlobRetrieval": { - "1": { - "version": 1, - "hash": "a8d7e1d6483e7a9b5a130e837fa398862aa6cbb316cc5f4470450d835755fdd9", - "action": "add" - } - }, - "SyftObjectRetrieval": { - "1": { - "version": 1, - "hash": "7ccc62d5b434d2d438b3df661b4d753b0c7c8d593d451d8b86d364da83998c89", - "action": "add" - } - }, - "BlobRetrievalByURL": { - "1": { - "version": 1, - "hash": "18fd860cb9de296532fc9ff075932e6a4377cc8f043dd88ed4f620517321077d", - "action": "add" - } - }, - "BlobDeposit": { - "1": { - "version": 1, - "hash": "c98e6da658a3be01ead4ea6ee6a4c10046879f0ce0f5fc5f946346671579b229", - "action": "add" - } - }, - "WorkerSettings": { - "1": { - "version": 1, - "hash": "0dcd95422ec8a7c74e45ee68a125084c08f898dc94a13d25fe5a5fd0e4fc5027", - "action": "add" - } - }, - "HTTPNodeRoute": { - "1": { - "version": 1, - "hash": "1901b9f53f9970ce2bd8307ba9f7cafc0e7eba1d2ec82e4014c6120e605e3741", - "action": "add" - } - }, - "PythonNodeRoute": { - "1": { - "version": 1, - "hash": "15711e6e7a1ef726c8e8b5c35a6cb2d30b56ba5213cba489524bf63489e136cf", - "action": "add" - } - }, - "EnclaveMetadata": { - "1": { - "version": 1, - "hash": "39f85e475015e6f860ddcc5fea819423eba2db8f4b7d8e004c05a44d6f8444c6", - "action": "add" - } - }, - "DataSubject": { - "1": { - "version": 1, - "hash": "0b8b049d4627727b444c419f5d6a97b7cb97a433088ebf744c854b6a470dadf1", - "action": "add" - } - }, - "DataSubjectCreate": { - "1": { - "version": 1, - "hash": "5a94f9fcba75c50d78d71222f0235c5fd4d8003ae0db4d74bdbc4d56a99de3aa", - "action": "add" - } - }, - "DataSubjectMemberRelationship": { - "1": { - "version": 1, - "hash": "0a820edc9f1a87387acc3c611fe852752fcb3dab7608058f2bc48211be7bfbd2", - "action": "add" - } - }, - "Contributor": { - "1": { - "version": 1, - "hash": "d1d4f25bb87e59c0414501d3335097de66815c164c9ed5a7850ff8bec69fbcdc", - "action": "add" - } - }, - "MarkdownDescription": { - "1": { - "version": 1, - "hash": "519328a3952049f57004013e4fb00840695b24b8575cad983056412c9c9d9ba6", - "action": "add" - } - }, - "Asset": { - "1": { - "version": 1, - "hash": "24350b8d9597df49999918ad42e0eece1328ea30389311f1e0a420be8f39b8a1", - "action": "add" - } - }, - "CreateAsset": { - "1": { - "version": 1, - "hash": "1b4c71569b8da64258672483bd36dc4aa99a32d4cb519659241d15bc898041a6", - "action": "add" - } - }, - "Dataset": { - "1": { - "version": 1, - "hash": "99ca2fa3e46fd9810222d269fac6accb546f632e94d5d57529016ba5e55af5a8", - "action": "add" - } - }, - "DatasetPageView": { - "1": { - "version": 1, - "hash": "b1de14bb9b6a259648dfc59b6a48fa526116afe50a689c24b8bb36fd0e6a97f8", - "action": "add" - } - }, - "CreateDataset": { - "1": { - "version": 1, - "hash": "3b020d9b8928cbd7e91f41c749ab4c932e19520696a183f2c7cd1312ebb640d1", - "action": "add" - } - }, - "ActionDataEmpty": { - "1": { - "version": 1, - "hash": "89b5912fe5416f922051b8068be6071a03c87a4ab264959de524f1b86e95f028", - "action": "add" - } - }, - "ActionFileData": { - "1": { - "version": 1, - "hash": "1f32d94b75b0a6b4e86cec93d94aa905738219e3e7e75f51dd335ee832a6ed3e", - "action": "add" - } - }, - "Action": { - "1": { - "version": 1, - "hash": "5cf71ee35097f17fbb1dd05096f875211d71cf07161205d7f6a9c11fd49d5272", - "action": "add" - } - }, - "ActionObject": { - "1": { - "version": 1, - "hash": "632446f1415102490c93fafb56dd9eb29d79623bcc5e9f2e6e37c4f63c2c51c3", - "action": "add" - } - }, - "AnyActionObject": { - "1": { - "version": 1, - "hash": "bcb31f847907edc9c95d2d120dc5427854604f40940e3f41cd0474a1820ac65e", - "action": "add" - } - }, - "TwinObject": { - "1": { - "version": 1, - "hash": "c42455586b43724a7421becd99122b787a129798daf6081e96954ecaea228099", - "action": "add" - } - }, - "ExactMatch": { - "1": { - "version": 1, - "hash": "e497e2e2380db72766c5e219e8afd13136d8953933d6f1eaf83b14001e887cde", - "action": "add" - } - }, - "OutputHistory": { - "1": { - "version": 1, - "hash": "4ec6e6efd86a972b474251885151bdfe4ef262562174605e8ab6a8abba1aa867", - "action": "add" - } - }, - "OutputPolicyExecuteCount": { - "1": { - "version": 1, - "hash": "6bb24b3b35e19564c43b838ca3f46ccdeadb6596511917f2d220681a378e439d", - "action": "add" - } - }, - "OutputPolicyExecuteOnce": { - "1": { - "version": 1, - "hash": "32a40fc9966b277528eebc61c01041f3a5447417731954abdaffbb14dabc76bb", - "action": "add" - } - }, - "UserPolicy": { - "1": { - "version": 1, - "hash": "c69b17b1d96cace8b45da6d9639165f2da4aa7ff156b6fd922ac217bf7856d8a", - "action": "add" - } - }, - "SubmitUserPolicy": { - "1": { - "version": 1, - "hash": "96f7f39279fadc70c569b8d48ed4d6420a8132db51e37466d272fda19953554b", - "action": "add" - } - }, - "UserCode": { - "1": { - "version": 1, - "hash": "e14c22686cdc7d1fb2b0d01c0aebdea37e62a61b051677c1d30234214f05cd42", - "action": "add" - } - }, - "SubmitUserCode": { - "1": { - "version": 1, - "hash": "f572d32350d09e25b29572c591029d37a216818618c383094404f84bc9c15dd6", - "action": "add" - } - }, - "UserCodeExecutionResult": { - "1": { - "version": 1, - "hash": "49c32e85e78b7b189a7f13b7e26115ef94fcb0b60b578adcbe2b95e289f63a6e", - "action": "add" - } - }, - "CodeHistory": { - "1": { - "version": 1, - "hash": "a7baae93862ae0aa67675f1617574e31aafb15a9ebff633eb817278a3a867161", - "action": "add" - } - }, - "CodeHistoryView": { - "1": { - "version": 1, - "hash": "0ed1a2a04a962ecbcfa38b0b8a03c1e51e8946a4b80f6bf2557148ce658671ce", - "action": "add" - } - }, - "CodeHistoriesDict": { - "1": { - "version": 1, - "hash": "95288411cd5843834f3273a2fd66a7df2e603e980f4ab1d329f9ab17d5d2f643", - "action": "add" - } - }, - "UsersCodeHistoriesDict": { - "1": { - "version": 1, - "hash": "5e1f389c4565ee8558386dd5c934d81e0c68ab1434f86bb9065976b587ef44d1", - "action": "add" - } - }, - "NodePeer": { - "1": { - "version": 1, - "hash": "7b88de7e38490e2d69f31295137673e7ddabc16ab0e2272ff491f6cea1835d63", - "action": "add" - } - }, - "OnDiskBlobDeposit": { - "1": { - "version": 1, - "hash": "5efc230c1ee65c4626d334aa69ed458c796c45265e546a333844c6c2bcd0e6b0", - "action": "add" - } - }, - "SeaweedFSBlobDeposit": { - "1": { - "version": 1, - "hash": "382a9ac178deed2a9591e1ebbb39f265cbe67027fb93a420d473a4c26b7fda11", - "action": "add" - } - }, - "DictStoreConfig": { - "1": { - "version": 1, - "hash": "256e9c623ce0becd555ddd2a55a0c15514e162786b1549388cef98a92a9b18c9", - "action": "add" - } - }, - "NumpyArrayObject": { - "1": { - "version": 1, - "hash": "dcc7b44fa5ad22ae0bc576948f856c172dac1e9de2bc8e2a302e428f3309a278", - "action": "add" - } - }, - "NumpyScalarObject": { - "1": { - "version": 1, - "hash": "5c1b6b6e8ba88bc79e76646d621489b889fe8f9b9fd59f117d594be18a409633", - "action": "add" - } - }, - "NumpyBoolObject": { - "1": { - "version": 1, - "hash": "a5c822a6a3ca9eefd6a2b68f7fd0bc614fba7995f6bcc30bdc9dc882296b9b16", - "action": "add" - } - }, - "PandasDataframeObject": { - "1": { - "version": 1, - "hash": "35058924b3de2e0a604a92f91f4dd2e3cc0dac80c219d34f360e7cedd52f5f4c", - "action": "add" - } - }, - "PandasSeriesObject": { - "1": { - "version": 1, - "hash": "2a0d8a55f1c27bd8fccd276cbe01bf272c40cab10417d7027273983fed423caa", - "action": "add" - } - }, - "ReplyNotification": { - "1": { - "version": 1, - "hash": "34b2ad522f7406c2486573467d9c7acef5c1063a0d9f2177c3bda2d8c4f87572", - "action": "add" - } - }, - "Notification": { - "1": { - "version": 1, - "hash": "d13981f721fe2b3e2717640ee07dc716c596e4ecd442461665c3fdab0b85bf0e", - "action": "add" - } - }, - "CreateNotification": { - "1": { - "version": 1, - "hash": "b1f459de374fe674f873a4a5f3fb8a8aabe0d83faad84a933f0a77dd1141159a", - "action": "add" - } - }, - "Change": { - "1": { - "version": 1, - "hash": "aefebd1601cf5bfd4817b0db75300a78299cc4949ead735a90873cbd22c8d4bc", - "action": "add" - } - }, - "ChangeStatus": { - "1": { - "version": 1, - "hash": "627f6f8e42cc285336aa6fd4916285d796140f4ff901487b7cb3907ef0f116a6", - "action": "add" - } - }, - "ActionStoreChange": { - "1": { - "version": 1, - "hash": "17b865e75eb3fb2693924fb00ba87a25260be45d55a4eb2184c4ead22d787cbe", - "action": "add" - } - }, - "Request": { - "1": { - "version": 1, - "hash": "e054307eeb7f13683cde9ce7613d5ca2925a13fff7c345b1c9f729a12c955f90", - "action": "add" - } - }, - "RequestInfo": { - "1": { - "version": 1, - "hash": "b76075c138afc0563ce9ac7f6b1131f048951f7486cd516c02736dc1a2a23639", - "action": "add" - } - }, - "RequestInfoFilter": { - "1": { - "version": 1, - "hash": "7103abdc464ae71bb746410f5730f55dd8ed82268aa32bbb0a69e0070488a669", - "action": "add" - } - }, - "SubmitRequest": { - "1": { - "version": 1, - "hash": "96b4ec12beafd9d8a7c97399cb8a23dade4db16d8f521be3fe7b8fec99db5161", - "action": "add" - } - }, - "ObjectMutation": { - "1": { - "version": 1, - "hash": "0ee3dd38d6df0fe9a19d848e8f3aaaf13a6ba86afe3406c239caed6da185651a", - "action": "add" - } - }, - "EnumMutation": { - "1": { - "version": 1, - "hash": "4c02f956ec9b973064972cc57fc8dd9c525e683f93f804642b4e1bfee1b62e57", - "action": "add" - } - }, - "UserCodeStatusChange": { - "1": { - "version": 1, - "hash": "4f5b405cc2b3976ed8f7018df82e873435d9187dff15fa5a23bc85a738969f3f", - "action": "add" - } - }, - "SyftObjectMigrationState": { - "1": { - "version": 1, - "hash": "d3c8126bc15dae4dd243bb035530e3f56cd9e433d403dd6b5f3b45face6d281f", - "action": "add" - } - }, - "ProjectThreadMessage": { - "1": { - "version": 1, - "hash": "1118e935792e8e54103dbf91fa33edbf192a7767d2b1d4526dfa7d4a643cde2e", - "action": "add" - } - }, - "ProjectMessage": { - "1": { - "version": 1, - "hash": "55a3a5171b6949372b4125cc461bf39bc998565e07703804fca6c7ef99695ae4", - "action": "add" - } - }, - "ProjectRequestResponse": { - "1": { - "version": 1, - "hash": "d4c360e845697a0b24695143d0781626cd344cfde43162c90ae90fe67e00ae21", - "action": "add" - } - }, - "ProjectRequest": { - "1": { - "version": 1, - "hash": "514d189df335c68869eea36befcdcafec74bdc682eaf18871fe879e26da4dbb6", - "action": "add" - } - }, - "AnswerProjectPoll": { - "1": { - "version": 1, - "hash": "ff2e1ac7bb764c99d646b96eb3ebfbf9311599b7e3be07aa4a4eb4810bb6dd12", - "action": "add" - } - }, - "ProjectPoll": { - "1": { - "version": 1, - "hash": "b0ac8f1d9c06997374ddbc33fdf1d0af0da15fdb6899f52d91a8574106558964", - "action": "add" - } - }, - "Project": { - "1": { - "version": 1, - "hash": "ec5b7ac1c92808e266f06b175c6ebcd50be81777ad120c02ce8c6074d0004788", - "action": "add" - } - }, - "ProjectSubmit": { - "1": { - "version": 1, - "hash": "0374b37779497d7e0b2ffeabc38d35bfbae2ee762a7674a5a8af75e7c5545e61", - "action": "add" - } - }, - "QueueItem": { - "1": { - "version": 1, - "hash": "5aa94681d9d0715d5b605f9625a54e114927271378cf2ea7245f85c488035e0b", - "action": "add" - } - }, - "ZMQClientConfig": { - "1": { - "version": 1, - "hash": "e6054969b495791569caaf33239039beae3d116e1fe74e9575467c48b9007c45", - "action": "add" - } - }, - "SQLiteStoreConfig": { - "1": { - "version": 1, - "hash": "b656b26c14cf4e97aba702dd62a0927aec7f860c12eed512c2c688e1b7109aa5", - "action": "add" - } - }, - "Plan": { - "1": { - "version": 1, - "hash": "a0bba2b7792c9e08c453e9e256f0ac6e6185610726566bcd50b057ae83b42d9a", - "action": "add" - } - } - } - } -} diff --git a/packages/syft/src/syft/protocol/releases/0.8.3.json b/packages/syft/src/syft/protocol/releases/0.8.3.json deleted file mode 100644 index 0c74b349c3f..00000000000 --- a/packages/syft/src/syft/protocol/releases/0.8.3.json +++ /dev/null @@ -1,194 +0,0 @@ -{ - "2": { - "object_versions": { - "Action": { - "2": { - "version": 2, - "hash": "a13b50c4d23bd6deb7896e394f2a20e6cef4c33c5e6f4ee30f19eaffab708f21", - "action": "add" - } - }, - "ActionObject": { - "2": { - "version": 2, - "hash": "577aa1f010b90194958a18ec38ee21db3718bd96d9e036501c6ddeefabedf432", - "action": "add" - } - }, - "AnyActionObject": { - "2": { - "version": 2, - "hash": "002d8be821140befebbc0503e6bc1ef8779094e24e46305e5da5af6eecb56b13", - "action": "add" - } - }, - "BlobFile": { - "2": { - "version": 2, - "hash": "f2b29d28fe81a04bf5e946c819010283a9f98a97d50519358bead773865a2e09", - "action": "add" - } - }, - "BlobFileOBject": { - "1": { - "version": 1, - "hash": "8da2c80ced4f0414c671313c4b63d05846df1e397c763d99d803be86c29755bb", - "action": "add" - } - }, - "BlobStorageEntry": { - "2": { - "version": 2, - "hash": "5472bdd5bdce6d0b561543a6bac70d47bf0c05c141a21450751460cc538d6b55", - "action": "add" - } - }, - "BlobStorageMetadata": { - "2": { - "version": 2, - "hash": "674f4c52a8444289d5ef389b919008860e2b0e7acbaafa774d58e492d5b6741a", - "action": "add" - } - }, - "BlobRetrieval": { - "2": { - "version": 2, - "hash": "4c4fbdb6df5bb9fcbe914a9890bd1c1b6a1b3f382a04cbc8752a5a1b03130111", - "action": "add" - } - }, - "SyftObjectRetrieval": { - "2": { - "version": 2, - "hash": "d9d7a7e1b8843145c9687fd013c9223700285886073547734267e91ac53e0996", - "action": "add" - } - }, - "BlobRetrievalByURL": { - "1": { - "version": 1, - "hash": "18fd860cb9de296532fc9ff075932e6a4377cc8f043dd88ed4f620517321077d", - "action": "remove" - }, - "2": { - "version": 2, - "hash": "8059ee03016c4d74e408dad9529e877f91829672e0cc42d8cfff9c8e14058adc", - "action": "add" - } - }, - "WorkerSettings": { - "2": { - "version": 2, - "hash": "d623a8a0d6c83b26ba49686bd8be10eccb126f54626fef334a85396c3b8a8ed6", - "action": "add" - } - }, - "QueueItem": { - "2": { - "version": 2, - "hash": "9503b878de4b5b7a1793580301353523b7d6219ebd27d38abe598061979b7570", - "action": "add" - } - }, - "ActionQueueItem": { - "1": { - "version": 1, - "hash": "11a43caf9164eb2a5a21f4bcb0ca361d0a5d134bf3c60173f2c502d0d80219de", - "action": "add" - } - }, - "ZMQClientConfig": { - "2": { - "version": 2, - "hash": "0f9bc88d56cd6eed6fc75459d1f914aed840c66e1195b9e41cc501b488fef2ed", - "action": "add" - } - }, - "JobItem": { - "1": { - "version": 1, - "hash": "7b8723861837b0b7e948b2cf9244159d232185f3407dd6bef108346f941ddf6e", - "action": "add" - }, - "2": { - "version": 2, - "hash": "e99cf5a78c6dd3a0adc37af3472c7c21570a9e747985dff540a2b06d24de6446", - "action": "add" - } - }, - "UserCode": { - "2": { - "version": 2, - "hash": "660e1abc15034f525e91ffdd820c2a2179bfddf83b7b9e3ce7823b2efc515c69", - "action": "add" - } - }, - "SubmitUserCode": { - "1": { - "version": 1, - "hash": "f572d32350d09e25b29572c591029d37a216818618c383094404f84bc9c15dd6", - "action": "remove" - }, - "2": { - "version": 2, - "hash": "9b29e060973a3de8d3564a2b7d2bb5c53745aa445bf257576994b613505d7194", - "action": "add" - } - }, - "NumpyArrayObject": { - "2": { - "version": 2, - "hash": "2c631121d9211006edab5620b214dea83e2398bee92244d822227ee316647e22", - "action": "add" - } - }, - "NumpyScalarObject": { - "2": { - "version": 2, - "hash": "0d5d81b9d45c140f6e07b43ed68d31e0ef060d6b4d0431c9b4795997bb35c69d", - "action": "add" - } - }, - "NumpyBoolObject": { - "2": { - "version": 2, - "hash": "24839ba1c88ed833a134124750d5f299abcdf318670315028ed87b254f4578b3", - "action": "add" - } - }, - "PandasDataframeObject": { - "2": { - "version": 2, - "hash": "66729d4ba7a92210d45c5a5c24fbdb4c8e58138a515a7bdb71ac8f6e8b868544", - "action": "add" - } - }, - "PandasSeriesObject": { - "2": { - "version": 2, - "hash": "cb05a714f75b1140a943f56a3622fcc0477b3a1f504cd545a98510959ffe1528", - "action": "add" - } - }, - "UserCodeStatusChange": { - "2": { - "version": 2, - "hash": "d83e0905ae882c824ba8fbbf455cd3881906bf8b2ebbfff07bcf471ef869cedc", - "action": "add" - } - }, - "SyftLog": { - "1": { - "version": 1, - "hash": "bd3f62b8fe4b2718a6380c8f05a93c5c40169fc4ab174db291929298e588429e", - "action": "add" - }, - "2": { - "version": 2, - "hash": "d3ce45794da2e6c4b0cef63b98a553525af50c5d9db42d3d64caef3e7d22b4a9", - "action": "add" - } - } - } - } -} diff --git a/packages/syft/src/syft/protocol/releases/0.8.4.json b/packages/syft/src/syft/protocol/releases/0.8.4.json deleted file mode 100644 index b1581fef20b..00000000000 --- a/packages/syft/src/syft/protocol/releases/0.8.4.json +++ /dev/null @@ -1,242 +0,0 @@ -{ - "3": { - "object_versions": { - "SyftWorkerImage": { - "1": { - "version": 1, - "hash": "2a9585b6a286e24f1a9f3f943d0128730cf853edc549184dc1809d19e1eec54b", - "action": "add" - } - }, - "ActionDataLink": { - "1": { - "version": 1, - "hash": "10bf94e99637695f1ba283f0b10e70743a4ebcb9ee75aefb1a05e6d6e1d21a71", - "action": "add" - } - }, - "ObjectNotReady": { - "1": { - "version": 1, - "hash": "88207988639b11eaca686b6e079616d9caecc3dbc2a8112258e0f39ee5c3e113", - "action": "add" - } - }, - "JobItem": { - "3": { - "version": 3, - "hash": "5b93a59e28574691339d22826d5650969336a2e930b93d6b3fe6d5409ca0cfc4", - "action": "add" - } - }, - "SeaweedSecureFilePathLocation": { - "2": { - "version": 2, - "hash": "5fd63fed2a4efba8c2b6c7a7b5e9b5939181781c331230896aa130b6fd558739", - "action": "add" - } - }, - "AzureSecureFilePathLocation": { - "1": { - "version": 1, - "hash": "1bb15f3f9d7082779f1c9f58de94011487924cb8a8c9c2ec18fd7c161c27fd0e", - "action": "add" - } - }, - "RemoteConfig": { - "1": { - "version": 1, - "hash": "ad7bc4780a8ad52e14ce68601852c93d2fe07bda489809cad7cae786d2461754", - "action": "add" - } - }, - "AzureRemoteConfig": { - "1": { - "version": 1, - "hash": "c05c6caa27db4e385c642536d4b0ecabc0c71e91220d2e6ce21a2761ca68a673", - "action": "add" - } - }, - "BlobRetrievalByURL": { - "2": { - "version": 2, - "hash": "8059ee03016c4d74e408dad9529e877f91829672e0cc42d8cfff9c8e14058adc", - "action": "remove" - }, - "3": { - "version": 3, - "hash": "0b664100ea08413ca4ef04665ca910c2cf9535539617ea4ba33687d05cdfe747", - "action": "add" - } - }, - "QueueItem": { - "3": { - "version": 3, - "hash": "3495f406d2c97050ce86be80c230f49b6b846c63b9a9230cbd6631952f2bad0f", - "action": "add" - } - }, - "ActionQueueItem": { - "2": { - "version": 2, - "hash": "6413ed01e949cac169299a43ce40651f9bf8053e408b6942853f8afa8a693b3d", - "action": "add" - } - }, - "ZMQClientConfig": { - "2": { - "version": 2, - "hash": "0f9bc88d56cd6eed6fc75459d1f914aed840c66e1195b9e41cc501b488fef2ed", - "action": "remove" - }, - "3": { - "version": 3, - "hash": "91ce5953cced58e12c576aa5174d5ca0c91981b01cf42edd5283d347baa3390b", - "action": "add" - } - }, - "SyftWorker": { - "1": { - "version": 1, - "hash": "0d5b367162f3ce55ab090cc1b49bd30e50d4eb144e8431eadc679bd0e743aa70", - "action": "add" - } - }, - "WorkerPool": { - "1": { - "version": 1, - "hash": "250699eb4c452fc427995353d5c5ad6245fb3e9fdac8814f8348784816a0733b", - "action": "add" - } - }, - "SyftImageRegistry": { - "1": { - "version": 1, - "hash": "dc83910c91947e3d9eaa3e6f8592237448f0408668c7cca80450b5fcd54722e1", - "action": "add" - } - }, - "UserCode": { - "3": { - "version": 3, - "hash": "90fcae0f556f375ba1e91d2e345f57241660695c6e2b84c8e311df89d09e6c66", - "action": "add" - } - }, - "SubmitUserCode": { - "3": { - "version": 3, - "hash": "a29160c16d2e2620800d42cdcd9f3637d063a570c477a5d05217a2e64b4bb396", - "action": "add" - } - }, - "CreateCustomImageChange": { - "1": { - "version": 1, - "hash": "bc09dca7995938f3b3a2bd9c8b3c2feffc8484df466144a425cb69cadb2ab635", - "action": "add" - } - }, - "CreateCustomWorkerPoolChange": { - "1": { - "version": 1, - "hash": "86894f8ccc037de61f44f9698fd113ba02c3cf3870a3048c00a46e15dcd1941c", - "action": "add" - } - }, - "JobInfo": { - "1": { - "version": 1, - "hash": "cf26eeac3d9254dfa439917493b816341f8a379a77d182bbecba3b7ed2c1d00a", - "action": "add" - } - }, - "User": { - "1": { - "version": 1, - "hash": "078636e64f737e60245b39cf348d30fb006531e80c12b70aa7cf98254e1bb37a", - "action": "remove" - }, - "2": { - "version": 2, - "hash": "ded970c92f202716ed33a2117cf541789f35fad66bd4b1db39da5026b1d7d0e7", - "action": "add" - } - }, - "UserUpdate": { - "1": { - "version": 1, - "hash": "839dd90aeb611e1dc471c8fd6daf230e913465c0625c6a297079cb7f0a271195", - "action": "remove" - }, - "2": { - "version": 2, - "hash": "32cba8fbd786c575f92e26c31384d282e68e3ebfe5c4b0a0e793820b1228d246", - "action": "add" - } - }, - "UserCreate": { - "1": { - "version": 1, - "hash": "dab78b63544ae91c09f9843c323cb237c0a6fcfeb71c1acf5f738e2fcf5c277f", - "action": "remove" - }, - "2": { - "version": 2, - "hash": "2540188c5aaea866914dccff459df6e0f4727108a503414bb1567ff6297d4646", - "action": "add" - } - }, - "UserView": { - "1": { - "version": 1, - "hash": "63289383fe7e7584652f242a4362ce6e2f0ade52f6416ab6149b326a506b0675", - "action": "remove" - }, - "2": { - "version": 2, - "hash": "e410de583bb15bc5af57acef7be55ea5fc56b5b0fc169daa3869f4203c4d7473", - "action": "add" - } - }, - "BlobFile": { - "2": { - "version": 2, - "hash": "f2b29d28fe81a04bf5e946c819010283a9f98a97d50519358bead773865a2e09", - "action": "remove" - }, - "3": { - "version": 3, - "hash": "8f1710c754bb3b39f546b97fd69c4826291398b247976bbc41fa873af431bca9", - "action": "add" - } - }, - "SyftObjectRetrieval": { - "1": { - "version": 1, - "hash": "7ccc62d5b434d2d438b3df661b4d753b0c7c8d593d451d8b86d364da83998c89", - "action": "remove" - }, - "3": { - "version": 3, - "hash": "952958e9afae007bef3cb89aa15be95dddc4c310e3a8ce4191576f90ac6fcbc8", - "action": "add" - } - }, - "ActionFileData": { - "1": { - "version": 1, - "hash": "1f32d94b75b0a6b4e86cec93d94aa905738219e3e7e75f51dd335ee832a6ed3e", - "action": "remove" - } - }, - "SeaweedFSBlobDeposit": { - "2": { - "version": 2, - "hash": "07d84a95324d95d9c868cd7d1c33c908f77aa468671d76c144586aab672bcbb5", - "action": "add" - } - } - } - } -} diff --git a/packages/syft/src/syft/serde/recursive.py b/packages/syft/src/syft/serde/recursive.py index eeb1236b749..9efd64e02c0 100644 --- a/packages/syft/src/syft/serde/recursive.py +++ b/packages/syft/src/syft/serde/recursive.py @@ -111,9 +111,14 @@ def recursive_serde_register( # if pydantic object and attrs are provided, the get attrs from __fields__ # cls.__fields__ auto inherits attrs pydantic_fields = [ - f.name - for f in cls.__fields__.values() - if f.outer_type_ not in (Callable, types.FunctionType, types.LambdaType) + field + for field, field_info in cls.model_fields.items() + if not ( + field_info.annotation is not None + and hasattr(field_info.annotation, "__origin__") + and field_info.annotation.__origin__ + in (Callable, types.FunctionType, types.LambdaType) + ) ] attribute_list.update(pydantic_fields) @@ -125,7 +130,9 @@ def recursive_serde_register( attribute_list.update(["value"]) exclude_attrs = [] if exclude_attrs is None else exclude_attrs - attribute_list = attribute_list - set(exclude_attrs) + attribute_list = ( + attribute_list - set(exclude_attrs) - {"syft_pre_hooks__", "syft_post_hooks__"} + ) if inheritable_attrs and attribute_list and not is_pydantic: # only set __syft_serializable__ for non-pydantic classes because diff --git a/packages/syft/src/syft/serde/third_party.py b/packages/syft/src/syft/serde/third_party.py index 2d70250cbe6..fddbb5ae755 100644 --- a/packages/syft/src/syft/serde/third_party.py +++ b/packages/syft/src/syft/serde/third_party.py @@ -20,6 +20,7 @@ import pyarrow as pa import pyarrow.parquet as pq import pydantic +from pydantic._internal._model_construction import ModelMetaclass from pymongo.collection import Collection from result import Err from result import Ok @@ -29,6 +30,8 @@ # relative from ..types.dicttuple import DictTuple from ..types.dicttuple import _Meta as _DictTupleMetaClass +from ..types.syft_metaclass import EmptyType +from ..types.syft_metaclass import PartialModelMetaclass from .deserialize import _deserialize as deserialize from .recursive_primitives import _serialize_kv_pairs from .recursive_primitives import deserialize_kv @@ -54,8 +57,6 @@ # result Ok and Err recursive_serde_register(Ok, serialize_attrs=["_value"]) recursive_serde_register(Err, serialize_attrs=["_value"]) - -recursive_serde_register_type(pydantic.main.ModelMetaclass) recursive_serde_register(Result) # exceptions @@ -148,6 +149,17 @@ def _serialize_dicttuple(x: DictTuple) -> bytes: ) +recursive_serde_register( + EmptyType, + serialize=serialize_type, + deserialize=deserialize_type, +) + + +recursive_serde_register_type(ModelMetaclass) +recursive_serde_register_type(PartialModelMetaclass) + + def serialize_bytes_io(io: BytesIO) -> bytes: io.seek(0) return serialize(io.read(), to_bytes=True) @@ -180,9 +192,9 @@ def serialize_bytes_io(io: BytesIO) -> bytes: recursive_serde_register(np.core._ufunc_config._unspecified()) recursive_serde_register( - pydantic.networks.EmailStr, + pydantic.EmailStr, serialize=lambda x: x.encode(), - deserialize=lambda x: pydantic.networks.EmailStr(x.decode()), + deserialize=lambda x: pydantic.EmailStr(x.decode()), ) recursive_serde_register( diff --git a/packages/syft/src/syft/service/action/action_data_empty.py b/packages/syft/src/syft/service/action/action_data_empty.py index e32f4e339bb..c8f0e143e3d 100644 --- a/packages/syft/src/syft/service/action/action_data_empty.py +++ b/packages/syft/src/syft/service/action/action_data_empty.py @@ -2,6 +2,7 @@ from __future__ import annotations # stdlib +import sys from typing import Optional from typing import Type @@ -11,7 +12,11 @@ from ...types.syft_object import SyftObject from ...types.uid import UID -NoneType = type(None) +if sys.version_info >= (3, 10): + # stdlib + from types import NoneType +else: + NoneType = type(None) @serializable() diff --git a/packages/syft/src/syft/service/action/action_graph.py b/packages/syft/src/syft/service/action/action_graph.py index edb3fabe548..26b633a8ae1 100644 --- a/packages/syft/src/syft/service/action/action_graph.py +++ b/packages/syft/src/syft/service/action/action_graph.py @@ -15,9 +15,8 @@ # third party import matplotlib.pyplot as plt import networkx as nx -import pydantic from pydantic import Field -from pydantic import validator +from pydantic import field_validator from result import Err from result import Ok from result import Result @@ -62,21 +61,17 @@ class NodeActionData(SyftObject): __canonical_name__ = "NodeActionData" __version__ = SYFT_OBJECT_VERSION_1 - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] type: NodeType status: ExecutionStatus = ExecutionStatus.PROCESSING retry: int = 0 - created_at: Optional[DateTime] - updated_at: Optional[DateTime] + created_at: DateTime = Field(default_factory=DateTime.now) + updated_at: DateTime = Field(default_factory=DateTime.now) user_verify_key: SyftVerifyKey is_mutated: bool = False # denotes that this node has been mutated is_mutagen: bool = False # denotes that this node is causing a mutation - next_mutagen_node: Optional[UID] # next neighboring mutagen node - last_nm_mutagen_node: Optional[UID] # last non mutated mutagen node - - @pydantic.validator("created_at", pre=True, always=True) - def make_created_at(cls, v: Optional[DateTime]) -> DateTime: - return DateTime.now() if v is None else v + next_mutagen_node: Optional[UID] = None # next neighboring mutagen node + last_nm_mutagen_node: Optional[UID] = None # last non mutated mutagen node @classmethod def from_action(cls, action: Action, credentials: SyftVerifyKey) -> Self: @@ -124,17 +119,13 @@ class NodeActionDataUpdate(PartialSyftObject): status: ExecutionStatus retry: int created_at: DateTime - updated_at: Optional[DateTime] + updated_at: DateTime = Field(default_factory=DateTime.now) credentials: SyftVerifyKey is_mutated: bool is_mutagen: bool next_mutagen_node: UID # next neighboring mutagen node last_nm_mutagen_node: UID # last non mutated mutagen node - @pydantic.validator("updated_at", pre=True, always=True) - def set_updated_at(cls, v: Optional[DateTime]) -> DateTime: - return DateTime.now() if v is None else v - @serializable() class BaseGraphStore: @@ -197,7 +188,8 @@ class InMemoryStoreClientConfig(StoreClientConfig): # We need this in addition to Field(default_factory=...) # so users can still do InMemoryStoreClientConfig(path=None) - @validator("path", pre=True) + @field_validator("path", mode="before") + @classmethod def __default_path(cls, path: Optional[Union[str, Path]]) -> Union[str, Path]: if path is None: return tempfile.gettempdir() diff --git a/packages/syft/src/syft/service/action/action_graph_service.py b/packages/syft/src/syft/service/action/action_graph_service.py index 6e06a9c84a0..886669f7deb 100644 --- a/packages/syft/src/syft/service/action/action_graph_service.py +++ b/packages/syft/src/syft/service/action/action_graph_service.py @@ -4,7 +4,7 @@ from typing import Union # third party -from pydantic.error_wrappers import ValidationError +from pydantic import ValidationError # relative from ...node.credentials import SyftVerifyKey @@ -118,10 +118,7 @@ def _extract_input_and_output_from_action( for _, kwarg in action.kwargs.items(): input_uids.add(kwarg.id) - if action.result_id is not None: - output_uid = action.result_id.id - else: - output_uid = None + output_uid = action.result_id.id if action.result_id is not None else None return input_uids, output_uid diff --git a/packages/syft/src/syft/service/action/action_object.py b/packages/syft/src/syft/service/action/action_object.py index b474ebd5128..d9c2340b2a6 100644 --- a/packages/syft/src/syft/service/action/action_object.py +++ b/packages/syft/src/syft/service/action/action_object.py @@ -22,7 +22,10 @@ from typing import cast # third party -import pydantic +from pydantic import ConfigDict +from pydantic import Field +from pydantic import field_validator +from pydantic import model_validator from result import Err from result import Ok from result import Result @@ -114,11 +117,11 @@ class ActionV1(SyftObject): path: str op: str - remote_self: Optional[LineageID] + remote_self: Optional[LineageID] = None args: List[LineageID] kwargs: Dict[str, LineageID] - result_id: Optional[LineageID] - action_type: Optional[ActionType] + result_id: Optional[LineageID] = None + action_type: Optional[ActionType] = None create_object: Optional[SyftObject] = None @@ -146,24 +149,19 @@ class Action(SyftObject): __attr_searchable__: ClassVar[List[str]] = [] - path: Optional[str] - op: Optional[str] - remote_self: Optional[LineageID] + path: Optional[str] = None + op: Optional[str] = None + remote_self: Optional[LineageID] = None args: List[LineageID] kwargs: Dict[str, LineageID] - result_id: Optional[LineageID] - action_type: Optional[ActionType] + result_id: LineageID = Field(default_factory=lambda: LineageID(UID())) + action_type: Optional[ActionType] = None create_object: Optional[SyftObject] = None user_code_id: Optional[UID] = None - @pydantic.validator("id", pre=True, always=True) - def make_id(cls, v: Optional[UID]) -> UID: - """Generate or reuse an UID""" - return v if isinstance(v, UID) else UID() - - @pydantic.validator("result_id", pre=True, always=True) - def make_result_id(cls, v: Optional[Union[UID, LineageID]]) -> UID: - """Generate or reuse a LineageID""" + @field_validator("result_id", mode="before") + @classmethod + def make_result_id(cls, v: Any) -> LineageID: return v if isinstance(v, LineageID) else LineageID(v) @property @@ -316,8 +314,41 @@ class ActionObjectPointer: "__include_fields__", # pydantic "_calculate_keys", # pydantic "_get_value", # pydantic - "__sha256__", - "__hash_exclude_attrs__", + "__pydantic_validator__", # pydantic + "__class_vars__", # pydantic + "__private_attributes__", # pydantic + "__signature__", # pydantic + "__pydantic_complete__", # pydantic + "__pydantic_core_schema__", # pydantic + "__pydantic_custom_init__", # pydantic + "__pydantic_decorators__", # pydantic + "__pydantic_generic_metadata__", # pydantic + "__pydantic_parent_namespace__", # pydantic + "__pydantic_post_init__", # pydantic + "__pydantic_root_model__", # pydantic + "__pydantic_serializer__", # pydantic + "__pydantic_validator__", # pydantic + "__pydantic_extra__", # pydantic + "__pydantic_fields_set__", # pydantic + "__pydantic_private__", # pydantic + "model_config", # pydantic + "model_computed_fields", # pydantic + "model_extra", # pydantic + "model_fields", # pydantic + "model_fields_set", # pydantic + "model_construct", # pydantic + "model_copy", # pydantic + "model_dump", # pydantic + "model_dump_json", # pydantic + "model_json_schema", # pydantic + "model_parametrized_name", # pydantic + "model_post_init", # pydantic + "model_rebuild", # pydantic + "model_validate", # pydantic + "model_validate_json", # pydantic + "copy", # pydantic + "__sha256__", # syft + "__hash_exclude_attrs__", # syft ] dont_wrap_output_attrs = [ "__repr__", @@ -376,13 +407,13 @@ class PreHookContext(SyftBaseObject): The action generated by the current hook """ - obj: Any + obj: Any = None op_name: str - node_uid: Optional[UID] - result_id: Optional[Union[UID, LineageID]] - result_twin_type: Optional[TwinMode] - action: Optional[Action] - action_type: Optional[ActionType] + node_uid: Optional[UID] = None + result_id: Optional[Union[UID, LineageID]] = None + result_twin_type: Optional[TwinMode] = None + action: Optional[Action] = None + action_type: Optional[ActionType] = None def make_action_side_effect( @@ -599,6 +630,7 @@ def debox_args_and_kwargs(args: Any, kwargs: Any) -> Tuple[Any, Any]: "node_uid", "__sha256__", "__hash_exclude_attrs__", + "__hash__", ] @@ -615,23 +647,23 @@ class ActionObjectV1(SyftObject): syft_pointer_type: ClassVar[Type[ActionObjectPointer]] # Help with calculating history hash for code verification - syft_parent_hashes: Optional[Union[int, List[int]]] - syft_parent_op: Optional[str] - syft_parent_args: Optional[Any] - syft_parent_kwargs: Optional[Any] - syft_history_hash: Optional[int] + syft_parent_hashes: Optional[Union[int, List[int]]] = None + syft_parent_op: Optional[str] = None + syft_parent_args: Optional[Any] = None + syft_parent_kwargs: Optional[Any] = None + syft_history_hash: Optional[int] = None syft_internal_type: ClassVar[Type[Any]] - syft_node_uid: Optional[UID] - _syft_pre_hooks__: Dict[str, List] = {} - _syft_post_hooks__: Dict[str, List] = {} + syft_node_uid: Optional[UID] = None + syft_pre_hooks__: Dict[str, List] = {} + syft_post_hooks__: Dict[str, List] = {} syft_twin_type: TwinMode = TwinMode.NONE - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_action_data_type: Optional[Type] - syft_action_data_repr_: Optional[str] - syft_action_data_str_: Optional[str] - syft_has_bool_attr: Optional[bool] - syft_resolve_data: Optional[bool] - syft_created_at: Optional[DateTime] + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_action_data_type: Optional[Type] = None + syft_action_data_repr_: Optional[str] = None + syft_action_data_str_: Optional[str] = None + syft_has_bool_attr: Optional[bool] = None + syft_resolve_data: Optional[bool] = None + syft_created_at: Optional[DateTime] = None @serializable() @@ -647,27 +679,27 @@ class ActionObjectV2(SyftObject): syft_pointer_type: ClassVar[Type[ActionObjectPointer]] # Help with calculating history hash for code verification - syft_parent_hashes: Optional[Union[int, List[int]]] - syft_parent_op: Optional[str] - syft_parent_args: Optional[Any] - syft_parent_kwargs: Optional[Any] - syft_history_hash: Optional[int] + syft_parent_hashes: Optional[Union[int, List[int]]] = None + syft_parent_op: Optional[str] = None + syft_parent_args: Optional[Any] = None + syft_parent_kwargs: Optional[Any] = None + syft_history_hash: Optional[int] = None syft_internal_type: ClassVar[Type[Any]] - syft_node_uid: Optional[UID] - _syft_pre_hooks__: Dict[str, List] = {} - _syft_post_hooks__: Dict[str, List] = {} + syft_node_uid: Optional[UID] = None + syft_pre_hooks__: Dict[str, List] = {} + syft_post_hooks__: Dict[str, List] = {} syft_twin_type: TwinMode = TwinMode.NONE - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_action_data_type: Optional[Type] - syft_action_data_repr_: Optional[str] - syft_action_data_str_: Optional[str] - syft_has_bool_attr: Optional[bool] - syft_resolve_data: Optional[bool] - syft_created_at: Optional[DateTime] + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_action_data_type: Optional[Type] = None + syft_action_data_repr_: Optional[str] = None + syft_action_data_str_: Optional[str] = None + syft_has_bool_attr: Optional[bool] = None + syft_resolve_data: Optional[bool] = None + syft_created_at: Optional[DateTime] = None syft_resolved: bool = True -@serializable() +@serializable(without=["syft_pre_hooks__", "syft_post_hooks__"]) class ActionObject(SyftObject): """Action object for remote execution.""" @@ -680,25 +712,25 @@ class ActionObject(SyftObject): syft_pointer_type: ClassVar[Type[ActionObjectPointer]] # Help with calculating history hash for code verification - syft_parent_hashes: Optional[Union[int, List[int]]] - syft_parent_op: Optional[str] - syft_parent_args: Optional[Any] - syft_parent_kwargs: Optional[Any] - syft_history_hash: Optional[int] + syft_parent_hashes: Optional[Union[int, List[int]]] = None + syft_parent_op: Optional[str] = None + syft_parent_args: Optional[Any] = None + syft_parent_kwargs: Optional[Any] = None + syft_history_hash: Optional[int] = None syft_internal_type: ClassVar[Type[Any]] - syft_node_uid: Optional[UID] - _syft_pre_hooks__: Dict[str, List] = {} - _syft_post_hooks__: Dict[str, List] = {} + syft_node_uid: Optional[UID] = None + syft_pre_hooks__: Dict[str, List] = {} + syft_post_hooks__: Dict[str, List] = {} syft_twin_type: TwinMode = TwinMode.NONE - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_action_data_type: Optional[Type] - syft_action_data_repr_: Optional[str] - syft_action_data_str_: Optional[str] - syft_has_bool_attr: Optional[bool] - syft_resolve_data: Optional[bool] - syft_created_at: Optional[DateTime] + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_action_data_type: Optional[Type] = None + syft_action_data_repr_: Optional[str] = None + syft_action_data_str_: Optional[str] = None + syft_has_bool_attr: Optional[bool] = None + syft_resolve_data: Optional[bool] = None + syft_created_at: Optional[DateTime] = None syft_resolved: bool = True - syft_action_data_node_id: Optional[UID] + syft_action_data_node_id: Optional[UID] = None # syft_dont_wrap_attrs = ["shape"] def get_diff(self, ext_obj: Any) -> List[AttrDiff]: @@ -858,15 +890,10 @@ def syft_lineage_id(self) -> LineageID: """Compute the LineageID of the ActionObject, using the `id` and the `syft_history_hash` memebers""" return LineageID(self.id, self.syft_history_hash) - @pydantic.validator("id", pre=True, always=True) - def make_id(cls, v: Optional[UID]) -> UID: - """Generate or reuse an UID""" - return Action.make_id(v) - - class Config: - validate_assignment = True + model_config = ConfigDict(validate_assignment=True) - @pydantic.root_validator() + @model_validator(mode="before") + @classmethod def __check_action_data(cls, values: dict) -> dict: v = values.get("syft_action_data_cache") if values.get("syft_action_data_type", None) is None: @@ -896,18 +923,6 @@ def is_real(self) -> bool: def is_twin(self) -> bool: return self.syft_twin_type != TwinMode.NONE - # @pydantic.validator("syft_action_data", pre=True, always=True) - # def check_action_data( - # cls, v: ActionObject.syft_pointer_type - # ) -> ActionObject.syft_pointer_type: - # if cls == AnyActionObject or isinstance( - # v, (cls.syft_internal_type, ActionDataEmpty) - # ): - # return v - # raise SyftException( - # f"Must init {cls} with {cls.syft_internal_type} not {type(v)}" - # ) - def syft_point_to(self, node_uid: UID) -> ActionObject: """Set the syft_node_uid, used in the post hooks""" self.syft_node_uid = node_uid @@ -1047,12 +1062,8 @@ def _syft_prepare_obj_uid(self, obj: Any) -> LineageID: return obj.syft_lineage_id # We got a raw object. We need to create the ActionObject from scratch and save it in the store. - obj_id = Action.make_id(None) - lin_obj_id = Action.make_result_id(obj_id) act_obj = ActionObject.from_obj( obj, - id=obj_id, - syft_lineage_id=lin_obj_id, syft_client_verify_key=self.syft_client_verify_key, syft_node_location=self.syft_node_location, ) @@ -1337,13 +1348,13 @@ def from_obj( @classmethod def add_trace_hook(cls) -> bool: return True - # if trace_action_side_effect not in self._syft_pre_hooks__[HOOK_ALWAYS]: - # self._syft_pre_hooks__[HOOK_ALWAYS].append(trace_action_side_effect) + # if trace_action_side_effect not in self.syft_pre_hooks__[HOOK_ALWAYS]: + # self.syft_pre_hooks__[HOOK_ALWAYS].append(trace_action_side_effect) @classmethod def remove_trace_hook(cls) -> bool: return True - # self._syft_pre_hooks__[HOOK_ALWAYS].pop(trace_action_side_effct, None) + # self.syft_pre_hooks__[HOOK_ALWAYS].pop(trace_action_side_effct, None) def as_empty_data(self) -> ActionDataEmpty: return ActionDataEmpty(syft_internal_type=self.syft_internal_type) @@ -1390,16 +1401,17 @@ def obj_not_ready( ) return res - @staticmethod + @classmethod def empty( # TODO: fix the mypy issue + cls, syft_internal_type: Optional[Type[Any]] = None, id: Optional[UID] = None, syft_lineage_id: Optional[LineageID] = None, syft_resolved: Optional[bool] = True, data_node_id: Optional[UID] = None, syft_blob_storage_entry_id: Optional[UID] = None, - ) -> ActionObject: + ) -> Self: """Create an ActionObject from a type, using a ActionDataEmpty object Parameters: @@ -1415,7 +1427,7 @@ def empty( type(None) if syft_internal_type is None else syft_internal_type ) empty = ActionDataEmpty(syft_internal_type=syft_internal_type) - res = ActionObject.from_obj( + res = cls.from_obj( id=id, syft_lineage_id=syft_lineage_id, syft_action_data=empty, @@ -1428,33 +1440,33 @@ def empty( def __post_init__(self) -> None: """Add pre/post hooks.""" - if HOOK_ALWAYS not in self._syft_pre_hooks__: - self._syft_pre_hooks__[HOOK_ALWAYS] = [] + if HOOK_ALWAYS not in self.syft_pre_hooks__: + self.syft_pre_hooks__[HOOK_ALWAYS] = [] - if HOOK_ON_POINTERS not in self._syft_post_hooks__: - self._syft_pre_hooks__[HOOK_ON_POINTERS] = [] + if HOOK_ON_POINTERS not in self.syft_post_hooks__: + self.syft_pre_hooks__[HOOK_ON_POINTERS] = [] # this should be a list as orders matters for side_effect in [make_action_side_effect]: - if side_effect not in self._syft_pre_hooks__[HOOK_ALWAYS]: - self._syft_pre_hooks__[HOOK_ALWAYS].append(side_effect) + if side_effect not in self.syft_pre_hooks__[HOOK_ALWAYS]: + self.syft_pre_hooks__[HOOK_ALWAYS].append(side_effect) for side_effect in [send_action_side_effect]: - if side_effect not in self._syft_pre_hooks__[HOOK_ON_POINTERS]: - self._syft_pre_hooks__[HOOK_ON_POINTERS].append(side_effect) + if side_effect not in self.syft_pre_hooks__[HOOK_ON_POINTERS]: + self.syft_pre_hooks__[HOOK_ON_POINTERS].append(side_effect) - if trace_action_side_effect not in self._syft_pre_hooks__[HOOK_ALWAYS]: - self._syft_pre_hooks__[HOOK_ALWAYS].append(trace_action_side_effect) + if trace_action_side_effect not in self.syft_pre_hooks__[HOOK_ALWAYS]: + self.syft_pre_hooks__[HOOK_ALWAYS].append(trace_action_side_effect) - if HOOK_ALWAYS not in self._syft_post_hooks__: - self._syft_post_hooks__[HOOK_ALWAYS] = [] + if HOOK_ALWAYS not in self.syft_post_hooks__: + self.syft_post_hooks__[HOOK_ALWAYS] = [] - if HOOK_ON_POINTERS not in self._syft_post_hooks__: - self._syft_post_hooks__[HOOK_ON_POINTERS] = [] + if HOOK_ON_POINTERS not in self.syft_post_hooks__: + self.syft_post_hooks__[HOOK_ON_POINTERS] = [] for side_effect in [propagate_node_uid]: - if side_effect not in self._syft_post_hooks__[HOOK_ALWAYS]: - self._syft_post_hooks__[HOOK_ALWAYS].append(side_effect) + if side_effect not in self.syft_post_hooks__[HOOK_ALWAYS]: + self.syft_post_hooks__[HOOK_ALWAYS].append(side_effect) if isinstance(self.syft_action_data_type, ActionObject): raise Exception("Nested ActionObjects", self.syft_action_data_repr_) @@ -1466,16 +1478,16 @@ def _syft_run_pre_hooks__( ) -> Tuple[PreHookContext, Tuple[Any, ...], Dict[str, Any]]: """Hooks executed before the actual call""" result_args, result_kwargs = args, kwargs - if name in self._syft_pre_hooks__: - for hook in self._syft_pre_hooks__[name]: + if name in self.syft_pre_hooks__: + for hook in self.syft_pre_hooks__[name]: result = hook(context, *result_args, **result_kwargs) if result.is_ok(): context, result_args, result_kwargs = result.ok() else: debug(f"Pre-hook failed with {result.err()}") if name not in self._syft_dont_wrap_attrs(): - if HOOK_ALWAYS in self._syft_pre_hooks__: - for hook in self._syft_pre_hooks__[HOOK_ALWAYS]: + if HOOK_ALWAYS in self.syft_pre_hooks__: + for hook in self.syft_pre_hooks__[HOOK_ALWAYS]: result = hook(context, *result_args, **result_kwargs) if result.is_ok(): context, result_args, result_kwargs = result.ok() @@ -1485,8 +1497,8 @@ def _syft_run_pre_hooks__( if self.is_pointer: if name not in self._syft_dont_wrap_attrs(): - if HOOK_ALWAYS in self._syft_pre_hooks__: - for hook in self._syft_pre_hooks__[HOOK_ON_POINTERS]: + if HOOK_ALWAYS in self.syft_pre_hooks__: + for hook in self.syft_pre_hooks__[HOOK_ON_POINTERS]: result = hook(context, *result_args, **result_kwargs) if result.is_ok(): context, result_args, result_kwargs = result.ok() @@ -1501,8 +1513,8 @@ def _syft_run_post_hooks__( ) -> Any: """Hooks executed after the actual call""" new_result = result - if name in self._syft_post_hooks__: - for hook in self._syft_post_hooks__[name]: + if name in self.syft_post_hooks__: + for hook in self.syft_post_hooks__[name]: result = hook(context, name, new_result) if result.is_ok(): new_result = result.ok() @@ -1510,8 +1522,8 @@ def _syft_run_post_hooks__( debug(f"Post hook failed with {result.err()}") if name not in self._syft_dont_wrap_attrs(): - if HOOK_ALWAYS in self._syft_post_hooks__: - for hook in self._syft_post_hooks__[HOOK_ALWAYS]: + if HOOK_ALWAYS in self.syft_post_hooks__: + for hook in self.syft_post_hooks__[HOOK_ALWAYS]: result = hook(context, name, new_result) if result.is_ok(): new_result = result.ok() @@ -1520,8 +1532,8 @@ def _syft_run_post_hooks__( if self.is_pointer: if name not in self._syft_dont_wrap_attrs(): - if HOOK_ALWAYS in self._syft_post_hooks__: - for hook in self._syft_post_hooks__[HOOK_ON_POINTERS]: + if HOOK_ALWAYS in self.syft_post_hooks__: + for hook in self.syft_post_hooks__[HOOK_ON_POINTERS]: result = hook(context, name, new_result) if result.is_ok(): new_result = result.ok() @@ -1795,6 +1807,9 @@ def __getattribute__(self, name: str) -> Any: if name.startswith("_syft") or name.startswith("syft"): return object.__getattribute__(self, name) + if name in passthrough_attrs: + return object.__getattribute__(self, name) + # third party if name in self._syft_passthrough_attrs(): return object.__getattribute__(self, name) @@ -1891,6 +1906,9 @@ def __str__(self) -> str: def __len__(self) -> int: return self.__len__() + def __hash__(self, *args: Any, **kwargs: Any) -> int: + return super().__hash__(*args, **kwargs) + def __getitem__(self, key: Any) -> Any: return self._syft_output_action_object(self.__getitem__(key)) @@ -2067,7 +2085,7 @@ class AnyActionObjectV2(ActionObjectV2): 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_ = "" + syft_action_data_str_: str = "" @serializable() @@ -2078,7 +2096,7 @@ class AnyActionObject(ActionObject): 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_ = "" + syft_action_data_str_: str = "" def __float__(self) -> float: return float(self.syft_action_data) diff --git a/packages/syft/src/syft/service/action/numpy.py b/packages/syft/src/syft/service/action/numpy.py index d16d4bcc769..afbf7c866b5 100644 --- a/packages/syft/src/syft/service/action/numpy.py +++ b/packages/syft/src/syft/service/action/numpy.py @@ -2,6 +2,7 @@ from typing import Any from typing import Callable from typing import ClassVar +from typing import List from typing import Type from typing import Union @@ -54,9 +55,9 @@ class NumpyArrayObjectV1(ActionObjectV1, np.lib.mixins.NDArrayOperatorsMixin): __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[Type[Any]] = np.ndarray - syft_pointer_type = NumpyArrayObjectPointer - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_pointer_type: ClassVar[Type[ActionObjectPointer]] = NumpyArrayObjectPointer + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] @serializable() @@ -66,8 +67,8 @@ class NumpyArrayObjectV2(ActionObjectV2, np.lib.mixins.NDArrayOperatorsMixin): syft_internal_type: ClassVar[Type[Any]] = np.ndarray syft_pointer_type = NumpyArrayObjectPointer - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] # 🔵 TODO 7: Map TPActionObjects and their 3rd Party types like numpy type to these @@ -78,9 +79,9 @@ class NumpyArrayObject(ActionObject, np.lib.mixins.NDArrayOperatorsMixin): __version__ = SYFT_OBJECT_VERSION_3 syft_internal_type: ClassVar[Type[Any]] = np.ndarray - syft_pointer_type = NumpyArrayObjectPointer - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_pointer_type: ClassVar[Type[ActionObjectPointer]] = NumpyArrayObjectPointer + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] # def __eq__(self, other: Any) -> bool: # # 🟡 TODO 8: move __eq__ to a Data / Serdeable type interface on ActionObject @@ -95,9 +96,11 @@ def __array_ufunc__( self, ufunc: Any, method: str, *inputs: Any, **kwargs: Any ) -> Union[Self, tuple[Self, ...]]: inputs = tuple( - np.array(x.syft_action_data, dtype=x.dtype) - if isinstance(x, NumpyArrayObject) - else x + ( + np.array(x.syft_action_data, dtype=x.dtype) + if isinstance(x, NumpyArrayObject) + else x + ) for x in inputs ) @@ -132,9 +135,9 @@ class NumpyScalarObjectV1(ActionObjectV1, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyScalarObject" __version__ = SYFT_OBJECT_VERSION_1 - syft_internal_type = np.number - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_internal_type: ClassVar[Type] = np.number + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] @serializable() @@ -142,9 +145,9 @@ class NumpyScalarObjectV2(ActionObjectV2, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyScalarObject" __version__ = SYFT_OBJECT_VERSION_2 - syft_internal_type = np.number - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_internal_type: ClassVar[Type] = np.number + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] @serializable() @@ -152,9 +155,9 @@ class NumpyScalarObject(ActionObject, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyScalarObject" __version__ = SYFT_OBJECT_VERSION_3 - syft_internal_type = np.number - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_internal_type: ClassVar[Type] = np.number + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] def __float__(self) -> float: return float(self.syft_action_data) @@ -179,9 +182,9 @@ class NumpyBoolObjectV1(ActionObjectV1, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyBoolObject" __version__ = SYFT_OBJECT_VERSION_1 - syft_internal_type = np.bool_ - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_internal_type: ClassVar[Type] = np.bool_ + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] @serializable() @@ -189,9 +192,9 @@ class NumpyBoolObjectV2(ActionObjectV2, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyBoolObject" __version__ = SYFT_OBJECT_VERSION_2 - syft_internal_type = np.bool_ - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_internal_type: ClassVar[Type] = np.bool_ + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] @serializable() @@ -199,9 +202,9 @@ class NumpyBoolObject(ActionObject, np.lib.mixins.NDArrayOperatorsMixin): __canonical_name__ = "NumpyBoolObject" __version__ = SYFT_OBJECT_VERSION_3 - syft_internal_type = np.bool_ - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS - syft_dont_wrap_attrs = ["dtype", "shape"] + syft_internal_type: ClassVar[Type] = np.bool_ + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS + syft_dont_wrap_attrs: List[str] = ["dtype", "shape"] @migrate(NumpyBoolObject, NumpyBoolObjectV1) diff --git a/packages/syft/src/syft/service/action/pandas.py b/packages/syft/src/syft/service/action/pandas.py index 3da2f3d1449..9da7f351ecc 100644 --- a/packages/syft/src/syft/service/action/pandas.py +++ b/packages/syft/src/syft/service/action/pandas.py @@ -2,6 +2,7 @@ from typing import Any from typing import Callable from typing import ClassVar +from typing import List from typing import Type # third party @@ -29,7 +30,7 @@ class PandasDataFrameObjectV1(ActionObjectV1): __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[Type[Any]] = DataFrame - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS @serializable() @@ -37,8 +38,8 @@ class PandasDataFrameObjectV2(ActionObjectV2): __canonical_name__ = "PandasDataframeObject" __version__ = SYFT_OBJECT_VERSION_2 - syft_internal_type: ClassVar[Type[Any]] = DataFrame - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS + syft_internal_type: ClassVar[Type] = DataFrame + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS @serializable() @@ -46,8 +47,8 @@ class PandasDataFrameObject(ActionObject): __canonical_name__ = "PandasDataframeObject" __version__ = SYFT_OBJECT_VERSION_3 - syft_internal_type: ClassVar[Type[Any]] = DataFrame - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS + 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"] @@ -86,8 +87,8 @@ class PandasSeriesObjectV1(ActionObjectV1): __canonical_name__ = "PandasSeriesObject" __version__ = SYFT_OBJECT_VERSION_1 - syft_internal_type = Series - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS + syft_internal_type: ClassVar[Type] = Series + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS @serializable() @@ -95,8 +96,8 @@ class PandasSeriesObjectV2(ActionObjectV2): __canonical_name__ = "PandasSeriesObject" __version__ = SYFT_OBJECT_VERSION_2 - syft_internal_type = Series - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS + syft_internal_type: ClassVar[Type] = Series + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS @serializable() @@ -105,7 +106,7 @@ class PandasSeriesObject(ActionObject): __version__ = SYFT_OBJECT_VERSION_3 syft_internal_type = Series - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS # name: Optional[str] = None # syft_dont_wrap_attrs = ["shape"] diff --git a/packages/syft/src/syft/service/action/plan.py b/packages/syft/src/syft/service/action/plan.py index a2a81b6f473..e2e920598cc 100644 --- a/packages/syft/src/syft/service/action/plan.py +++ b/packages/syft/src/syft/service/action/plan.py @@ -21,7 +21,13 @@ class Plan(SyftObject): __canonical_name__ = "Plan" __version__ = SYFT_OBJECT_VERSION_1 - syft_passthrough_attrs = ["inputs", "outputs", "code", "actions", "client"] + syft_passthrough_attrs: List[str] = [ + "inputs", + "outputs", + "code", + "actions", + "client", + ] inputs: Dict[str, ActionObject] outputs: List[ActionObject] diff --git a/packages/syft/src/syft/service/code/user_code.py b/packages/syft/src/syft/service/code/user_code.py index 4cb5874b0a5..5c57c1d30aa 100644 --- a/packages/syft/src/syft/service/code/user_code.py +++ b/packages/syft/src/syft/service/code/user_code.py @@ -31,7 +31,7 @@ # third party from IPython.display import display -import pydantic +from pydantic import field_validator from result import Err from typing_extensions import Self @@ -267,7 +267,7 @@ class UserCodeV1(SyftObject): __version__ = SYFT_OBJECT_VERSION_1 id: UID - node_uid: Optional[UID] + node_uid: Optional[UID] = None user_verify_key: SyftVerifyKey raw_code: str input_policy_type: Union[Type[InputPolicy], UserPolicy] @@ -285,7 +285,7 @@ class UserCodeV1(SyftObject): status: UserCodeStatusCollection input_kwargs: List[str] enclave_metadata: Optional[EnclaveMetadata] = None - submit_time: Optional[DateTime] + submit_time: Optional[DateTime] = None __attr_searchable__ = [ "user_verify_key", @@ -302,7 +302,7 @@ class UserCodeV2(SyftObject): __version__ = SYFT_OBJECT_VERSION_2 id: UID - node_uid: Optional[UID] + node_uid: Optional[UID] = None user_verify_key: SyftVerifyKey raw_code: str input_policy_type: Union[Type[InputPolicy], UserPolicy] @@ -320,8 +320,8 @@ class UserCodeV2(SyftObject): status: UserCodeStatusCollection input_kwargs: List[str] enclave_metadata: Optional[EnclaveMetadata] = None - submit_time: Optional[DateTime] - uses_domain = False # tracks if the code calls domain.something, variable is set during parsing + submit_time: Optional[DateTime] = None + uses_domain: bool = False # tracks if the code calls domain.something, variable is set during parsing nested_requests: Dict[str, str] = {} nested_codes: Optional[Dict[str, Tuple[LinkedObject, Dict]]] = {} @@ -331,7 +331,7 @@ class UserCodeV3(SyftObject): __version__ = SYFT_OBJECT_VERSION_3 id: UID - node_uid: Optional[UID] + node_uid: Optional[UID] = None user_verify_key: SyftVerifyKey raw_code: str input_policy_type: Union[Type[InputPolicy], UserPolicy] @@ -349,11 +349,11 @@ class UserCodeV3(SyftObject): status: UserCodeStatusCollection input_kwargs: List[str] enclave_metadata: Optional[EnclaveMetadata] = None - submit_time: Optional[DateTime] - uses_domain = False # tracks if the code calls domain.something, variable is set during parsing + submit_time: Optional[DateTime] = None + uses_domain: bool = False # tracks if the code calls domain.something, variable is set during parsing nested_requests: Dict[str, str] = {} nested_codes: Optional[Dict[str, Tuple[LinkedObject, Dict]]] = {} - worker_pool_name: Optional[str] + worker_pool_name: Optional[str] = None __attr_searchable__: ClassVar[List[str]] = [ "user_verify_key", @@ -377,7 +377,7 @@ class UserCode(SyftObject): __version__ = SYFT_OBJECT_VERSION_4 id: UID - node_uid: Optional[UID] + node_uid: Optional[UID] = None user_verify_key: SyftVerifyKey raw_code: str input_policy_type: Union[Type[InputPolicy], UserPolicy] @@ -395,10 +395,10 @@ class UserCode(SyftObject): status_link: LinkedObject input_kwargs: List[str] enclave_metadata: Optional[EnclaveMetadata] = None - submit_time: Optional[DateTime] - uses_domain = False # tracks if the code calls domain.something, variable is set during parsing + submit_time: Optional[DateTime] = None + uses_domain: bool = False # tracks if the code calls domain.something, variable is set during parsing nested_codes: Optional[Dict[str, Tuple[LinkedObject, Dict]]] = {} - worker_pool_name: Optional[str] + worker_pool_name: Optional[str] = None __attr_searchable__: ClassVar[List[str]] = [ "user_verify_key", @@ -871,7 +871,7 @@ class SubmitUserCodeV2(SyftObject): __canonical_name__ = "SubmitUserCode" __version__ = SYFT_OBJECT_VERSION_2 - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] code: str func_name: str signature: inspect.Signature @@ -879,7 +879,7 @@ class SubmitUserCodeV2(SyftObject): input_policy_init_kwargs: Optional[Dict[Any, Any]] = {} output_policy_type: Union[SubmitUserPolicy, UID, Type[OutputPolicy]] output_policy_init_kwargs: Optional[Dict[Any, Any]] = {} - local_function: Optional[Callable] + local_function: Optional[Callable] = None input_kwargs: List[str] enclave_metadata: Optional[EnclaveMetadata] = None @@ -890,7 +890,7 @@ class SubmitUserCode(SyftObject): __canonical_name__ = "SubmitUserCode" __version__ = SYFT_OBJECT_VERSION_3 - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] code: str func_name: str signature: inspect.Signature @@ -898,17 +898,18 @@ class SubmitUserCode(SyftObject): input_policy_init_kwargs: Optional[Dict[Any, Any]] = {} output_policy_type: Union[SubmitUserPolicy, UID, Type[OutputPolicy]] output_policy_init_kwargs: Optional[Dict[Any, Any]] = {} - local_function: Optional[Callable] + local_function: Optional[Callable] = None input_kwargs: List[str] enclave_metadata: Optional[EnclaveMetadata] = None worker_pool_name: Optional[str] = None __repr_attrs__ = ["func_name", "code"] - @pydantic.root_validator(pre=True) - def add_output_policy_ids(cls, values: dict) -> dict: - if "id" not in values["output_policy_init_kwargs"]: - values["output_policy_init_kwargs"]["id"] = UID() + @field_validator("output_policy_init_kwargs", mode="after") + @classmethod + def add_output_policy_ids(cls, values: Any) -> Any: + if isinstance(values, dict) and "id" not in values: + values["id"] = UID() return values @property @@ -1442,7 +1443,7 @@ class UserCodeExecutionResult(SyftObject): user_code_id: UID stdout: str stderr: str - result: Any + result: Any = None @serializable() @@ -1455,7 +1456,7 @@ class UserCodeExecutionOutput(SyftObject): user_code_id: UID stdout: str stderr: str - result: Any + result: Any = None class SecureContext: diff --git a/packages/syft/src/syft/service/context.py b/packages/syft/src/syft/service/context.py index dc0d3c283b1..a26bde54efa 100644 --- a/packages/syft/src/syft/service/context.py +++ b/packages/syft/src/syft/service/context.py @@ -25,8 +25,9 @@ class NodeServiceContext(Context, SyftObject): __canonical_name__ = "NodeServiceContext" __version__ = SYFT_OBJECT_VERSION_1 - id: Optional[UID] # type: ignore[assignment] - node: Optional[AbstractNode] + + id: Optional[UID] = None # type: ignore[assignment] + node: Optional[AbstractNode] = None class AuthedServiceContext(NodeServiceContext): @@ -35,7 +36,7 @@ class AuthedServiceContext(NodeServiceContext): credentials: SyftVerifyKey role: ServiceRole = ServiceRole.NONE - job_id: Optional[UID] + job_id: Optional[UID] = None extra_kwargs: Dict = {} has_execute_permissions: bool = False @@ -73,7 +74,7 @@ class UnauthedServiceContext(NodeServiceContext): __version__ = SYFT_OBJECT_VERSION_1 login_credentials: UserLoginCredentials - node: Optional[AbstractNode] + node: Optional[AbstractNode] = None role: ServiceRole = ServiceRole.NONE @@ -82,8 +83,8 @@ class ChangeContext(SyftBaseObject): __version__ = SYFT_OBJECT_VERSION_1 node: Optional[AbstractNode] = None - approving_user_credentials: Optional[SyftVerifyKey] - requesting_user_credentials: Optional[SyftVerifyKey] + approving_user_credentials: Optional[SyftVerifyKey] = None + requesting_user_credentials: Optional[SyftVerifyKey] = None extra_kwargs: Dict = {} @classmethod diff --git a/packages/syft/src/syft/service/data_subject/data_subject.py b/packages/syft/src/syft/service/data_subject/data_subject.py index 0bbd47dccc8..4c79b0ff53c 100644 --- a/packages/syft/src/syft/service/data_subject/data_subject.py +++ b/packages/syft/src/syft/service/data_subject/data_subject.py @@ -34,7 +34,7 @@ class DataSubject(SyftObject): node_uid: UID name: str - description: Optional[str] + description: Optional[str] = None aliases: List[str] = [] @property @@ -80,7 +80,7 @@ class DataSubjectCreate(SyftObject): id: Optional[UID] = None # type: ignore[assignment] name: str - description: Optional[str] + description: Optional[str] = None aliases: Optional[List[str]] = [] members: Dict[str, "DataSubjectCreate"] = {} diff --git a/packages/syft/src/syft/service/dataset/dataset.py b/packages/syft/src/syft/service/dataset/dataset.py index 31b20fcb508..14066afed3a 100644 --- a/packages/syft/src/syft/service/dataset/dataset.py +++ b/packages/syft/src/syft/service/dataset/dataset.py @@ -15,12 +15,13 @@ from IPython.display import display import itables import pandas as pd -from pydantic import ValidationError -from pydantic import root_validator -from pydantic import validator +from pydantic import ConfigDict +from pydantic import field_validator +from pydantic import model_validator from result import Err from result import Ok from result import Result +from typing_extensions import Self # relative from ...serde.serializable import serializable @@ -62,10 +63,10 @@ class Contributor(SyftObject): __version__ = SYFT_OBJECT_VERSION_1 name: str - role: Optional[str] + role: Optional[str] = None email: str - phone: Optional[str] - note: Optional[str] + phone: Optional[str] = None + note: Optional[str] = None __repr_attrs__ = ["name", "role", "email"] @@ -131,9 +132,9 @@ class Asset(SyftObject): contributors: Set[Contributor] = set() data_subjects: List[DataSubject] = [] mock_is_real: bool = False - shape: Optional[Tuple] + shape: Optional[Tuple] = None created_at: DateTime = DateTime.now() - uploader: Optional[Contributor] + uploader: Optional[Contributor] = None __repr_attrs__ = ["name", "shape"] @@ -322,40 +323,29 @@ class CreateAsset(SyftObject): description: Optional[MarkdownDescription] = None contributors: Set[Contributor] = set() data_subjects: List[DataSubjectCreate] = [] - node_uid: Optional[UID] - action_id: Optional[UID] - data: Optional[Any] - mock: Optional[Any] - shape: Optional[Tuple] + node_uid: Optional[UID] = None + action_id: Optional[UID] = None + data: Optional[Any] = None + mock: Optional[Any] = None + shape: Optional[Tuple] = None mock_is_real: bool = False - created_at: Optional[DateTime] - uploader: Optional[Contributor] + created_at: Optional[DateTime] = None + uploader: Optional[Contributor] = None __repr_attrs__ = ["name"] - - class Config: - validate_assignment = True + model_config = ConfigDict(validate_assignment=True) def __init__(self, description: Optional[str] = "", **data: Any) -> None: super().__init__(**data, description=MarkdownDescription(text=str(description))) - @root_validator() - def __empty_mock_cannot_be_real(cls, values: dict[str, Any]) -> Dict: - """set mock_is_real to False whenever mock is None or empty""" - - if (mock := values.get("mock")) is None or _is_action_data_empty(mock): - values["mock_is_real"] = False - - return values - - @validator("mock_is_real") - def __mock_is_real_for_empty_mock_must_be_false( - cls, v: bool, values: dict[str, Any], **kwargs: Any - ) -> bool: - if v and ((mock := values.get("mock")) is None or _is_action_data_empty(mock)): - raise ValueError("mock_is_real must be False if mock is not provided") + @model_validator(mode="after") + def __mock_is_real_for_empty_mock_must_be_false(self) -> Self: + if self.mock_is_real and ( + self.mock is None or _is_action_data_empty(self.mock) + ): + self.__dict__["mock_is_real"] = False - return v + return self def add_data_subject(self, data_subject: DataSubject) -> None: self.data_subjects.append(data_subject) @@ -397,14 +387,11 @@ def set_mock(self, mock_data: Any, mock_is_real: bool) -> None: if isinstance(mock_data, SyftError): raise SyftException(mock_data) - current_mock = self.mock - self.mock = mock_data + if mock_is_real and (mock_data is None or _is_action_data_empty(mock_data)): + raise SyftException("`mock_is_real` must be False if mock is empty") - try: - self.mock_is_real = mock_is_real - except ValidationError as e: - self.mock = current_mock - raise e + self.mock = mock_data + self.mock_is_real = mock_is_real def no_mock(self) -> None: # relative @@ -460,15 +447,15 @@ class Dataset(SyftObject): id: UID name: str - node_uid: Optional[UID] + node_uid: Optional[UID] = None asset_list: List[Asset] = [] contributors: Set[Contributor] = set() - citation: Optional[str] - url: Optional[str] + citation: Optional[str] = None + url: Optional[str] = None description: Optional[MarkdownDescription] = None - updated_at: Optional[str] + updated_at: Optional[str] = None requests: Optional[int] = 0 - mb_size: Optional[int] + mb_size: Optional[float] = None created_at: DateTime = DateTime.now() uploader: Contributor @@ -635,16 +622,16 @@ class CreateDataset(Dataset): __repr_attrs__ = ["name", "url"] id: Optional[UID] = None # type: ignore[assignment] - created_at: Optional[DateTime] # type: ignore[assignment] - uploader: Optional[Contributor] # type: ignore[assignment] + created_at: Optional[DateTime] = None # type: ignore[assignment] + uploader: Optional[Contributor] = None # type: ignore[assignment] - class Config: - validate_assignment = True + model_config = ConfigDict(validate_assignment=True) def _check_asset_must_contain_mock(self) -> None: _check_asset_must_contain_mock(self.asset_list) - @validator("asset_list") + @field_validator("asset_list") + @classmethod def __assets_must_contain_mock( cls, asset_list: List[CreateAsset] ) -> List[CreateAsset]: diff --git a/packages/syft/src/syft/service/job/job_stash.py b/packages/syft/src/syft/service/job/job_stash.py index 29635646f46..824af0ee82e 100644 --- a/packages/syft/src/syft/service/job/job_stash.py +++ b/packages/syft/src/syft/service/job/job_stash.py @@ -10,7 +10,8 @@ from typing import Union # third party -import pydantic +from pydantic import field_validator +from pydantic import model_validator from result import Err from result import Ok from result import Result @@ -69,11 +70,11 @@ class JobV1(SyftObject): id: UID node_uid: UID - result: Optional[Any] + result: Optional[Any] = None resolved: bool = False status: JobStatus = JobStatus.CREATED - log_id: Optional[UID] - parent_job_id: Optional[UID] + log_id: Optional[UID] = None + parent_job_id: Optional[UID] = None n_iters: Optional[int] = 0 current_iter: Optional[int] = None creation_time: Optional[str] = None @@ -87,11 +88,11 @@ class JobV2(SyftObject): id: UID node_uid: UID - result: Optional[Any] + result: Optional[Any] = None resolved: bool = False status: JobStatus = JobStatus.CREATED - log_id: Optional[UID] - parent_job_id: Optional[UID] + log_id: Optional[UID] = None + parent_job_id: Optional[UID] = None n_iters: Optional[int] = 0 current_iter: Optional[int] = None creation_time: Optional[str] = None @@ -106,11 +107,11 @@ class Job(SyftObject): id: UID node_uid: UID - result: Optional[Any] + result: Optional[Any] = None resolved: bool = False status: JobStatus = JobStatus.CREATED - log_id: Optional[UID] - parent_job_id: Optional[UID] + log_id: Optional[UID] = None + parent_job_id: Optional[UID] = None n_iters: Optional[int] = 0 current_iter: Optional[int] = None creation_time: Optional[str] = None @@ -124,26 +125,23 @@ class Job(SyftObject): __repr_attrs__ = ["id", "result", "resolved", "progress", "creation_time"] __exclude_sync_diff_attrs__ = ["action"] - @pydantic.root_validator() - def check_time(cls, values: dict) -> dict: - if values.get("creation_time", None) is None: - values["creation_time"] = str(datetime.now()) - return values - - @pydantic.root_validator() - def check_user_code_id(cls, values: dict) -> dict: - action = values.get("action") - user_code_id = values.get("user_code_id") - - if action is not None: - if user_code_id is None: - values["user_code_id"] = action.user_code_id - elif action.user_code_id != user_code_id: - raise pydantic.ValidationError( - "user_code_id does not match the action's user_code_id", cls + @field_validator("creation_time") + @classmethod + def check_time(cls, time: Any) -> Any: + return str(datetime.now()) if time is None else time + + @model_validator(mode="after") + def check_user_code_id(self) -> Self: + if self.action is not None: + if self.user_code_id is None: + self.user_code_id = self.action.user_code_id + elif self.action.user_code_id != self.user_code_id: + raise ValueError( + "user_code_id does not match the action's user_code_id", + self.__class__, ) - return values + return self @property def action_display_name(self) -> str: diff --git a/packages/syft/src/syft/service/metadata/node_metadata.py b/packages/syft/src/syft/service/metadata/node_metadata.py index 2dca67662fb..39cd8b140e7 100644 --- a/packages/syft/src/syft/service/metadata/node_metadata.py +++ b/packages/syft/src/syft/service/metadata/node_metadata.py @@ -9,7 +9,7 @@ # third party from packaging import version from pydantic import BaseModel -from pydantic import root_validator +from pydantic import model_validator # relative from ...abstract_node import NodeType @@ -51,16 +51,16 @@ class NodeMetadataUpdate(SyftObject): __canonical_name__ = "NodeMetadataUpdate" __version__ = SYFT_OBJECT_VERSION_1 - name: Optional[str] - organization: Optional[str] - description: Optional[str] - on_board: Optional[bool] - id: Optional[UID] # type: ignore[assignment] - verify_key: Optional[SyftVerifyKey] - highest_object_version: Optional[int] - lowest_object_version: Optional[int] - syft_version: Optional[str] - admin_email: Optional[str] + name: Optional[str] = None + organization: Optional[str] = None + description: Optional[str] = None + on_board: Optional[bool] = None + id: Optional[UID] = None # type: ignore[assignment] + verify_key: Optional[SyftVerifyKey] = None + highest_object_version: Optional[int] = None + lowest_object_version: Optional[int] = None + syft_version: Optional[str] = None + admin_email: Optional[str] = None @serializable() @@ -152,8 +152,8 @@ class NodeMetadataJSON(BaseModel, StorableObjectType): name: str id: str verify_key: str - highest_object_version: Optional[int] - lowest_object_version: Optional[int] + highest_object_version: Optional[int] = None + lowest_object_version: Optional[int] = None syft_version: str node_type: str = NodeType.DOMAIN.value organization: str = "OpenMined" @@ -164,7 +164,8 @@ class NodeMetadataJSON(BaseModel, StorableObjectType): show_warnings: bool supported_protocols: List = [] - @root_validator(pre=True) + @model_validator(mode="before") + @classmethod def add_protocol_versions(cls, values: dict) -> dict: if "supported_protocols" not in values: data_protocol = get_data_protocol() diff --git a/packages/syft/src/syft/service/network/node_peer.py b/packages/syft/src/syft/service/network/node_peer.py index 4a8da92732d..4f5f6ac5593 100644 --- a/packages/syft/src/syft/service/network/node_peer.py +++ b/packages/syft/src/syft/service/network/node_peer.py @@ -35,7 +35,7 @@ class NodePeer(SyftObject): __attr_unique__ = ["verify_key"] __repr_attrs__ = ["name", "node_type", "admin_email"] - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] name: str verify_key: SyftVerifyKey node_routes: List[NodeRouteType] = [] diff --git a/packages/syft/src/syft/service/notification/notifications.py b/packages/syft/src/syft/service/notification/notifications.py index 1a4e5a9794c..f2feb5e0a17 100644 --- a/packages/syft/src/syft/service/notification/notifications.py +++ b/packages/syft/src/syft/service/notification/notifications.py @@ -45,8 +45,8 @@ class ReplyNotification(SyftObject): text: str target_msg: UID - id: Optional[UID] # type: ignore[assignment] - from_user_verify_key: Optional[SyftVerifyKey] + id: Optional[UID] = None # type: ignore[assignment] + from_user_verify_key: Optional[SyftVerifyKey] = None @serializable() @@ -60,7 +60,7 @@ class Notification(SyftObject): to_user_verify_key: SyftVerifyKey created_at: DateTime status: NotificationStatus = NotificationStatus.UNREAD - linked_obj: Optional[LinkedObject] + linked_obj: Optional[LinkedObject] = None replies: Optional[List[ReplyNotification]] = [] __attr_searchable__ = [ @@ -140,10 +140,10 @@ class CreateNotification(Notification): __canonical_name__ = "CreateNotification" __version__ = SYFT_OBJECT_VERSION_1 - id: Optional[UID] # type: ignore[assignment] - node_uid: Optional[UID] # type: ignore[assignment] - from_user_verify_key: Optional[SyftVerifyKey] # type: ignore[assignment] - created_at: Optional[DateTime] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] + node_uid: Optional[UID] = None # type: ignore[assignment] + from_user_verify_key: Optional[SyftVerifyKey] = None # type: ignore[assignment] + created_at: Optional[DateTime] = None # type: ignore[assignment] def add_msg_creation_time(context: TransformContext) -> TransformContext: diff --git a/packages/syft/src/syft/service/output/output_service.py b/packages/syft/src/syft/service/output/output_service.py index 12abcf46c1c..7e0a190b366 100644 --- a/packages/syft/src/syft/service/output/output_service.py +++ b/packages/syft/src/syft/service/output/output_service.py @@ -8,7 +8,7 @@ from typing import Union # third party -import pydantic +from pydantic import model_validator from result import Result # relative @@ -49,7 +49,7 @@ class ExecutionOutput(SyftObject): job_link: Optional[LinkedObject] = None created_at: DateTime = DateTime.now() - # Required for __attr_searchable__, set by root_validator + # 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 @@ -67,7 +67,8 @@ class ExecutionOutput(SyftObject): "output_ids", ] - @pydantic.root_validator(pre=True) + @model_validator(mode="before") + @classmethod def add_user_code_id(cls, values: dict) -> dict: if "user_code_link" in values: values["user_code_id"] = values["user_code_link"].object_uid diff --git a/packages/syft/src/syft/service/policy/policy.py b/packages/syft/src/syft/service/policy/policy.py index 4e84caabd93..745abf8daef 100644 --- a/packages/syft/src/syft/service/policy/policy.py +++ b/packages/syft/src/syft/service/policy/policy.py @@ -325,7 +325,7 @@ class OutputHistory(SyftObject): __version__ = SYFT_OBJECT_VERSION_1 output_time: DateTime - outputs: Optional[Union[List[UID], Dict[str, UID]]] + outputs: Optional[Union[List[UID], Dict[str, UID]]] = None executing_user_verify_key: SyftVerifyKey @@ -335,7 +335,7 @@ class OutputPolicy(Policy): __version__ = SYFT_OBJECT_VERSION_1 output_kwargs: List[str] = [] - node_uid: Optional[UID] + node_uid: Optional[UID] = None output_readers: List[SyftVerifyKey] = [] def apply_output( @@ -470,7 +470,7 @@ class UserPolicy(Policy): __version__ = SYFT_OBJECT_VERSION_1 id: UID - node_uid: Optional[UID] + node_uid: Optional[UID] = None user_verify_key: SyftVerifyKey raw_code: str parsed_code: str @@ -478,7 +478,6 @@ class UserPolicy(Policy): class_name: str unique_name: str code_hash: str - byte_code: PyCodeObject status: UserPolicyStatus = UserPolicyStatus.SUBMITTED # TODO: fix the mypy issue @@ -540,7 +539,7 @@ class SubmitUserPolicy(Policy): __canonical_name__ = "SubmitUserPolicy" __version__ = SYFT_OBJECT_VERSION_1 - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] code: str class_name: str input_kwargs: List[str] diff --git a/packages/syft/src/syft/service/project/project.py b/packages/syft/src/syft/service/project/project.py index d487c97fdd3..41388d27080 100644 --- a/packages/syft/src/syft/service/project/project.py +++ b/packages/syft/src/syft/service/project/project.py @@ -18,8 +18,8 @@ from typing import Union # third party -import pydantic -from pydantic import validator +from pydantic import Field +from pydantic import field_validator from rich.progress import Progress from typing_extensions import Self @@ -79,17 +79,17 @@ class ProjectEvent(SyftObject): # 1. Creation attrs id: UID - timestamp: DateTime + timestamp: DateTime = Field(default_factory=DateTime.now) allowed_sub_types: Optional[List] = [] # 2. Rebase attrs - project_id: Optional[UID] - seq_no: Optional[int] - prev_event_uid: Optional[UID] - prev_event_hash: Optional[str] - event_hash: Optional[str] + project_id: Optional[UID] = None + seq_no: Optional[int] = None + prev_event_uid: Optional[UID] = None + prev_event_hash: Optional[str] = None + event_hash: Optional[str] = None # 3. Signature attrs - creator_verify_key: Optional[SyftVerifyKey] - signature: Optional[bytes] # dont use in signing + creator_verify_key: Optional[SyftVerifyKey] = None + signature: Optional[bytes] = None # dont use in signing def __repr_syft_nested__(self) -> tuple[str, str]: return ( @@ -97,12 +97,6 @@ def __repr_syft_nested__(self) -> tuple[str, str]: f"{str(self.id)[:4]}...{str(self.id)[-3:]}", ) - @pydantic.root_validator(pre=True) - def make_timestamp(cls, values: Dict[str, Any]) -> Dict[str, Any]: - if "timestamp" not in values or values["timestamp"] is None: - values["timestamp"] = DateTime.now() - return values - def _pre_add_update(self, project: Project) -> None: pass @@ -278,8 +272,9 @@ class ProjectRequest(ProjectEventAddObject): linked_request: LinkedObject allowed_sub_types: List[Type] = [ProjectRequestResponse] - @validator("linked_request", pre=True) - def _validate_linked_request(cls, v: Any) -> Union[Request, LinkedObject]: + @field_validator("linked_request", mode="before") + @classmethod + def _validate_linked_request(cls, v: Any) -> LinkedObject: if isinstance(v, Request): linked_request = LinkedObject.from_obj(v, node_uid=v.node_uid) return linked_request @@ -557,8 +552,9 @@ class ProjectMultipleChoicePoll(ProjectEventAddObject): choices: List[str] allowed_sub_types: List[Type] = [AnswerProjectPoll] - @validator("choices") - def choices_min_length(cls, v: str) -> str: + @field_validator("choices") + @classmethod + def choices_min_length(cls, v: list[str]) -> list[str]: if len(v) < 1: raise ValueError("choices must have at least one item") return v @@ -681,14 +677,14 @@ class Project(SyftObject): "event_id_hashmap", ] - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] name: str - description: Optional[str] + description: Optional[str] = None members: List[NodeIdentity] users: List[UserIdentity] = [] - username: Optional[str] + username: Optional[str] = None created_by: str - start_hash: Optional[str] + start_hash: Optional[str] = None # WARNING: Do not add it to hash keys or print directly user_signing_key: Optional[SyftSigningKey] = None @@ -698,7 +694,7 @@ class Project(SyftObject): # Project sync state_sync_leader: NodeIdentity - leader_node_peer: Optional[NodePeer] + leader_node_peer: Optional[NodePeer] = None # Unused consensus_model: ConsensusModel @@ -1172,19 +1168,19 @@ class ProjectSubmit(SyftObject): # Init args name: str - description: Optional[str] + description: Optional[str] = None members: Union[List[SyftClient], List[NodeIdentity]] # These will be automatically populated users: List[UserIdentity] = [] created_by: Optional[str] = None - username: Optional[str] + username: Optional[str] = None clients: List[SyftClient] = [] # List of member clients start_hash: str = "" # Project sync args - leader_node_route: Optional[NodeRoute] - state_sync_leader: Optional[NodeIdentity] + leader_node_route: Optional[NodeRoute] = None + state_sync_leader: Optional[NodeIdentity] = None bootstrap_events: Optional[List[ProjectEvent]] = [] # Unused at the moment @@ -1231,7 +1227,8 @@ def _repr_html_(self) -> Any: + "" ) - @validator("members", pre=True) + @field_validator("members", mode="before") + @classmethod def verify_members( cls, val: Union[List[SyftClient], List[NodeIdentity]] ) -> Union[List[SyftClient], List[NodeIdentity]]: diff --git a/packages/syft/src/syft/service/queue/queue_stash.py b/packages/syft/src/syft/service/queue/queue_stash.py index 34cc3265583..1c23ccfcb0a 100644 --- a/packages/syft/src/syft/service/queue/queue_stash.py +++ b/packages/syft/src/syft/service/queue/queue_stash.py @@ -55,7 +55,7 @@ class QueueItemV1(SyftObject): id: UID node_uid: UID - result: Optional[Any] + result: Optional[Any] = None resolved: bool = False status: Status = Status.CREATED @@ -67,7 +67,7 @@ class QueueItemV2(SyftObject): id: UID node_uid: UID - result: Optional[Any] + result: Optional[Any] = None resolved: bool = False status: Status = Status.CREATED @@ -75,8 +75,8 @@ class QueueItemV2(SyftObject): service: str args: List kwargs: Dict[str, Any] - job_id: Optional[UID] - worker_settings: Optional[WorkerSettings] + job_id: Optional[UID] = None + worker_settings: Optional[WorkerSettings] = None has_execute_permissions: bool = False @@ -89,7 +89,7 @@ class QueueItem(SyftObject): id: UID node_uid: UID - result: Optional[Any] + result: Optional[Any] = None resolved: bool = False status: Status = Status.CREATED @@ -97,8 +97,8 @@ class QueueItem(SyftObject): service: str args: List kwargs: Dict[str, Any] - job_id: Optional[UID] - worker_settings: Optional[WorkerSettings] + job_id: Optional[UID] = None + worker_settings: Optional[WorkerSettings] = None has_execute_permissions: bool = False worker_pool: LinkedObject diff --git a/packages/syft/src/syft/service/queue/zmq_queue.py b/packages/syft/src/syft/service/queue/zmq_queue.py index a2bc6512dfc..7f7d26fe085 100644 --- a/packages/syft/src/syft/service/queue/zmq_queue.py +++ b/packages/syft/src/syft/service/queue/zmq_queue.py @@ -17,7 +17,7 @@ # third party from loguru import logger -from pydantic import validator +from pydantic import field_validator from zmq import Frame from zmq import LINGER from zmq.error import ContextTerminated @@ -121,8 +121,11 @@ class Worker(SyftBaseModel): syft_worker_id: Optional[UID] = None expiry_t: Timeout = Timeout(WORKER_TIMEOUT_SEC) - @validator("syft_worker_id", pre=True, always=True) - def set_syft_worker_id(cls, v: Any, values: Any) -> Union[UID, Any]: + # TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually. + # Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information. + @field_validator("syft_worker_id", mode="before") + @classmethod + def set_syft_worker_id(cls, v: Any) -> Any: if isinstance(v, str): return UID(v) return v @@ -794,7 +797,7 @@ class ZMQClientConfigV1(SyftObject, QueueClientConfig): __canonical_name__ = "ZMQClientConfig" __version__ = SYFT_OBJECT_VERSION_1 - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] hostname: str = "127.0.0.1" @@ -802,7 +805,7 @@ class ZMQClientConfigV2(SyftObject, QueueClientConfig): __canonical_name__ = "ZMQClientConfig" __version__ = SYFT_OBJECT_VERSION_2 - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] hostname: str = "127.0.0.1" queue_port: Optional[int] = None # TODO: setting this to false until we can fix the ZMQ @@ -816,14 +819,14 @@ class ZMQClientConfig(SyftObject, QueueClientConfig): __canonical_name__ = "ZMQClientConfig" __version__ = SYFT_OBJECT_VERSION_3 - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] hostname: str = "127.0.0.1" queue_port: Optional[int] = None # TODO: setting this to false until we can fix the ZMQ # port issue causing tests to randomly fail create_producer: bool = False n_consumers: int = 0 - consumer_service: Optional[str] + consumer_service: Optional[str] = None @migrate(ZMQClientConfig, ZMQClientConfigV1) diff --git a/packages/syft/src/syft/service/request/request.py b/packages/syft/src/syft/service/request/request.py index 0df43565b03..972ce71759b 100644 --- a/packages/syft/src/syft/service/request/request.py +++ b/packages/syft/src/syft/service/request/request.py @@ -79,7 +79,7 @@ class Change(SyftObject): __canonical_name__ = "Change" __version__ = SYFT_OBJECT_VERSION_1 - linked_obj: Optional[LinkedObject] + linked_obj: Optional[LinkedObject] = None def change_object_is_type(self, type_: type) -> bool: return self.linked_obj is not None and type_ == self.linked_obj.object_type @@ -90,7 +90,7 @@ class ChangeStatus(SyftObject): __canonical_name__ = "ChangeStatus" __version__ = SYFT_OBJECT_VERSION_1 - id: Optional[UID] # type: ignore[assignment] + id: Optional[UID] = None # type: ignore[assignment] change_id: UID applied: bool = False @@ -204,7 +204,7 @@ class CreateCustomImageChange(Change): config: WorkerConfig tag: str - registry_uid: Optional[UID] + registry_uid: Optional[UID] = None __repr_attrs__ = ["config", "tag"] @@ -283,8 +283,8 @@ class CreateCustomWorkerPoolChange(Change): pool_name: str num_workers: int - image_uid: Optional[UID] - config: Optional[WorkerConfig] + image_uid: Optional[UID] = None + config: Optional[WorkerConfig] = None __repr_attrs__ = ["pool_name", "num_workers", "image_uid"] @@ -353,9 +353,9 @@ class Request(SyftObject): requesting_user_name: str = "" requesting_user_email: Optional[str] = "" requesting_user_institution: Optional[str] = "" - approving_user_verify_key: Optional[SyftVerifyKey] + approving_user_verify_key: Optional[SyftVerifyKey] = None request_time: DateTime - updated_at: Optional[DateTime] + updated_at: Optional[DateTime] = None node_uid: UID request_hash: str changes: List[Change] @@ -912,7 +912,7 @@ class RequestInfoFilter(SyftObject): __canonical_name__ = "RequestInfoFilter" __version__ = SYFT_OBJECT_VERSION_1 - name: Optional[str] + name: Optional[str] = None @serializable() @@ -921,7 +921,7 @@ class SubmitRequest(SyftObject): __version__ = SYFT_OBJECT_VERSION_1 changes: List[Change] - requesting_user_verify_key: Optional[SyftVerifyKey] + requesting_user_verify_key: Optional[SyftVerifyKey] = None def hash_changes(context: TransformContext) -> TransformContext: @@ -998,11 +998,11 @@ class ObjectMutation(Change): __canonical_name__ = "ObjectMutation" __version__ = SYFT_OBJECT_VERSION_1 - linked_obj: Optional[LinkedObject] + linked_obj: Optional[LinkedObject] = None attr_name: str - value: Optional[Any] + value: Optional[Any] = None match_type: bool - previous_value: Optional[Any] + previous_value: Optional[Any] = None __repr_attrs__ = ["linked_obj", "attr_name"] @@ -1070,7 +1070,7 @@ class EnumMutation(ObjectMutation): __version__ = SYFT_OBJECT_VERSION_1 enum_type: Type[Enum] - value: Optional[Enum] + value: Optional[Enum] = None match_type: bool = True __repr_attrs__ = ["linked_obj", "attr_name", "value"] diff --git a/packages/syft/src/syft/service/service.py b/packages/syft/src/syft/service/service.py index 42f65aeafe5..0ee5517d00e 100644 --- a/packages/syft/src/syft/service/service.py +++ b/packages/syft/src/syft/service/service.py @@ -95,10 +95,10 @@ class BaseConfig(SyftBaseObject): private_path: str public_name: str method_name: str - doc_string: Optional[str] - signature: Optional[Signature] + doc_string: Optional[str] = None + signature: Optional[Signature] = None is_from_lib: bool = False - warning: Optional[APIEndpointWarning] + warning: Optional[APIEndpointWarning] = None @serializable() diff --git a/packages/syft/src/syft/service/sync/diff_state.py b/packages/syft/src/syft/service/sync/diff_state.py index 5fdf2ee6761..0def3b1fa94 100644 --- a/packages/syft/src/syft/service/sync/diff_state.py +++ b/packages/syft/src/syft/service/sync/diff_state.py @@ -20,13 +20,14 @@ from typing import Union # third party -import pydantic +from pydantic import model_validator from rich import box from rich.console import Console from rich.console import Group from rich.markdown import Markdown from rich.padding import Padding from rich.panel import Panel +from typing_extensions import Self # relative from ...types.syft_object import SYFT_OBJECT_VERSION_1 @@ -56,8 +57,8 @@ class AttrDiff(SyftObject): __canonical_name__ = "AttrDiff" __version__ = SYFT_OBJECT_VERSION_1 attr_name: str - low_attr: Any - high_attr: Any + low_attr: Any = None + high_attr: Any = None def _repr_html_(self) -> str: return f"""{self.attr_name}: @@ -437,15 +438,14 @@ def visual_hierarchy(self) -> Tuple[Type, dict]: } raise ValueError(f"Unknown root type: {self.root.obj_type}") - @pydantic.root_validator - def make_dependents(cls, values: dict) -> dict: - dependencies = values.get("dependencies", {}) + @model_validator(mode="after") + def make_dependents(self) -> Self: dependents: Dict = {} - for parent, children in dependencies.items(): + for parent, children in self.dependencies.items(): for child in children: dependents[child] = dependents.get(child, []) + [parent] - values["dependents"] = dependents - return values + self.dependents = dependents + return self @property def root(self) -> ObjectDiff: diff --git a/packages/syft/src/syft/service/sync/sync_state.py b/packages/syft/src/syft/service/sync/sync_state.py index 84968f98910..0e6ecb28074 100644 --- a/packages/syft/src/syft/service/sync/sync_state.py +++ b/packages/syft/src/syft/service/sync/sync_state.py @@ -37,7 +37,7 @@ class SyncStateRow(SyftObject): __version__ = SYFT_OBJECT_VERSION_1 object: SyftObject - previous_object: Optional[SyftObject] + previous_object: Optional[SyftObject] = None current_state: str previous_state: str level: int = 0 diff --git a/packages/syft/src/syft/service/user/user.py b/packages/syft/src/syft/service/user/user.py index d6c0c3c2124..5edf454cda2 100644 --- a/packages/syft/src/syft/service/user/user.py +++ b/packages/syft/src/syft/service/user/user.py @@ -13,9 +13,9 @@ from bcrypt import checkpw from bcrypt import gensalt from bcrypt import hashpw -import pydantic +from pydantic import EmailStr from pydantic import ValidationError -from pydantic.networks import EmailStr +from pydantic import field_validator # relative from ...client.api import APIRegistry @@ -45,14 +45,14 @@ class UserV1(SyftObject): __canonical_name__ = "User" __version__ = SYFT_OBJECT_VERSION_1 - email: Optional[EmailStr] - name: Optional[str] - hashed_password: Optional[str] - salt: Optional[str] - signing_key: Optional[SyftSigningKey] - verify_key: Optional[SyftVerifyKey] - role: Optional[ServiceRole] - institution: Optional[str] + email: Optional[EmailStr] = None + name: Optional[str] = None + hashed_password: Optional[str] = None + salt: Optional[str] = None + signing_key: Optional[SyftSigningKey] = None + verify_key: Optional[SyftVerifyKey] = None + role: Optional[ServiceRole] = None + institution: Optional[str] = None website: Optional[str] = None created_at: Optional[str] = None @@ -63,21 +63,17 @@ class User(SyftObject): __canonical_name__ = "User" __version__ = SYFT_OBJECT_VERSION_2 - id: Optional[UID] # type: ignore[assignment] - - @pydantic.validator("email", pre=True, always=True) - def make_email(cls, v: EmailStr) -> EmailStr: - return EmailStr(v) + id: Optional[UID] = None # type: ignore[assignment] # fields - email: Optional[EmailStr] - name: Optional[str] - hashed_password: Optional[str] - salt: Optional[str] - signing_key: Optional[SyftSigningKey] - verify_key: Optional[SyftVerifyKey] - role: Optional[ServiceRole] - institution: Optional[str] + email: Optional[EmailStr] = None + name: Optional[str] = None + hashed_password: Optional[str] = None + salt: Optional[str] = None + signing_key: Optional[SyftSigningKey] = None + verify_key: Optional[SyftVerifyKey] = None + role: Optional[ServiceRole] = None + institution: Optional[str] = None website: Optional[str] = None created_at: Optional[str] = None # TODO where do we put this flag? @@ -152,11 +148,8 @@ class UserUpdate(PartialSyftObject): __canonical_name__ = "UserUpdate" __version__ = SYFT_OBJECT_VERSION_2 - @pydantic.validator("email", pre=True) - def make_email(cls, v: Any) -> Any: - return EmailStr(v) if isinstance(v, str) and not isinstance(v, EmailStr) else v - - @pydantic.validator("role", pre=True) + @field_validator("role", mode="before") + @classmethod def str_to_role(cls, v: Any) -> Any: if isinstance(v, str) and hasattr(ServiceRole, v.upper()): return getattr(ServiceRole, v.upper()) @@ -182,10 +175,10 @@ class UserCreateV1(UserUpdateV1): role: Optional[ServiceRole] = None # type: ignore[assignment] password: str password_verify: Optional[str] = None # type: ignore[assignment] - verify_key: Optional[SyftVerifyKey] # type: ignore[assignment] - institution: Optional[str] # type: ignore[assignment] - website: Optional[str] # type: ignore[assignment] - created_by: Optional[SyftSigningKey] + verify_key: Optional[SyftVerifyKey] = None # type: ignore[assignment] + institution: Optional[str] = None # type: ignore[assignment] + website: Optional[str] = None # type: ignore[assignment] + created_by: Optional[SyftSigningKey] = None @serializable() @@ -198,10 +191,10 @@ class UserCreate(UserUpdate): role: Optional[ServiceRole] = None # type: ignore[assignment] password: str password_verify: Optional[str] = None # type: ignore[assignment] - verify_key: Optional[SyftVerifyKey] # type: ignore[assignment] - institution: Optional[str] # type: ignore[assignment] - website: Optional[str] # type: ignore[assignment] - created_by: Optional[SyftSigningKey] + verify_key: Optional[SyftVerifyKey] = None # type: ignore[assignment] + institution: Optional[str] = None # type: ignore[assignment] + website: Optional[str] = None # type: ignore[assignment] + created_by: Optional[SyftSigningKey] = None mock_execution_permission: bool = False __repr_attrs__ = ["name", "email"] @@ -225,8 +218,8 @@ class UserViewV1(SyftObject): email: EmailStr name: str role: ServiceRole # make sure role cant be set without uid - institution: Optional[str] - website: Optional[str] + institution: Optional[str] = None + website: Optional[str] = None @serializable() @@ -237,8 +230,8 @@ class UserView(SyftObject): email: EmailStr name: str role: ServiceRole # make sure role cant be set without uid - institution: Optional[str] - website: Optional[str] + institution: Optional[str] = None + website: Optional[str] = None mock_execution_permission: bool __repr_attrs__ = ["name", "email", "institution", "website", "role"] diff --git a/packages/syft/src/syft/service/warnings.py b/packages/syft/src/syft/service/warnings.py index 10038d2026e..015121c4bfa 100644 --- a/packages/syft/src/syft/service/warnings.py +++ b/packages/syft/src/syft/service/warnings.py @@ -22,8 +22,8 @@ class WarningContext( Context, ): - node: Optional[AbstractNode] - credentials: Optional[SyftCredentials] + node: Optional[AbstractNode] = None + credentials: Optional[SyftCredentials] = None role: ServiceRole diff --git a/packages/syft/src/syft/service/worker/image_identifier.py b/packages/syft/src/syft/service/worker/image_identifier.py index 4651c3f4f2e..ac29f9ed3c9 100644 --- a/packages/syft/src/syft/service/worker/image_identifier.py +++ b/packages/syft/src/syft/service/worker/image_identifier.py @@ -29,7 +29,7 @@ class SyftWorkerImageIdentifier(SyftBaseModel): https://docs.docker.com/engine/reference/commandline/tag/#tag-an-image-referenced-by-name-and-tag """ - registry: Optional[Union[SyftImageRegistry, str]] + registry: Optional[Union[SyftImageRegistry, str]] = None repo: str tag: str diff --git a/packages/syft/src/syft/service/worker/image_registry.py b/packages/syft/src/syft/service/worker/image_registry.py index 7292273c605..bac6b8274a4 100644 --- a/packages/syft/src/syft/service/worker/image_registry.py +++ b/packages/syft/src/syft/service/worker/image_registry.py @@ -3,7 +3,7 @@ from urllib.parse import urlparse # third party -from pydantic import validator +from pydantic import field_validator from typing_extensions import Self # relative @@ -28,7 +28,8 @@ class SyftImageRegistry(SyftObject): id: UID url: str - @validator("url") + @field_validator("url") + @classmethod def validate_url(cls, val: str) -> str: if not val: raise ValueError("Invalid Registry URL. Must not be empty") diff --git a/packages/syft/src/syft/service/worker/worker_pool.py b/packages/syft/src/syft/service/worker/worker_pool.py index 947571cde2e..2cc89394a49 100644 --- a/packages/syft/src/syft/service/worker/worker_pool.py +++ b/packages/syft/src/syft/service/worker/worker_pool.py @@ -69,14 +69,14 @@ class SyftWorker(SyftObject): id: UID name: str - container_id: Optional[str] + container_id: Optional[str] = None created_at: DateTime = DateTime.now() - healthcheck: Optional[WorkerHealth] + healthcheck: Optional[WorkerHealth] = None status: WorkerStatus - image: Optional[SyftWorkerImage] + image: Optional[SyftWorkerImage] = None worker_pool_name: str consumer_state: ConsumerState = ConsumerState.DETACHED - job_id: Optional[UID] + job_id: Optional[UID] = None @property def logs(self) -> Union[str, SyftError]: @@ -160,7 +160,7 @@ class WorkerPool(SyftObject): ] name: str - image_id: Optional[UID] + image_id: Optional[UID] = None max_count: int worker_list: List[LinkedObject] created_at: DateTime = DateTime.now() @@ -268,8 +268,8 @@ class ContainerSpawnStatus(SyftBaseModel): __repr_attrs__ = ["worker_name", "worker", "error"] worker_name: str - worker: Optional[SyftWorker] - error: Optional[str] + worker: Optional[SyftWorker] = None + error: Optional[str] = None def _get_worker_container( diff --git a/packages/syft/src/syft/store/blob_storage/__init__.py b/packages/syft/src/syft/store/blob_storage/__init__.py index fb75e5f8e8a..54fb4b202de 100644 --- a/packages/syft/src/syft/store/blob_storage/__init__.py +++ b/packages/syft/src/syft/store/blob_storage/__init__.py @@ -89,7 +89,7 @@ class BlobRetrievalV1(SyftObject): __canonical_name__ = "BlobRetrieval" __version__ = SYFT_OBJECT_VERSION_1 - type_: Optional[Type] + type_: Optional[Type] = None file_name: str @@ -98,10 +98,10 @@ class BlobRetrieval(SyftObject): __canonical_name__ = "BlobRetrieval" __version__ = SYFT_OBJECT_VERSION_2 - type_: Optional[Type] + type_: Optional[Type] = None file_name: str syft_blob_storage_entry_id: Optional[UID] = None - file_size: Optional[int] + file_size: Optional[int] = None @migrate(BlobRetrieval, BlobRetrievalV1) diff --git a/packages/syft/src/syft/store/document_store.py b/packages/syft/src/syft/store/document_store.py index d56b9434471..6468756d3cb 100644 --- a/packages/syft/src/syft/store/document_store.py +++ b/packages/syft/src/syft/store/document_store.py @@ -140,7 +140,7 @@ def from_dict(cks_dict: Dict[str, type]) -> PartitionKeys: @serializable() class QueryKey(PartitionKey): - value: Any + value: Any = None def __eq__(self, other: Any) -> bool: return ( @@ -783,5 +783,5 @@ class StoreConfig(SyftBaseObject): __version__ = SYFT_OBJECT_VERSION_1 store_type: Type[DocumentStore] - client_config: Optional[StoreClientConfig] + client_config: Optional[StoreClientConfig] = None locking_config: LockingConfig = NoLockingConfig() diff --git a/packages/syft/src/syft/store/mongo_document_store.py b/packages/syft/src/syft/store/mongo_document_store.py index 0e012cde66f..ebc38ba1c28 100644 --- a/packages/syft/src/syft/store/mongo_document_store.py +++ b/packages/syft/src/syft/store/mongo_document_store.py @@ -871,6 +871,6 @@ class MongoStoreConfig(StoreConfig): client_config: MongoStoreClientConfig store_type: Type[DocumentStore] = MongoDocumentStore db_name: str = "app" - backing_store = MongoBackingStore + backing_store: Type[KeyValueBackingStore] = MongoBackingStore # TODO: should use a distributed lock, with RedisLockingConfig locking_config: LockingConfig = NoLockingConfig() diff --git a/packages/syft/src/syft/store/sqlite_document_store.py b/packages/syft/src/syft/store/sqlite_document_store.py index 172aba160a8..ced53a523ac 100644 --- a/packages/syft/src/syft/store/sqlite_document_store.py +++ b/packages/syft/src/syft/store/sqlite_document_store.py @@ -16,7 +16,7 @@ # third party from pydantic import Field -from pydantic import validator +from pydantic import field_validator from result import Err from result import Ok from result import Result @@ -437,7 +437,8 @@ class SQLiteStoreClientConfig(StoreClientConfig): # We need this in addition to Field(default_factory=...) # so users can still do SQLiteStoreClientConfig(path=None) - @validator("path", pre=True) + @field_validator("path", mode="before") + @classmethod def __default_path(cls, path: Optional[Union[str, Path]]) -> Union[str, Path]: if path is None: return tempfile.gettempdir() diff --git a/packages/syft/src/syft/types/base.py b/packages/syft/src/syft/types/base.py index bb5160aebb0..764be4ae07a 100644 --- a/packages/syft/src/syft/types/base.py +++ b/packages/syft/src/syft/types/base.py @@ -2,8 +2,8 @@ # third party from pydantic import BaseModel +from pydantic import ConfigDict class SyftBaseModel(BaseModel): - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict(arbitrary_types_allowed=True) diff --git a/packages/syft/src/syft/types/blob_storage.py b/packages/syft/src/syft/types/blob_storage.py index 2bf25f0b7fe..91c061a9346 100644 --- a/packages/syft/src/syft/types/blob_storage.py +++ b/packages/syft/src/syft/types/blob_storage.py @@ -89,8 +89,8 @@ class BlobFile(SyftObject): file_name: str syft_blob_storage_entry_id: Optional[UID] = None file_size: Optional[int] = None - path: Optional[Path] - uploaded = False + path: Optional[Path] = None + uploaded: bool = False __repr_attrs__ = ["id", "file_name"] @@ -241,8 +241,8 @@ class BlobFileObjectV1(ActionObjectV2): __version__ = SYFT_OBJECT_VERSION_1 syft_internal_type: ClassVar[Type[Any]] = BlobFile - syft_pointer_type = BlobFileObjectPointer - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS + syft_pointer_type: ClassVar[Type[ActionObjectPointer]] = BlobFileObjectPointer + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS @serializable() @@ -251,8 +251,8 @@ class BlobFileObject(ActionObject): __version__ = SYFT_OBJECT_VERSION_2 syft_internal_type: ClassVar[Type[Any]] = BlobFile - syft_pointer_type = BlobFileObjectPointer - syft_passthrough_attrs = BASE_PASSTHROUGH_ATTRS + syft_pointer_type: ClassVar[Type[ActionObjectPointer]] = BlobFileObjectPointer + syft_passthrough_attrs: List[str] = BASE_PASSTHROUGH_ATTRS @serializable() @@ -367,7 +367,7 @@ class BlobStorageEntryV1(SyftObject): id: UID location: Union[SecureFilePathLocation, SeaweedSecureFilePathLocation] - type_: Optional[Type] + type_: Optional[Type] = None mimetype: str = "bytes" file_size: int uploaded_by: SyftVerifyKey @@ -383,13 +383,13 @@ class BlobStorageEntry(SyftObject): id: UID location: Union[SecureFilePathLocation, SeaweedSecureFilePathLocation] - type_: Optional[Type] + type_: Optional[Type] = None mimetype: str = "bytes" file_size: int no_lines: Optional[int] = 0 uploaded_by: SyftVerifyKey created_at: DateTime = DateTime.now() - bucket_name: Optional[str] + bucket_name: Optional[str] = None __attr_searchable__ = ["bucket_name"] @@ -411,7 +411,7 @@ class BlobStorageMetadataV1(SyftObject): __canonical_name__ = "BlobStorageMetadata" __version__ = SYFT_OBJECT_VERSION_1 - type_: Optional[Type[SyftObject]] + type_: Optional[Type[SyftObject]] = None mimetype: str = "bytes" file_size: int @@ -421,7 +421,7 @@ class BlobStorageMetadata(SyftObject): __canonical_name__ = "BlobStorageMetadata" __version__ = SYFT_OBJECT_VERSION_2 - type_: Optional[Type[SyftObject]] + type_: Optional[Type[SyftObject]] = None mimetype: str = "bytes" file_size: int no_lines: Optional[int] = 0 @@ -445,7 +445,7 @@ class CreateBlobStorageEntry(SyftObject): __version__ = SYFT_OBJECT_VERSION_1 id: UID - type_: Optional[Type] + type_: Optional[Type] = None mimetype: str = "bytes" file_size: int extensions: List[str] = [] diff --git a/packages/syft/src/syft/types/datetime.py b/packages/syft/src/syft/types/datetime.py index 32b356a4a96..79ca1f35311 100644 --- a/packages/syft/src/syft/types/datetime.py +++ b/packages/syft/src/syft/types/datetime.py @@ -20,7 +20,7 @@ class DateTime(SyftObject): __canonical_name__ = "DateTime" __version__ = SYFT_OBJECT_VERSION_1 - id: Optional[UID] # type: ignore + id: Optional[UID] = None # type: ignore utc_timestamp: float @classmethod diff --git a/packages/syft/src/syft/types/syft_metaclass.py b/packages/syft/src/syft/types/syft_metaclass.py index 4fd067b232a..08ac3ce32de 100644 --- a/packages/syft/src/syft/types/syft_metaclass.py +++ b/packages/syft/src/syft/types/syft_metaclass.py @@ -1,113 +1,40 @@ -# Reference: https://github.com/pydantic/pydantic/issues/1223#issuecomment-998160737 - - # stdlib -import inspect -import threading from typing import Any -from typing import Dict -from typing import Generator -from typing import Tuple -from typing import Type +from typing import TypeVar +from typing import Union +from typing import final # third party -from pydantic.fields import UndefinedType -from pydantic.main import BaseModel -from pydantic.main import ModelField -from pydantic.main import ModelMetaclass +from pydantic import BaseModel +from pydantic._internal._model_construction import ModelMetaclass # relative -from ..serde.recursive_primitives import recursive_serde_register_type from ..serde.serializable import serializable -TupleGenerator = Generator[Tuple[str, Any], None, None] - - -@serializable() -class Empty: - pass - +_T = TypeVar("_T", bound=BaseModel) -class PartialModelMetaclass(ModelMetaclass): - def __new__( - meta: Type["PartialModelMetaclass"], *args: Any, **kwargs: Any - ) -> "PartialModelMetaclass": - cls = super().__new__(meta, *args, *kwargs) - cls_init = cls.__init__ - # Because the class will be modified temporarily, need to lock __init__ - init_lock = threading.Lock() - # To preserve identical hashes of temporary nested partial models, - # only one instance of each temporary partial class can exist - - def __init__(self: BaseModel, *args: Any, **kwargs: Any) -> None: - with init_lock: - fields = self.__class__.__fields__ - fields_map: Dict[ModelField, Tuple[Any, bool]] = {} - - def optionalize( - fields: Dict[str, ModelField], *, restore: bool = False - ) -> None: - for _, field in fields.items(): - if not restore: - if isinstance(field.required, UndefinedType): - raise Exception(f"{field.name} is a required field.") - fields_map[field] = (field.type_, field.required) - # If field has None allowed as a value - # then it becomes a required field. - if field.allow_none and field.name in kwargs: - field.required = True - else: - field.required = False - if inspect.isclass(field.type_) and issubclass( - field.type_, BaseModel - ): - field.populate_validators() - if field.sub_fields is not None: - for sub_field in field.sub_fields: - sub_field.type_ = field.type_ - sub_field.populate_validators() - optionalize(field.type_.__fields__) - else: - # No need to recursively de-optionalize once original types - # are restored - field.type_, field.required = fields_map[field] - if field.sub_fields is not None: - for sub_field in field.sub_fields: - sub_field.type_ = field.type_ - - # Make fields and fields of nested model types optional - optionalize(fields) - # Transform kwargs that are PartialModels to their dict() forms. This - # will exclude `None` (see below) from the dictionary used to construct - # the temporarily-partial model field, avoiding ValidationErrors of - # type type_error.none.not_allowed. - for kwarg, value in kwargs.items(): - if value.__class__.__class__ is PartialModelMetaclass: - kwargs[kwarg] = value.dict() - elif isinstance(value, (tuple, list)): - kwargs[kwarg] = value.__class__( - v.dict() - if v.__class__.__class__ is PartialModelMetaclass - else v - for v in value - ) +class EmptyType(type): + def __repr__(self) -> str: + return self.__name__ - # Validation is performed in __init__, for which all fields are now optional - cls_init(self, *args, **kwargs) - # Restore requiredness - optionalize(fields, restore=True) + def __bool__(self) -> bool: + return False - cls.__init__ = __init__ - def iter_exclude_empty(self: BaseModel) -> TupleGenerator: - for key, value in self.__dict__.items(): - if value is not Empty: - yield key, value +@serializable() +@final +class Empty(metaclass=EmptyType): + pass - cls.__iter__ = iter_exclude_empty - return cls +class PartialModelMetaclass(ModelMetaclass): + def __call__(cls: type[_T], *args: Any, **kwargs: Any) -> _T: + for field_info in cls.model_fields.values(): + if field_info.annotation is not None and field_info.is_required(): + field_info.annotation = Union[field_info.annotation, EmptyType] + field_info.default = Empty + cls.model_rebuild(force=True) -recursive_serde_register_type(PartialModelMetaclass) + return super().__call__(*args, **kwargs) # type: ignore[misc] diff --git a/packages/syft/src/syft/types/syft_object.py b/packages/syft/src/syft/types/syft_object.py index 8d80d9e368b..214cd867c0d 100644 --- a/packages/syft/src/syft/types/syft_object.py +++ b/packages/syft/src/syft/types/syft_object.py @@ -8,12 +8,15 @@ import inspect from inspect import Signature import re +import sys import traceback import types +import typing from typing import Any from typing import Callable from typing import ClassVar from typing import Dict +from typing import Generator from typing import Iterable from typing import KeysView from typing import List @@ -23,13 +26,18 @@ from typing import Tuple from typing import Type from typing import Union +from typing import get_args +from typing import get_origin import warnings # third party import pandas as pd import pydantic +from pydantic import ConfigDict from pydantic import EmailStr -from pydantic.fields import Undefined +from pydantic import Field +from pydantic import model_validator +from pydantic.fields import PydanticUndefined from result import OkErr from typeguard import check_type from typing_extensions import Self @@ -49,6 +57,14 @@ from .syft_metaclass import PartialModelMetaclass from .uid import UID +if sys.version_info >= (3, 10): + # stdlib + from types import NoneType + from types import UnionType +else: + UnionType = Union + NoneType = type(None) + if TYPE_CHECKING: # relative from ..service.sync.diff_state import AttrDiff @@ -82,6 +98,25 @@ ] +def _is_optional(x: Any) -> bool: + return get_origin(x) in (Optional, UnionType, Union) and any( + arg is NoneType for arg in get_args(x) + ) + + +def _get_optional_inner_type(x: Any) -> Any: + if get_origin(x) not in (Optional, UnionType, Union): + return x + + args = get_args(x) + + if not any(arg is NoneType for arg in args): + return x + + non_none = [arg for arg in args if arg is not NoneType] + return non_none[0] if len(non_none) == 1 else x + + class SyftHashableObject: __hash_exclude_attrs__: list = [] @@ -98,15 +133,14 @@ def hash(self) -> str: class SyftBaseObject(pydantic.BaseModel, SyftHashableObject): - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict(arbitrary_types_allowed=True) # the name which doesn't change even when there are multiple classes __canonical_name__: str __version__: int # data is always versioned - syft_node_location: Optional[UID] - syft_client_verify_key: Optional[SyftVerifyKey] + syft_node_location: Optional[UID] = Field(default=None, exclude=True) + syft_client_verify_key: Optional[SyftVerifyKey] = Field(default=None, exclude=True) def _set_obj_location_(self, node_uid: UID, credentials: SyftVerifyKey) -> None: self.syft_node_location = node_uid @@ -364,18 +398,22 @@ class SyftObject(SyftBaseObject, SyftObjectRegistry, SyftMigrationRegistry): __canonical_name__ = "SyftObject" __version__ = SYFT_OBJECT_VERSION_1 - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict( + arbitrary_types_allowed=True, + json_encoders={UID: str}, + ) # all objects have a UID id: UID # # move this to transforms - @pydantic.root_validator(pre=True) - def make_id(cls, values: Dict[str, Any]) -> Dict[str, Any]: - id_field = cls.__fields__["id"] - if "id" not in values and id_field.required: - values["id"] = id_field.type_() + @model_validator(mode="before") + @classmethod + def make_id(cls, values: Any) -> Any: + if isinstance(values, dict): + id_field = cls.model_fields["id"] + if "id" not in values and id_field.is_required(): + values["id"] = id_field.annotation() return values __attr_searchable__: ClassVar[ @@ -425,7 +463,7 @@ def __str__(self) -> str: def _repr_debug_(self) -> str: class_name = get_qualname_for(type(self)) _repr_str = f"class {class_name}:\n" - fields = getattr(self, "__fields__", {}) + fields = getattr(self, "model_fields", {}) for attr in fields.keys(): if attr in DYNAMIC_SYFT_ATTRIBUTES: continue @@ -546,32 +584,6 @@ def to_dict( new_dict[k] = v return new_dict - def dict( - self, - *, - include: Optional[Union["AbstractSetIntStr", "MappingIntStrAny"]] = None, - exclude: Optional[Union["AbstractSetIntStr", "MappingIntStrAny"]] = None, - by_alias: bool = False, - skip_defaults: Optional[bool] = None, - exclude_unset: bool = False, - exclude_defaults: bool = False, - exclude_none: bool = False, - ) -> dict: - if exclude is None: - exclude = set() - - for attr in DYNAMIC_SYFT_ATTRIBUTES: - exclude.add(attr) # type: ignore - return super().dict( - include=include, - exclude=exclude, - by_alias=by_alias, - skip_defaults=skip_defaults, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, - exclude_none=exclude_none, - ) - def __post_init__(self) -> None: pass @@ -581,18 +593,13 @@ def _syft_set_validate_private_attrs_(self, **kwargs: Any) -> None: for attr, decl in self.__private_attributes__.items(): value = kwargs.get(attr, decl.get_default()) var_annotation = self.__annotations__.get(attr) - if value is not Undefined: - if decl.default_factory: - # If the value is defined via PrivateAttr with default factory - value = decl.default_factory(value) - elif var_annotation is not None: + if value is not PydanticUndefined: + if var_annotation is not None: # Otherwise validate value against the variable annotation check_type(value, var_annotation) setattr(self, attr, value) else: - # check if the private is optional - is_optional_attr = type(None) in getattr(var_annotation, "__args__", []) - if not is_optional_attr: + if not _is_optional(var_annotation): raise ValueError( f"{attr}\n field required (type=value_error.missing)" ) @@ -610,8 +617,8 @@ def __hash__(self) -> int: def _syft_keys_types_dict(cls, attr_name: str) -> Dict[str, type]: kt_dict = {} for key in getattr(cls, attr_name, []): - if key in cls.__fields__: - type_ = cls.__fields__[key].type_ + if key in cls.model_fields: + type_ = _get_optional_inner_type(cls.model_fields[key].annotation) else: try: method = getattr(cls, key) @@ -625,8 +632,9 @@ def _syft_keys_types_dict(cls, attr_name: str) -> Dict[str, type]: # EmailStr seems to be lost every time the value is set even with a validator # this means the incoming type is str so our validators fail - if type(type_) is type and issubclass(type_, EmailStr): + if type_ is EmailStr: type_ = str + kt_dict[key] = type_ return kt_dict @@ -709,6 +717,53 @@ def get_diffs(self, ext_obj: Self) -> List["AttrDiff"]: diff_attrs.append(diff_attr) return diff_attrs + ## OVERRIDING pydantic.BaseModel.__getattr__ + ## return super().__getattribute__(item) -> return self.__getattribute__(item) + ## so that ActionObject.__getattribute__ works properly, + ## raising AttributeError when underlying object does not have the attribute + if not typing.TYPE_CHECKING: + # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access + + def __getattr__(self, item: str) -> Any: + private_attributes = object.__getattribute__(self, "__private_attributes__") + if item in private_attributes: + attribute = private_attributes[item] + if hasattr(attribute, "__get__"): + return attribute.__get__(self, type(self)) # type: ignore + + try: + # Note: self.__pydantic_private__ cannot be None if self.__private_attributes__ has items + return self.__pydantic_private__[item] # type: ignore + except KeyError as exc: + raise AttributeError( + f"{type(self).__name__!r} object has no attribute {item!r}" + ) from exc + else: + # `__pydantic_extra__` can fail to be set if the model is not yet fully initialized. + # See `BaseModel.__repr_args__` for more details + try: + pydantic_extra = object.__getattribute__(self, "__pydantic_extra__") + except AttributeError: + pydantic_extra = None + + if pydantic_extra is not None: + try: + return pydantic_extra[item] + except KeyError as exc: + raise AttributeError( + f"{type(self).__name__!r} object has no attribute {item!r}" + ) from exc + else: + if hasattr(self.__class__, item): + return self.__getattribute__( + item + ) # Raises AttributeError if appropriate + else: + # this is the current error + raise AttributeError( + f"{type(self).__name__!r} object has no attribute {item!r}" + ) + def short_qual_name(name: str) -> str: # If the name is a qualname of formax a.b.c.d we will only get d @@ -903,51 +958,17 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +TupleGenerator = Generator[Tuple[str, Any], None, None] + + class PartialSyftObject(SyftObject, metaclass=PartialModelMetaclass): """Syft Object to which partial arguments can be provided.""" __canonical_name__ = "PartialSyftObject" __version__ = SYFT_OBJECT_VERSION_1 - def __init__(self, *args: Any, **kwargs: Any) -> None: - # Filter out Empty values from args and kwargs - args_, kwargs_ = (), {} - for arg in args: - if arg is not Empty: - args_.append(arg) - - for key, val in kwargs.items(): - if val is not Empty: - kwargs_[key] = val - - super().__init__(*args_, **kwargs_) - - fields_with_default = set() - for _field_name, _field in self.__fields__.items(): - if _field.default is not None or _field.allow_none: - fields_with_default.add(_field_name) - - # Fields whose values are set via a validator hook - fields_set_via_validator = [] - - for _field_name in self.__validators__.keys(): - _field = self.__fields__[_field_name] - if self.__dict__[_field_name] is None: - # Since all fields are None, only allow None - # where either none is allowed or default is None - if _field.allow_none or _field.default is None: - fields_set_via_validator.append(_field) - - # Exclude unset fields - unset_fields = ( - set(self.__fields__) - - set(self.__fields_set__) - - set(fields_set_via_validator) - ) - - empty_fields = unset_fields - fields_with_default - for field_name in empty_fields: - self.__dict__[field_name] = Empty + def __iter__(self) -> TupleGenerator: + yield from ((k, v) for k, v in super().__iter__() if v is not Empty) recursive_serde_register_type(PartialSyftObject) diff --git a/packages/syft/src/syft/types/transforms.py b/packages/syft/src/syft/types/transforms.py index af0be902f2f..1b3a4967ad8 100644 --- a/packages/syft/src/syft/types/transforms.py +++ b/packages/syft/src/syft/types/transforms.py @@ -28,19 +28,19 @@ class NotNone: class TransformContext(Context): - output: Optional[Dict[str, Any]] - node: Optional[AbstractNode] - credentials: Optional[SyftVerifyKey] - obj: Optional[Any] + output: Optional[Dict[str, Any]] = None + node: Optional[AbstractNode] = None + credentials: Optional[SyftVerifyKey] = None + obj: Optional[Any] = None @classmethod def from_context(cls, obj: Any, context: Optional[Context] = None) -> Self: t_context = cls() t_context.obj = obj try: - t_context.output = dict(obj) + t_context.output = obj.to_dict(exclude_empty=True) except Exception: - t_context.output = obj.to_dict() + t_context.output = dict(obj) if context is None: return t_context if hasattr(context, "credentials"): @@ -156,8 +156,7 @@ def validate_url(context: TransformContext) -> TransformContext: def validate_email(context: TransformContext) -> TransformContext: if context.output and context.output["email"] is not None: - context.output["email"] = EmailStr(context.output["email"]) - EmailStr.validate(context.output["email"]) + EmailStr._validate(context.output["email"]) return context diff --git a/packages/syft/src/syft/types/twin_object.py b/packages/syft/src/syft/types/twin_object.py index fe7a0db1495..d06d97d8b77 100644 --- a/packages/syft/src/syft/types/twin_object.py +++ b/packages/syft/src/syft/types/twin_object.py @@ -4,11 +4,12 @@ # stdlib from typing import Any from typing import ClassVar -from typing import Dict from typing import Optional # third party -import pydantic +from pydantic import field_validator +from pydantic import model_validator +from typing_extensions import Self # relative from ..serde.serializable import serializable @@ -26,7 +27,7 @@ def to_action_object(obj: Any) -> ActionObject: if type(obj) in action_types: return action_types[type(obj)](syft_action_data_cache=obj) - raise Exception(f"{type(obj)} not in action_types") + raise ValueError(f"{type(obj)} not in action_types") @serializable() @@ -42,21 +43,27 @@ class TwinObject(SyftObject): mock_obj: ActionObject mock_obj_id: UID = None # type: ignore - @pydantic.validator("private_obj", pre=True, always=True) - def make_private_obj(cls, v: ActionObject) -> ActionObject: + @field_validator("private_obj", mode="before") + @classmethod + def make_private_obj(cls, v: Any) -> ActionObject: return to_action_object(v) - @pydantic.validator("private_obj_id", pre=True, always=True) - def make_private_obj_id(cls, v: Optional[UID], values: Dict) -> UID: - return values["private_obj"].id if v is None else v + @model_validator(mode="after") + def make_private_obj_id(self) -> Self: + if self.private_obj_id is None: + self.private_obj_id = self.private_obj.id # type: ignore[unreachable] + return self - @pydantic.validator("mock_obj", pre=True, always=True) - def make_mock_obj(cls, v: ActionObject) -> ActionObject: + @field_validator("mock_obj", mode="before") + @classmethod + def make_mock_obj(cls, v: Any) -> ActionObject: return to_action_object(v) - @pydantic.validator("mock_obj_id", pre=True, always=True) - def make_mock_obj_id(cls, v: Optional[UID], values: Dict) -> UID: - return values["mock_obj"].id if v is None else v + @model_validator(mode="after") + def make_mock_obj_id(self) -> Self: + if self.mock_obj_id is None: + self.mock_obj_id = self.mock_obj.id # type: ignore[unreachable] + return self @property def private(self) -> ActionObject: diff --git a/packages/syft/tests/syft/action_graph/action_graph_service_test.py b/packages/syft/tests/syft/action_graph/action_graph_service_test.py index 22199150ad3..3cac37f975e 100644 --- a/packages/syft/tests/syft/action_graph/action_graph_service_test.py +++ b/packages/syft/tests/syft/action_graph/action_graph_service_test.py @@ -105,7 +105,6 @@ def test_action_graph_service_add_action_no_mutagen( assert action_node.status == ExecutionStatus.PROCESSING assert action_node.retry == 0 assert isinstance(action_node.created_at, DateTime) - assert action_node.updated_at is None assert action_node.user_verify_key == authed_context.credentials assert action_node.is_mutated is False assert action_node.is_mutagen is False @@ -117,7 +116,6 @@ def test_action_graph_service_add_action_no_mutagen( assert result_node.status == ExecutionStatus.PROCESSING assert result_node.retry == 0 assert isinstance(result_node.created_at, DateTime) - assert result_node.updated_at is None assert result_node.user_verify_key == authed_context.credentials assert result_node.is_mutated is False assert result_node.is_mutagen is False @@ -168,7 +166,6 @@ def test_action_graph_service_add_action_mutagen( assert result_node.id == action.result_id.id assert action_node.type == NodeType.ACTION assert result_node.type == NodeType.ACTION_OBJECT - assert result_node.updated_at is None assert result_node.is_mutated is False assert result_node.is_mutagen is False assert result_node.next_mutagen_node is None diff --git a/packages/syft/tests/syft/action_graph/action_graph_test.py b/packages/syft/tests/syft/action_graph/action_graph_test.py index d01466afa75..8e7e235105a 100644 --- a/packages/syft/tests/syft/action_graph/action_graph_test.py +++ b/packages/syft/tests/syft/action_graph/action_graph_test.py @@ -30,7 +30,7 @@ from syft.service.action.action_object import Action from syft.service.action.action_object import ActionObject from syft.store.document_store import QueryKeys -from syft.store.locks import NoLockingConfig +from syft.store.locks import ThreadingLockingConfig from syft.types.datetime import DateTime from syft.types.syft_metaclass import Empty from syft.types.uid import UID @@ -164,7 +164,7 @@ def test_in_memory_store_client_config() -> None: def test_in_memory_graph_config() -> None: store_config = InMemoryGraphConfig() default_client_conf = InMemoryStoreClientConfig() - locking_config = NoLockingConfig() + locking_config = ThreadingLockingConfig() assert store_config.client_config == default_client_conf assert store_config.store_type == NetworkXBackingStore 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 131b93d70da..d5eefcd7f77 100644 --- a/packages/syft/tests/syft/service/action/action_object_test.py +++ b/packages/syft/tests/syft/service/action/action_object_test.py @@ -25,13 +25,12 @@ 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.types.uid import LineageID +from syft.types.uid import UID def helper_make_action_obj(orig_obj: Any): - obj_id = Action.make_id(None) - lin_obj_id = Action.make_result_id(obj_id) - - return ActionObject.from_obj(orig_obj, id=obj_id, syft_lineage_id=lin_obj_id) + return ActionObject.from_obj(orig_obj) def helper_make_action_pointers(worker, obj, *args, **kwargs): @@ -62,15 +61,13 @@ def helper_make_action_pointers(worker, obj, *args, **kwargs): def test_action_sanity(path_op: Tuple[str, str]): path, op = path_op - remote_self = Action.make_result_id(None) - result_id = Action.make_result_id(None) + remote_self = LineageID() new_action = Action( path=path, op=op, remote_self=remote_self, args=[], kwargs={}, - result_id=result_id, ) assert new_action is not None assert new_action.full_path == f"{path}.{op}" @@ -99,22 +96,22 @@ def test_actionobject_from_obj_sanity(orig_obj: Any): assert obj.syft_history_hash is not None # with id - obj_id = Action.make_id(None) + obj_id = UID() obj = ActionObject.from_obj(orig_obj, id=obj_id) assert obj.id == obj_id assert obj.syft_history_hash == hash(obj_id) # with id and lineage id - obj_id = Action.make_id(None) - lin_obj_id = Action.make_result_id(obj_id) + obj_id = UID() + lin_obj_id = LineageID(obj_id) obj = ActionObject.from_obj(orig_obj, id=obj_id, syft_lineage_id=lin_obj_id) assert obj.id == obj_id assert obj.syft_history_hash == lin_obj_id.syft_history_hash def test_actionobject_from_obj_fail_id_mismatch(): - obj_id = Action.make_id(None) - lineage_id = Action.make_result_id(None) + obj_id = UID() + lineage_id = LineageID() with pytest.raises(ValueError): ActionObject.from_obj("abc", id=obj_id, syft_lineage_id=lineage_id) @@ -131,14 +128,14 @@ def test_actionobject_make_empty_sanity(dtype: Type): assert obj.syft_history_hash is not None # with id - obj_id = Action.make_id(None) + obj_id = UID() obj = ActionObject.empty(syft_internal_type=syft_type, id=obj_id) assert obj.id == obj_id assert obj.syft_history_hash == hash(obj_id) # with id and lineage id - obj_id = Action.make_id(None) - lin_obj_id = Action.make_result_id(obj_id) + obj_id = UID() + lin_obj_id = LineageID(obj_id) obj = ActionObject.empty( syft_internal_type=syft_type, id=obj_id, syft_lineage_id=lin_obj_id ) @@ -163,12 +160,12 @@ def test_actionobject_make_empty_sanity(dtype: Type): def test_actionobject_hooks_init(orig_obj: Any): obj = ActionObject.from_obj(orig_obj) - assert HOOK_ALWAYS in obj._syft_pre_hooks__ - assert HOOK_ALWAYS in obj._syft_post_hooks__ + assert HOOK_ALWAYS in obj.syft_pre_hooks__ + assert HOOK_ALWAYS in obj.syft_post_hooks__ - assert make_action_side_effect in obj._syft_pre_hooks__[HOOK_ALWAYS] - assert send_action_side_effect in obj._syft_pre_hooks__[HOOK_ON_POINTERS] - assert propagate_node_uid in obj._syft_post_hooks__[HOOK_ALWAYS] + assert make_action_side_effect in obj.syft_pre_hooks__[HOOK_ALWAYS] + assert send_action_side_effect in obj.syft_pre_hooks__[HOOK_ON_POINTERS] + assert propagate_node_uid in obj.syft_post_hooks__[HOOK_ALWAYS] @pytest.mark.parametrize( @@ -302,7 +299,7 @@ def test_actionobject_hooks_propagate_node_uid_ok(): orig_obj = "abc" op = "capitalize" - obj_id = Action.make_id(None) + obj_id = UID() obj = ActionObject.from_obj(orig_obj) obj.syft_point_to(obj_id) @@ -315,7 +312,7 @@ def test_actionobject_hooks_propagate_node_uid_ok(): def test_actionobject_syft_point_to(): orig_obj = "abc" - obj_id = Action.make_id(None) + obj_id = UID() obj = ActionObject.from_obj(orig_obj) obj.syft_point_to(obj_id) @@ -587,7 +584,7 @@ def test_actionobject_syft_execute_hooks(worker, testcase): ) assert context.result_id is not None - context.obj.syft_node_uid = Action.make_id(None) + context.obj.syft_node_uid = UID() result = obj_pointer._syft_run_post_hooks__(context, name=op, result=obj_pointer) assert result.syft_node_uid == context.obj.syft_node_uid 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 8b4f1380961..a60bc653c13 100644 --- a/packages/syft/tests/syft/service/dataset/dataset_service_test.py +++ b/packages/syft/tests/syft/service/dataset/dataset_service_test.py @@ -16,6 +16,7 @@ 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 @@ -62,8 +63,9 @@ def make_asset_with_empty_mock() -> dict[str, Any]: def test_asset_without_mock_mock_is_real_must_be_false( asset_without_mock: dict[str, Any], ): - with pytest.raises(ValidationError): - Asset(**asset_without_mock, mock_is_real=True) + asset = Asset(**asset_without_mock, mock_is_real=True) + asset.mock_is_real = True + assert not asset.mock_is_real def test_mock_always_not_real_after_calling_no_mock( @@ -85,8 +87,8 @@ def test_mock_always_not_real_after_set_mock_to_empty( asset.no_mock() assert not asset.mock_is_real - with pytest.raises(ValidationError): - asset.mock_is_real = True + asset.mock_is_real = True + assert not asset.mock_is_real asset.mock = mock() asset.mock_is_real = True @@ -102,8 +104,8 @@ def test_mock_always_not_real_after_set_to_empty( asset.mock = ActionObject.empty() assert not asset.mock_is_real - with pytest.raises(ValidationError): - asset.mock_is_real = True + asset.mock_is_real = True + assert not asset.mock_is_real asset.mock = mock() asset.mock_is_real = True @@ -123,7 +125,7 @@ def test_cannot_set_empty_mock_with_true_mock_is_real( asset = Asset(**asset_with_mock, mock_is_real=True) assert asset.mock_is_real - with pytest.raises(ValidationError): + with pytest.raises(SyftException): asset.set_mock(empty_mock, mock_is_real=True) assert asset.mock is asset_with_mock["mock"] diff --git a/packages/syft/tests/syft/settings/settings_service_test.py b/packages/syft/tests/syft/settings/settings_service_test.py index d0a6def902d..d359eb2848f 100644 --- a/packages/syft/tests/syft/settings/settings_service_test.py +++ b/packages/syft/tests/syft/settings/settings_service_test.py @@ -158,8 +158,12 @@ def mock_stash_get_all(root_verify_key) -> Ok: assert response.is_ok() is True assert len(response.ok()) == len(mock_stash_get_all_output) - assert updated_settings == new_settings # the first settings is updated - assert not_updated_settings == settings # the second settings is not updated + assert ( + updated_settings.model_dump() == new_settings.model_dump() + ) # the first settings is updated + assert ( + not_updated_settings.model_dump() == settings.model_dump() + ) # the second settings is not updated def test_settingsservice_update_stash_get_all_fail( diff --git a/packages/syft/tests/syft/transforms/transform_methods_test.py b/packages/syft/tests/syft/transforms/transform_methods_test.py index 4010e454ce3..40669b0db5d 100644 --- a/packages/syft/tests/syft/transforms/transform_methods_test.py +++ b/packages/syft/tests/syft/transforms/transform_methods_test.py @@ -5,8 +5,8 @@ from typing import Optional # third party -from pydantic import EmailError from pydantic import EmailStr +from pydantic_core import PydanticCustomError import pytest # syft absolute @@ -421,7 +421,7 @@ def __iter__(self): ) result = validate_email(transform_context) assert isinstance(result, TransformContext) - assert isinstance(result.output["email"], EmailStr) + assert EmailStr._validate(result.output["email"]) assert result.output["email"] == mock_obj.email mock_obj = MockObject(email=faker.name()) @@ -429,5 +429,5 @@ def __iter__(self): obj=mock_obj, context=node_context ) - with pytest.raises(EmailError): + with pytest.raises(PydanticCustomError): validate_email(transform_context) diff --git a/packages/syft/tests/syft/users/user_code_test.py b/packages/syft/tests/syft/users/user_code_test.py index 77f3b81e5aa..5720244cfdc 100644 --- a/packages/syft/tests/syft/users/user_code_test.py +++ b/packages/syft/tests/syft/users/user_code_test.py @@ -124,7 +124,9 @@ def func(asset): c for c in request.changes if (isinstance(c, UserCodeStatusChange)) ) - assert status_change.code.assets[0] == asset_input + assert status_change.code.assets[0].model_dump( + mode="json" + ) == asset_input.model_dump(mode="json") @sy.syft_function() diff --git a/packages/syft/tests/syft/users/user_service_test.py b/packages/syft/tests/syft/users/user_service_test.py index 94e3d7a5deb..b372fa5d690 100644 --- a/packages/syft/tests/syft/users/user_service_test.py +++ b/packages/syft/tests/syft/users/user_service_test.py @@ -172,7 +172,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.view(authed_context, uid_to_view) assert isinstance(response, UserView) - assert response == expected_output + assert response.model_dump() == expected_output.model_dump() def test_userservice_get_all_success( @@ -192,7 +192,10 @@ def mock_get_all(credentials: SyftVerifyKey) -> Ok: response = user_service.get_all(authed_context) assert isinstance(response, List) assert len(response) == len(expected_output) - assert response == expected_output + assert all( + r.model_dump() == expected.model_dump() + for r, expected in zip(response, expected_output) + ) def test_userservice_get_all_error( @@ -230,17 +233,27 @@ def mock_find_all(credentials: SyftVerifyKey, **kwargs) -> Union[Ok, Err]: # Search via id response = user_service.search(authed_context, id=guest_user.id) assert isinstance(response, List) - assert response == expected_output + assert all( + r.model_dump() == expected.model_dump() + for r, expected in zip(response, expected_output) + ) + # assert response.model_dump() == expected_output.model_dump() # Search via email response = user_service.search(authed_context, email=guest_user.email) assert isinstance(response, List) - assert response == expected_output + assert all( + r.model_dump() == expected.model_dump() + for r, expected in zip(response, expected_output) + ) # Search via name response = user_service.search(authed_context, name=guest_user.name) assert isinstance(response, List) - assert response == expected_output + assert all( + r.model_dump() == expected.model_dump() + for r, expected in zip(response, expected_output) + ) # Search via verify_key response = user_service.search( @@ -248,14 +261,20 @@ def mock_find_all(credentials: SyftVerifyKey, **kwargs) -> Union[Ok, Err]: verify_key=guest_user.verify_key, ) assert isinstance(response, List) - assert response == expected_output + assert all( + r.model_dump() == expected.model_dump() + for r, expected in zip(response, expected_output) + ) # Search via multiple kwargs response = user_service.search( authed_context, name=guest_user.name, email=guest_user.email ) assert isinstance(response, List) - assert response == expected_output + assert all( + r.model_dump() == expected.model_dump() + for r, expected in zip(response, expected_output) + ) def test_userservice_search_with_invalid_kwargs( diff --git a/packages/syft/tests/syft/worker_test.py b/packages/syft/tests/syft/worker_test.py index 03772951d71..268e03c10c5 100644 --- a/packages/syft/tests/syft/worker_test.py +++ b/packages/syft/tests/syft/worker_test.py @@ -210,8 +210,8 @@ def post_add(context: Any, name: str, new_result: Any) -> Any: # change return type to sum return Ok(sum(new_result)) - action_object._syft_pre_hooks__["__add__"] = [pre_add] - action_object._syft_post_hooks__["__add__"] = [post_add] + action_object.syft_pre_hooks__["__add__"] = [pre_add] + action_object.syft_post_hooks__["__add__"] = [post_add] result = action_object + action_object x = result.syft_action_data @@ -219,8 +219,8 @@ def post_add(context: Any, name: str, new_result: Any) -> Any: assert y == 18 assert x == y - action_object._syft_pre_hooks__["__add__"] = [] - action_object._syft_post_hooks__["__add__"] = [] + action_object.syft_pre_hooks__["__add__"] = [] + action_object.syft_post_hooks__["__add__"] = [] def test_worker_serde() -> None: diff --git a/tox.ini b/tox.ini index 8a18bc6d4ff..97040d2ae71 100644 --- a/tox.ini +++ b/tox.ini @@ -328,16 +328,6 @@ commands = exit $return; \ fi' - ; container workload - bash -c 'if [[ "$PYTEST_MODULES" == *"container_workload"* ]]; then \ - echo "Starting Container Workload test"; date; \ - pytest tests/integration -m container_workload -p no:randomly --co; \ - pytest tests/integration -m container_workload -vvvv -p no:randomly -p no:benchmark -o log_cli=True --capture=no; \ - return=$?; \ - echo "Finished container workload"; date; \ - exit $return; \ - fi' - ; network bash -c 'if [[ "$PYTEST_MODULES" == *"network"* ]]; then \ echo "Starting network"; date; \ @@ -348,6 +338,16 @@ commands = exit $return; \ fi' + ; container workload + bash -c 'if [[ "$PYTEST_MODULES" == *"container_workload"* ]]; then \ + echo "Starting Container Workload test"; date; \ + pytest tests/integration -m container_workload -p no:randomly --co; \ + pytest tests/integration -m container_workload -vvvv -p no:randomly -p no:benchmark -o log_cli=True --capture=no; \ + return=$?; \ + echo "Finished container workload"; date; \ + exit $return; \ + fi' + ; shutdown bash -c "echo Killing Nodes; date" bash -c 'HAGRID_ART=false hagrid land all --force' @@ -1131,4 +1131,4 @@ commands = fi" - pytest notebooks/api/0.8 --nbmake -p no:randomly -vvvv --nbmake-timeout=1000 -k '{env:EXCLUDE_NOTEBOOKS:}' \ No newline at end of file + pytest notebooks/api/0.8 --nbmake -p no:randomly -vvvv --nbmake-timeout=1000 -k '{env:EXCLUDE_NOTEBOOKS:}'