def test_serializer_loads_bad_data(): class BirdSchema(BaseSchema): flying = fields.Boolean(required=True) serializer = MsgpackSerializer(BirdSchema) for raw in (packb(0), packb([]), packb({}), b"dummy"): with pytest.raises(SerdeError): serializer.loads(raw)
def any_cmd_req_factory(name: str, *req_types: Type[BaseReq]): # type: ignore[no-untyped-def] assert name.endswith("Req") class AnyCmdReqSchema(OneOfSchemaLegacy): type_field = "cmd" type_schemas = { x.SCHEMA_CLS._declared_fields["cmd"].default: x.SCHEMA_CLS for x in req_types } def get_obj_type(self, obj: Dict[str, object]) -> Optional[str]: return cast(str, obj.get("cmd")) AnyCmdReqSchema.__name__ = f"{name}Schema" serializer = MsgpackSerializer(AnyCmdReqSchema, InvalidMessageError, MessageSerializationError) @classmethod # type: ignore[misc] def load(cls, raw: bytes) -> Dict[Any, Any]: # type: ignore[no-untyped-def, misc] return serializer.loads(raw) fields = {"load": load, "TYPES": req_types} suffix = "Req" for rep_type in req_types: assert rep_type.__name__.endswith(suffix) rep_type_name = rep_type.__name__[: -len(suffix)] assert rep_type_name not in fields fields[rep_type_name] = rep_type return type(name, (), fields)
def cmd_rep_factory( # type: ignore[no-untyped-def] name: str, *rep_types: Type[BaseRep] ): assert name.endswith("Rep") class RepSchema(OneOfSchemaLegacy): type_field = "status" type_schemas = { x.SCHEMA_CLS._declared_fields["status"].default: x.SCHEMA_CLS for x in rep_types } def get_obj_type(self, obj: Dict[str, object]) -> str: return cast(str, obj.get("status")) RepSchema.__name__ = f"{name}Schema" serializer = MsgpackSerializer(RepSchema, InvalidMessageError, MessageSerializationError) @classmethod # type: ignore[misc] def load(cls, raw: bytes) -> Dict[Any, Any]: # type: ignore[no-untyped-def, misc] return serializer.loads(raw) fields = {"load": load, "TYPES": rep_types} for rep_type in rep_types: assert rep_type.__name__.startswith(name) rep_type_name = rep_type.__name__[len(name) :] assert rep_type_name not in fields fields[rep_type_name] = rep_type return type(name, (), fields)
def __new__( # type: ignore[no-untyped-def, misc] cls, name: str, bases: Tuple[type, ...], nmspc: Dict[str, Any] ): # Sanity checks if "SCHEMA_CLS" not in nmspc: raise RuntimeError("Missing attribute `SCHEMA_CLS` in class definition") if not issubclass(nmspc["SCHEMA_CLS"], cls.BASE_SCHEMA_CLS): raise RuntimeError(f"Attribute `SCHEMA_CLS` must inherit {cls.BASE_SCHEMA_CLS!r}") # Special case if we are defining `BaseReq/BaseRep` if nmspc["SCHEMA_CLS"] is not cls.BASE_SCHEMA_CLS: # Sanity check: discriminant field should be defined as check constant discriminant_field = nmspc["SCHEMA_CLS"]._declared_fields.get(cls.DISCRIMINANT_FIELD) if not discriminant_field or not isinstance(discriminant_field, fields.CheckedConstant): raise RuntimeError( f"Attribute `SCHEMA_CLS` must contain a `{cls.DISCRIMINANT_FIELD}` field" ) raw_cls = type.__new__(cls, name, bases, nmspc) # Sanity checks: class SCHEMA_CLS needs to define parents SCHEMA_CLS fields schema_cls_fields = set(nmspc["SCHEMA_CLS"]._declared_fields) bases_schema_cls = (base for base in bases if hasattr(base, "SCHEMA_CLS")) for base in bases_schema_cls: assert ( base.SCHEMA_CLS._declared_fields.keys() # type: ignore[attr-defined] <= schema_cls_fields ) # Sanity check: attr fields need to be defined in SCHEMA_CLS if "__attrs_attrs__" in nmspc: assert {att.name for att in nmspc["__attrs_attrs__"]} <= schema_cls_fields raw_cls.SERIALIZER = MsgpackSerializer( # type: ignore[attr-defined] nmspc["SCHEMA_CLS"], InvalidMessageError, MessageSerializationError ) # Define attribute `BaseTypedReqSchema.TYPE` raw_cls.SCHEMA_CLS.TYPE = raw_cls # type: ignore[attr-defined] return raw_cls
type_field_remove = False type_schemas = { "foreground": ForegroundReqSchema, "new_instance": NewInstanceReqSchema } def get_obj_type(self, obj): return obj["cmd"] class CommandRepSchema(BaseSchema): status = fields.String(required=True) reason = fields.String(allow_none=True) cmd_req_serializer = MsgpackSerializer(CommandReqSchema) cmd_rep_serializer = MsgpackSerializer(CommandRepSchema) DEFAULT_WIN32_MUTEX_NAME = "parsec-cloud" @contextmanager def _install_win32_mutex(mutex_name: str): from parsec.win32 import CreateMutex, CloseHandle, GetLastError, ERROR_ALREADY_EXISTS try: mutex = CreateMutex(None, False, mutex_name) except WindowsError as exc: raise IPCServerError( f"Cannot create mutex `{mutex_name}`: {exc}") from exc
class DeviceFileSchema(OneOfSchema): type_field = "type" type_schemas = { DeviceFileType.PASSWORD: PasswordDeviceFileSchema(), DeviceFileType.RECOVERY: RecoveryDeviceFileSchema(), DeviceFileType.SMARTCARD: SmartcardDeviceFileSchema(), } def get_obj_type(self, obj: Dict[str, object]) -> object: return obj["type"] legacy_key_file_serializer = MsgpackSerializer( LegacyDeviceFileSchema, validation_exc=LocalDeviceValidationError, packing_exc=LocalDevicePackingError, ) key_file_serializer = MsgpackSerializer( DeviceFileSchema, validation_exc=LocalDeviceValidationError, packing_exc=LocalDevicePackingError) def generate_new_device( organization_addr: BackendOrganizationAddr, device_id: Optional[DeviceID] = None, profile: UserProfile = UserProfile.STANDARD, human_handle: Optional[HumanHandle] = None, device_label: Optional[DeviceLabel] = None,
__id__ = fields.String(required=True) __signal__ = fields.EnumCheckedConstant( BackendEvent.PKI_ENROLLMENTS_UPDATED, required=True) organization_id = OrganizationIDField(required=True) class BackendEventSchema(OneOfSchema): type_field = "__signal__" type_schemas = { BackendEvent.DEVICE_CREATED: DeviceCreatedSchema, BackendEvent.INVITE_CONDUIT_UPDATED: InviteConduitUpdatedSchema, BackendEvent.USER_CREATED: UserCreatedSchema, BackendEvent.USER_REVOKED: UserRevokedSchema, BackendEvent.ORGANIZATION_EXPIRED: OrganizationExpiredSchema, BackendEvent.PINGED: PingedSchema, BackendEvent.MESSAGE_RECEIVED: MessageReceivedSchema, BackendEvent.INVITE_STATUS_CHANGED: InviteStatusChangedSchema, BackendEvent.REALM_MAINTENANCE_FINISHED: RealmMaintenanceFinishedSchema, BackendEvent.REALM_MAINTENANCE_STARTED: RealmMaintenanceStartedSchema, BackendEvent.REALM_VLOBS_UPDATED: RealmVlobsUpdatedSchema, BackendEvent.REALM_ROLES_UPDATED: RealmRolesUpdatedSchema, BackendEvent.PKI_ENROLLMENTS_UPDATED: PkiEnrollmentUpdatedSchema, } def get_obj_type(self, obj): return obj["__signal__"] backend_event_serializer = MsgpackSerializer(BackendEventSchema)
def serializer_factory(schema_cls: Type[BaseSchema]) -> MsgpackSerializer: return MsgpackSerializer(schema_cls, InvalidMessageError, MessageSerializationError)
def test_repr_serializer(): class MySchema(BaseSchema): pass serializer = MsgpackSerializer(MySchema) assert repr(serializer) == "MsgpackSerializer(schema=MySchema)"
def serializer_factory(schema_cls): return MsgpackSerializer(schema_cls, InvalidMessageError, MessageSerializationError)
raise NotImplementedError() @staticmethod def can_decrypt(ciphertext: bytes) -> bool: raise NotImplementedError() class PasswordPayloadSchema(BaseSchema): type = fields.CheckedConstant("password", required=True) salt = fields.Bytes(required=True) ciphertext = fields.Bytes(required=True) password_payload_serializer = MsgpackSerializer( PasswordPayloadSchema, validation_exc=LocalDeviceValidationError, packing_exc=LocalDevicePackingError, ) class PasswordDeviceEncryptor(BaseLocalDeviceEncryptor): def __init__(self, password): self.password = password def encrypt(self, plaintext: bytes) -> bytes: """ Raises: LocalDeviceCryptoError LocalDeviceValidationError LocalDevicePackingError """