Source code for syft.core.common.uid

# stdlib
from typing import Any
from typing import Optional
import uuid
from uuid import UUID as uuid_type

# third party
from google.protobuf.reflection import GeneratedProtocolMessageType

# syft relative
from ...logger import critical
from ...logger import traceback_and_raise
from ...proto.core.common.common_object_pb2 import UID as UID_PB
from ..common.serde.serializable import Serializable
from ..common.serde.serializable import bind_protobuf


[docs]@bind_protobuf class UID(Serializable): """A unique ID for every Syft object. This object creates a unique ID for every object in the Syft ecosystem. This ID is guaranteed to be unique for the node on which it is initialized and is very likely to be unique across the whole ecosystem (because it is long and randomly generated). Nearly all objects within Syft subclass from this object because nearly all objects need to have a unique ID. The only major exception a the time of writing is the Client object because it just points to another object which itself has an id. There is no other way in Syft to create an ID for any object. """ value: uuid_type
[docs] def __init__(self, value: Optional[uuid_type] = None): """Initializes the internal id using the uuid package. This initializes the object. Normal use for this object is to initialize the constructor with value==None because you want to initialize with a novel ID. The only major exception is deserialization, wherein a UID object is created with a specific id value. :param value: if you want to initialize an object with a specific UID, pass it in here. This is normally only used during deserialization. :type value: uuid.uuid4, optional :return: returns the initialized object :rtype: UID .. code-block:: python from syft.core.common.uid import UID my_id = UID() """ # checks to make sure you've set a proto_type super().__init__() # if value is not set - create a novel and unique ID. if value is None: # for more info on how this UUID is generated: # https://docs.python.org/3/library/uuid.html value = uuid.uuid4() # save the ID's value. Note that this saves the uuid value # itself instead of saving the self.value = value
@staticmethod def from_string(value: str) -> "UID": try: return UID(value=uuid.UUID(value)) except Exception as e: critical(f"Unable to convert {value} to UUID. {e}") traceback_and_raise(e) def __hash__(self) -> int: """Hashes the UID for use in dictionaries and sets A very common use of UID objects is as a key in a dictionary or database. The object must be able to be hashed in order to be used in this way. We take the 128-bit int representation of the value. :return: returns a hash of the object :rtype: int .. note:: Note that this probably gets further hashed into a shorter representation for most python data-structures. .. note:: Note that we assume that any collisions will be very rare and detected by the ObjectStore class in Syft. """ return self.value.int def __eq__(self, other: Any) -> bool: """Checks to see if two UIDs are the same using the internal object This checks to see whether this UID is equal to another UID by comparing whether they have the same .value objects. These objects come with their own __eq__ function which we assume to be correct. :param other: this is the other ID to be compared with :type other: Any (note this must be Any or __eq__ fails on other types) :return: returns True/False based on whether the objects are the same :rtype: bool """ try: return self.value == other.value except Exception: return False def __repr__(self) -> str: """Returns a human-readable version of the ID Return a human-readable representation of the UID with brackets so that it can be easily spotted when nested inside of the human- readable representations of other objects.""" no_dash = str(self.value).replace("-", "") return f"<{type(self).__name__}: {no_dash}>" def char_emoji(self, hex_chars: str) -> str: base = ord("\U0001F642") hex_base = ord("0") code = 0 for char in hex_chars: offset = ord(char) code += offset - hex_base return chr(base + code) def string_emoji(self, string: str, length: int, chunk: int) -> str: output = [] part = string[-length:] while len(part) > 0: part, end = part[:-chunk], part[-chunk:] output.append(self.char_emoji(hex_chars=end)) return "".join(output) def emoji(self) -> str: return f"<UID:{self.string_emoji(string=str(self.value), length=8, chunk=4)}>"
[docs] def repr_short(self) -> str: """Returns a SHORT human-readable version of the ID Return a SHORT human-readable version of the ID which makes it print nicer when embedded (often alongside other UID objects) within other object __repr__ methods.""" return f"..{str(self.value)[-5:]}"
def _object2proto(self) -> UID_PB: """Returns a protobuf serialization of self. As a requirement of all objects which inherit from Serializable, this method transforms the current object into the corresponding Protobuf object so that it can be further serialized. :return: returns a protobuf object :rtype: ProtoUID .. note:: This method is purely an internal method. Please use serialize(object) or one of the other public serialization methods if you wish to serialize an object. """ return UID_PB(value=self.value.bytes) @staticmethod def _proto2object(proto: UID_PB) -> "UID": """Creates a UID from a protobuf As a requirement of all objects which inherit from Serializable, this method transforms a protobuf object into an instance of this class. :return: returns an instance of UID :rtype: UID .. note:: This method is purely an internal method. Please use syft.deserialize() if you wish to deserialize an object. """ return UID(value=uuid.UUID(bytes=proto.value))
[docs] @staticmethod def get_protobuf_schema() -> GeneratedProtocolMessageType: """Return the type of protobuf object which stores a class of this type As a part of serialization and deserialization, we need the ability to lookup the protobuf object type directly from the object type. This static method allows us to do this. Importantly, this method is also used to create the reverse lookup ability within the metaclass of Serializable. In the metaclass, it calls this method and then it takes whatever type is returned from this method and adds an attribute to it with the type of this class attached to it. See the MetaSerializable class for details. :return: the type of protobuf object which corresponds to this class. :rtype: GeneratedProtocolMessageType """ return UID_PB