def element_to_objects(
        element: etree.ElementTree, sender: str, sender_key_fetcher:Callable[[str], str]=None, user: UserType =None,
) -> List:
    """Transform an Element to a list of entities recursively.

    Possible child entities are added to each entity ``_children`` list.

    :param tree: Element
    :param sender: Payload sender id
    :param sender_key_fetcher: Function to fetch sender public key. If not given, key will always be fetched
        over network. The function should take sender handle as the only parameter.
    :param user: Optional receiving user object. If given, should have an ``id``.
    :returns: list of entities
    """
    entities = []
    cls = MAPPINGS.get(element.tag)
    if not cls:
        return []

    attrs = xml_children_as_dict(element)
    transformed = transform_attributes(attrs, cls)
    if hasattr(cls, "fill_extra_attributes"):
        transformed = cls.fill_extra_attributes(transformed)
    entity = cls(**transformed)
    # Add protocol name
    entity._source_protocol = "diaspora"
    # Save element object to entity for possible later use
    entity._source_object = etree.tostring(element)
    # Save receiving id to object
    if user:
        entity._receiving_actor_id = user.id
    if issubclass(cls, DiasporaRelayableMixin):
        # If relayable, fetch sender key for validation
        entity._xml_tags = get_element_child_info(element, "tag")
        if sender_key_fetcher:
            entity._sender_key = sender_key_fetcher(entity.actor_id)
        else:
            profile = retrieve_and_parse_profile(entity.handle)
            if profile:
                entity._sender_key = profile.public_key
    else:
        # If not relayable, ensure handles match
        if not check_sender_and_entity_handle_match(sender, entity.handle):
            return []
    try:
        entity.validate()
    except ValueError as ex:
        logger.error("Failed to validate entity %s: %s", entity, ex, extra={
            "attrs": attrs,
            "transformed": transformed,
        })
        return []
    # Extract mentions
    entity._mentions = entity.extract_mentions()
    # Do child elements
    for child in element:
        entity._children.extend(element_to_objects(child, sender, user=user))
    # Add to entities list
    entities.append(entity)
    return entities
def element_to_objects ( element : etree . ElementTree , sender : str , sender_key_fetcher : Callable [ [ str ] , str ] = None , user : UserType = None , ) -> List : entities = [ ] cls = MAPPINGS . get ( element . tag ) if not cls : return [ ] attrs = xml_children_as_dict ( element ) transformed = transform_attributes ( attrs , cls ) if hasattr ( cls , "fill_extra_attributes" ) : transformed = cls . fill_extra_attributes ( transformed ) entity = cls ( ** transformed ) entity . _source_protocol = "diaspora" entity . _source_object = etree . tostring ( element ) if user : entity . _receiving_actor_id = user . id if issubclass ( cls , DiasporaRelayableMixin ) : entity . _xml_tags = get_element_child_info ( element , "tag" ) if sender_key_fetcher : entity . _sender_key = sender_key_fetcher ( entity . actor_id ) else : profile = retrieve_and_parse_profile ( entity . handle ) if profile : entity . _sender_key = profile . public_key else : if not check_sender_and_entity_handle_match ( sender , entity . handle ) : return [ ] try : entity . validate ( ) except ValueError as ex : logger . error ( "Failed to validate entity %s: %s" , entity , ex , extra = { "attrs" : attrs , "transformed" : transformed , } ) return [ ] entity . _mentions = entity . extract_mentions ( ) for child in element : entity . _children . extend ( element_to_objects ( child , sender , user = user ) ) entities . append ( entity ) return entities
Transform an Element to a list of entities recursively.

    Possible child entities are added to each entity ``_children`` list.

    :param tree: Element
    :param sender: Payload sender id
    :param sender_key_fetcher: Function to fetch sender public key. If not given, key will always be fetched
        over network. The function should take sender handle as the only parameter.
    :param user: Optional receiving user object. If given, should have an ``id``.
    :returns: list of entities