Definition of messages exchanged by the researcher and the nodes
Attributes
Classes
AddScalarReply dataclass
Bases: Message
, RequiresProtocolVersion
Describes a add_scalar message sent by the node.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that receives the reply |
job_id | str | ID of the Job that is sent by researcher |
train | bool | Declares whether scalar value is for training |
test | bool | Declares whether scalar value is for validation |
test_on_local_updates | bool | Declares whether validation is performed over locally updated parameters |
test_on_global_updates | bool | Declares whether validation is performed over aggregated parameters |
metric | dict | Evaluation metroc |
epoch | (int, type(None)) | Scalar is received at |
total_samples | int | Number of all samples in dataset |
batch_samples | int | Number of samples in batch |
num_batches | int | Number of batches in single epoch |
iteration | int | Scalar is received at |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
batch_samples instance-attribute
batch_samples: int
command instance-attribute
command: str
epoch instance-attribute
epoch: (int, type(None))
iteration instance-attribute
iteration: int
job_id instance-attribute
job_id: str
metric instance-attribute
metric: dict
node_id instance-attribute
node_id: str
num_batches instance-attribute
num_batches: int
num_samples_trained instance-attribute
num_samples_trained: (int, type(None))
researcher_id instance-attribute
researcher_id: str
test instance-attribute
test: bool
test_on_global_updates instance-attribute
test_on_global_updates: bool
test_on_local_updates instance-attribute
test_on_local_updates: bool
total_samples instance-attribute
total_samples: int
train instance-attribute
train: bool
ApprovalReply dataclass
Bases: Message
, RequiresProtocolVersion
Describes the TrainingPlan approval reply (acknoledge) from node to researcher.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that will receive the reply |
node_id | str | Node id that replys the request |
sequence | int | sequence number of the corresponding request |
status | int | status code received after uploading the training plan (usually HTTP status) |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
sequence instance-attribute
sequence: int
status instance-attribute
status: int
success instance-attribute
success: bool
ApprovalRequest dataclass
Bases: Message
, RequiresProtocolVersion
Describes the TrainingPlan approval request from researcher to node.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | id of the researcher that sends the request |
description | str | description of the training plan |
sequence | int | (unique) sequence number which identifies the message |
training_plan_url | str | URL where TrainingPlan is available |
command | str | request command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
description instance-attribute
description: str
researcher_id instance-attribute
researcher_id: str
sequence instance-attribute
sequence: int
training_plan_url instance-attribute
training_plan_url: str
ErrorMessage dataclass
Bases: Message
, RequiresProtocolVersion
Describes an error message sent by the node.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that receives the error message |
node_id | str | ID of the node that sends error message |
errnum | ErrorNumbers | Error ID/Number |
extra_msg | str | Additional message regarding the error |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
errnum instance-attribute
errnum: ErrorNumbers
extra_msg instance-attribute
extra_msg: str
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
ListReply dataclass
Bases: Message
, RequiresProtocolVersion
This class describes a list reply message sent by the node that includes list of datasets. It is a reply for ListRequest message from the researcher.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that sends the request |
succes | str | True if the node process the request as expected, false if any exception occurs |
databases | list | List of datasets |
node_id | str | Node id that replys the request |
count | int | Number of datasets |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
count instance-attribute
count: int
databases instance-attribute
databases: list
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
success instance-attribute
success: bool
ListRequest dataclass
Bases: Message
, RequiresProtocolVersion
Describes a list request message sent by the researcher to nodes in order to list datasets belonging to each node.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that sends the request |
command | str | Request command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
researcher_id instance-attribute
researcher_id: str
LogMessage dataclass
Bases: Message
, RequiresProtocolVersion
Describes a log message sent by the node.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that will receive the log message |
node_id | str | ID of the node that sends log message |
level | str | Log level |
msg | str | Log message |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
level instance-attribute
level: str
msg instance-attribute
msg: str
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
Message
Bases: object
Base class for all fedbiomed messages providing all methods to access the messages
The subclasses of this class will be pure data containers (no provided functions)
Functions
get_dict
get_dict()
Returns pairs (Message class attributes name, attributes values) into a dictionary
Returns:
Type | Description |
---|---|
Dict[str, Any] | Message as dictionary |
Source code in fedbiomed/common/message.py
def get_dict(self) -> Dict[str, Any]:
"""Returns pairs (Message class attributes name, attributes values) into a dictionary
Returns:
Message as dictionary
"""
return self.__dict__
get_param
get_param(param)
Get the value of a given param
Parameters:
Name | Type | Description | Default |
---|---|---|---|
param | str | name of the param | required |
Source code in fedbiomed/common/message.py
def get_param(self, param: str):
"""Get the value of a given param
Args:
param: name of the param
"""
return getattr(self, param)
MessageFactory
Pack message contents into the appropriate Message class.
Functions
format_incoming_message classmethod
format_incoming_message(params)
Format a dictionary representing an incoming message into the appropriate Message class.
Packs the input into the appropriate Message class representing an incoming message. The type of Message class is inferred from the command
key in the input dictionary. This function also validates:
- the legacy of the message
- the structure of the received message
Attributes:
Name | Type | Description |
---|---|---|
params | the dictionary of key-value pairs extracted from the received message. |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | if 'command' field is not present in |
FedbiomedMessageError | if the component is not allowed to receive the message |
Returns:
Type | Description |
---|---|
Message | The received message formatted as an instance of the appropriate Message class |
Source code in fedbiomed/common/message.py
@classmethod
def format_incoming_message(cls, params: Dict[str, Any]) -> Message:
"""Format a dictionary representing an incoming message into the appropriate Message class.
Packs the input into the appropriate Message class representing an incoming message.
The type of Message class is inferred from the `command` key in the input dictionary.
This function also validates:
- the legacy of the message
- the structure of the received message
Attributes:
params: the dictionary of key-value pairs extracted from the received message.
Raises:
FedbiomedMessageError: if 'command' field is not present in `params`
FedbiomedMessageError: if the component is not allowed to receive the message
Returns:
The received message formatted as an instance of the appropriate Message class
"""
MessageFactory._raise_for_missing_command(params)
message_type = params['command']
MessageFactory._validate_message_type_or_raise(message_type, cls.INCOMING_MESSAGE_TYPE_TO_CLASS_MAP)
return cls.INCOMING_MESSAGE_TYPE_TO_CLASS_MAP[message_type](**params)
format_outgoing_message classmethod
format_outgoing_message(params)
Format a dictionary representing an outgoing message into the appropriate Message class.
Packs the input into the appropriate Message class representing an outbound message. The type of Message class is inferred from the command
key in the input dictionary. This function also validates:
- the legacy of the message
- the structure of the received message
Attributes:
Name | Type | Description |
---|---|---|
params | the dictionary of key-value pairs to be packed into the outgoing message. |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | if 'command' field is not present in |
FedbiomedMessageError | if the component is not allowed to send the message |
Returns:
Type | Description |
---|---|
Message | The outbound message formatted as an instance of the appropriate Message class |
Source code in fedbiomed/common/message.py
@classmethod
def format_outgoing_message(cls, params: Dict[str, Any]) -> Message:
"""Format a dictionary representing an outgoing message into the appropriate Message class.
Packs the input into the appropriate Message class representing an outbound message.
The type of Message class is inferred from the `command` key in the input dictionary.
This function also validates:
- the legacy of the message
- the structure of the received message
Attributes:
params: the dictionary of key-value pairs to be packed into the outgoing message.
Raises:
FedbiomedMessageError: if 'command' field is not present in `params`
FedbiomedMessageError: if the component is not allowed to send the message
Returns:
The outbound message formatted as an instance of the appropriate Message class
"""
MessageFactory._raise_for_missing_command(params)
message_type = params['command']
MessageFactory._validate_message_type_or_raise(message_type, cls.OUTGOING_MESSAGE_TYPE_TO_CLASS_MAP)
params['protocol_version'] = str(__messaging_protocol_version__) # inject procotol version only in outgoing msg
return cls.OUTGOING_MESSAGE_TYPE_TO_CLASS_MAP[message_type](**params)
NodeMessages
Bases: MessageFactory
Specializes MessageFactory for Node.
Node send replies and receive requests.
Attributes
INCOMING_MESSAGE_TYPE_TO_CLASS_MAP class-attribute
instance-attribute
INCOMING_MESSAGE_TYPE_TO_CLASS_MAP = {'train': TrainRequest, 'search': SearchRequest, 'ping': PingRequest, 'list': ListRequest, 'training-plan-status': TrainingPlanStatusRequest, 'approval': ApprovalRequest, 'secagg': SecaggRequest, 'secagg-delete': SecaggDeleteRequest}
OUTGOING_MESSAGE_TYPE_TO_CLASS_MAP class-attribute
instance-attribute
OUTGOING_MESSAGE_TYPE_TO_CLASS_MAP = {'train': TrainReply, 'search': SearchReply, 'pong': PingReply, 'log': LogMessage, 'error': ErrorMessage, 'add_scalar': AddScalarReply, 'list': ListReply, 'training-plan-status': TrainingPlanStatusReply, 'approval': ApprovalReply, 'secagg': SecaggReply, 'secagg-delete': SecaggDeleteReply}
PingReply dataclass
Bases: Message
, RequiresProtocolVersion
This class describes a ping message sent by the node.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that will receive the reply |
node_id | str | Node id that replys the request |
succes | str | True if the node process the request as expected, false if any exception occurs |
sequence | int | Ping sequence |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
sequence instance-attribute
sequence: int
success instance-attribute
success: bool
PingRequest dataclass
Bases: Message
, RequiresProtocolVersion
Describes a ping message sent by the researcher
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that send ping reqeust |
sequence | int | Ping sequence |
command | str | Request command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
researcher_id instance-attribute
researcher_id: str
sequence instance-attribute
sequence: int
RequiresProtocolVersion dataclass
Mixin class for messages that must be endowed with a version field.
Attributes:
Name | Type | Description |
---|---|---|
protocol_version | str | version of the messaging protocol used |
Attributes
protocol_version instance-attribute
protocol_version: str
ResearcherMessages
Bases: MessageFactory
Specializes MessageFactory for Researcher.
Researchers send requests and receive replies.
Attributes
INCOMING_MESSAGE_TYPE_TO_CLASS_MAP class-attribute
instance-attribute
INCOMING_MESSAGE_TYPE_TO_CLASS_MAP = {'train': TrainReply, 'search': SearchReply, 'pong': PingReply, 'log': LogMessage, 'error': ErrorMessage, 'list': ListReply, 'add_scalar': AddScalarReply, 'training-plan-status': TrainingPlanStatusReply, 'approval': ApprovalReply, 'secagg': SecaggReply, 'secagg-delete': SecaggDeleteReply}
OUTGOING_MESSAGE_TYPE_TO_CLASS_MAP class-attribute
instance-attribute
OUTGOING_MESSAGE_TYPE_TO_CLASS_MAP = {'train': TrainRequest, 'search': SearchRequest, 'ping': PingRequest, 'list': ListRequest, 'training-plan-status': TrainingPlanStatusRequest, 'approval': ApprovalRequest, 'secagg': SecaggRequest, 'secagg-delete': SecaggDeleteRequest}
SearchReply dataclass
Bases: Message
, RequiresProtocolVersion
Describes a search message sent by the node
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that sends the request |
succes | str | True if the node process the request as expected, false if any exception occurs |
databases | list | List of datasets |
node_id | str | Node id that replys the request |
count | int | Number of datasets |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
count instance-attribute
count: int
databases instance-attribute
databases: list
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
success instance-attribute
success: bool
SearchRequest dataclass
Bases: Message
, RequiresProtocolVersion
Describes a search message sent by the researcher.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that sends the request |
tags | list | Tags for search request |
command | str | Request command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
researcher_id instance-attribute
researcher_id: str
tags instance-attribute
tags: list
SecaggDeleteReply dataclass
Bases: Message
, RequiresProtocolVersion
Describes a secagg context element delete reply message sent by the node
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that requests deletion |
secagg_id | str | ID of secagg context element that is sent by researcher |
sequence | int | (unique) sequence number which identifies the message |
success | bool | True if the node process the request as expected, false if any exception occurs |
node_id | str | Node id that replies to the request |
msg | str | Custom message |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
msg instance-attribute
msg: str
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
secagg_id instance-attribute
secagg_id: str
sequence instance-attribute
sequence: int
success instance-attribute
success: bool
SecaggDeleteRequest dataclass
Bases: Message
, RequiresProtocolVersion
Describes a secagg context element delete request message sent by the researcher
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that requests deletion |
secagg_id | str | ID of secagg context element that is sent by researcher |
sequence | int | (unique) sequence number which identifies the message |
element | int | Type of secagg context element |
job_id | (str, type(None)) | Id of the Job to which this secagg context element is attached |
command | str | Request command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
element instance-attribute
element: int
job_id instance-attribute
job_id: (str, type(None))
researcher_id instance-attribute
researcher_id: str
secagg_id instance-attribute
secagg_id: str
sequence instance-attribute
sequence: int
SecaggReply dataclass
Bases: Message
, RequiresProtocolVersion
Describes a secagg context element setup reply message sent by the node
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that requests setup |
secagg_id | str | ID of secagg context element that is sent by researcher |
sequence | int | (unique) sequence number which identifies the message |
success | bool | True if the node process the request as expected, false if any exception occurs |
node_id | str | Node id that replies to the request |
msg | str | Custom message |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
msg instance-attribute
msg: str
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
secagg_id instance-attribute
secagg_id: str
sequence instance-attribute
sequence: int
success instance-attribute
success: bool
SecaggRequest dataclass
Bases: Message
, RequiresProtocolVersion
Describes a secagg context element setup request message sent by the researcher
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that requests setup |
secagg_id | str | ID of secagg context element that is sent by researcher |
sequence | int | (unique) sequence number which identifies the message |
element | int | Type of secagg context element |
job_id | (str, type(None)) | Id of the Job to which this secagg context element is attached |
parties | list | List of parties participating to the secagg context element setup |
command | str | Request command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
element instance-attribute
element: int
job_id instance-attribute
job_id: (str, type(None))
parties instance-attribute
parties: list
researcher_id instance-attribute
researcher_id: str
secagg_id instance-attribute
secagg_id: str
sequence instance-attribute
sequence: int
TrainReply dataclass
Bases: Message
, RequiresProtocolVersion
Describes a train message sent by the node.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that receives the reply |
job_id | str | Id of the Job that is sent by researcher |
success | bool | True if the node process the request as expected, false if any exception occurs |
node_id | str | Node id that replys the request |
dataset_id | str | id of the dataset that is used for training |
params_url | str | URL of parameters uploaded by node |
timing | dict | Timing statistics |
msg | str | Custom message |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
dataset_id instance-attribute
dataset_id: str
job_id instance-attribute
job_id: str
msg instance-attribute
msg: str
node_id instance-attribute
node_id: str
params_url instance-attribute
params_url: str
researcher_id instance-attribute
researcher_id: str
sample_size instance-attribute
sample_size: (int, type(None))
state_id instance-attribute
state_id: (str, type(None))
success instance-attribute
success: bool
timing instance-attribute
timing: dict
TrainRequest dataclass
Bases: Message
, RequiresProtocolVersion
Describes a train message sent by the researcher
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | ID of the researcher that requests training |
job_id | str | Id of the Job that is sent by researcher |
params_url | str | URL where model parameters are uploaded |
training_args | dict | Arguments for training routine |
dataset_id | str | id of the dataset that is used for training |
training | bool | Declares whether training will be performed |
model_args | dict | Arguments to initialize training plan class |
training_plan_url | str | URL where TrainingPlan is available |
training_plan_class | str | Class name of the training plan |
command | str | Reply command string |
aggregator_args | dict | ?? |
aux_var_urls | (list, type(None)) | Optional list of URLs where Optimizer auxiliary variables files are available |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
aggregator_args instance-attribute
aggregator_args: dict
aux_var_urls instance-attribute
aux_var_urls: (list, type(None))
command instance-attribute
command: str
dataset_id instance-attribute
dataset_id: str
job_id instance-attribute
job_id: str
model_args instance-attribute
model_args: dict
params_url instance-attribute
params_url: str
researcher_id instance-attribute
researcher_id: str
round instance-attribute
round: int
secagg_biprime_id instance-attribute
secagg_biprime_id: (str, type(None))
secagg_clipping_range instance-attribute
secagg_clipping_range: (int, type(None))
secagg_random instance-attribute
secagg_random: (float, type(None))
secagg_servkey_id instance-attribute
secagg_servkey_id: (str, type(None))
state_id instance-attribute
state_id: (str, type(None))
training instance-attribute
training: bool
training_args instance-attribute
training_args: dict
training_plan_class instance-attribute
training_plan_class: str
training_plan_url instance-attribute
training_plan_url: str
TrainingPlanStatusReply dataclass
Bases: Message
, RequiresProtocolVersion
Describes a training plan approve status check message sent by the node
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that sends the request |
node_id | str | Node id that replys the request |
job_id | str | job id related to the experiment |
succes | str | True if the node process the request as expected, false if any execption occurs |
approval_obligation | Approval mode for node. True, if training plan approval is enabled/required in the node for training. | |
is_approved | True, if the requested training plan is one of the approved training plan by the node | |
msg | str | Message from node based on state of the reply |
training_plan_url | str | The training plan that has been checked for approval |
command | str | Reply command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
approval_obligation instance-attribute
approval_obligation: bool
command instance-attribute
command: str
job_id instance-attribute
job_id: str
msg instance-attribute
msg: str
node_id instance-attribute
node_id: str
researcher_id instance-attribute
researcher_id: str
status instance-attribute
status: str
success instance-attribute
success: bool
training_plan_url instance-attribute
training_plan_url: str
TrainingPlanStatusRequest dataclass
Bases: Message
, RequiresProtocolVersion
Describes a training plan approve status check message sent by the researcher.
Attributes:
Name | Type | Description |
---|---|---|
researcher_id | str | Id of the researcher that sends the request |
job_id | str | Job id related to the experiment. |
training_plan_url | str | The training plan that is going to be checked for approval |
command | str | Request command string |
Raises:
Type | Description |
---|---|
FedbiomedMessageError | triggered if message's fields validation failed |
Attributes
command instance-attribute
command: str
job_id instance-attribute
job_id: str
researcher_id instance-attribute
researcher_id: str
training_plan_url instance-attribute
training_plan_url: str
Functions
catch_dataclass_exception
catch_dataclass_exception(cls)
Encapsulates the init() method of dataclass in order to transform the exceptions sent by the dataclass (TypeError) into our own exception (FedbiomedMessageError)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
cls | Callable | Dataclass to validate | required |
Source code in fedbiomed/common/message.py
def catch_dataclass_exception(cls: Callable):
"""Encapsulates the __init__() method of dataclass in order to transform the exceptions sent
by the dataclass (TypeError) into our own exception (FedbiomedMessageError)
Args:
cls: Dataclass to validate
"""
def __cde_init__(self: Any, *args: list, **kwargs: dict):
"""This is the __init__() replacement.
Its purpose is to catch the TypeError created by the __init__
method of the @dataclass decorator and replace this exception by FedbiomedMessageError
Raises:
FedbiomedMessageError if number/type of arguments is wrong
"""
try:
self.__class__.__dict__['__initial_init__'](self, *args, **kwargs)
except TypeError as e:
# this is the error raised by dataclass if number of parameter is wrong
_msg = ErrorNumbers.FB601.value + ": bad number of parameters: " + str(e)
logger.error(_msg)
raise FedbiomedMessageError(_msg)
@functools.wraps(cls)
def wrap(cls: Callable):
""" Wrapper to the class given as parameter
Class wrapping should keep some attributes (__doc__, etc) of the initial class or the API documentation tools
will be mistaken
"""
cls.__initial_init__ = cls.__init__
setattr(cls, "__init__", __cde_init__)
return cls
return wrap(cls)