Compute a schema around compound documents and sparse fieldsets

    :param Schema schema_cls: the schema class
    :param dict default_kwargs: the schema default kwargs
    :param QueryStringManager qs: qs
    :param list include: the relation field to include data from

    :return Schema schema: the schema computed

def compute_schema(schema_cls, default_kwargs, qs, include):
    """Compute a schema around compound documents and sparse fieldsets

    :param Schema schema_cls: the schema class
    :param dict default_kwargs: the schema default kwargs
    :param QueryStringManager qs: qs
    :param list include: the relation field to include data from

    :return Schema schema: the schema computed
    """
    # manage include_data parameter of the schema
    schema_kwargs = default_kwargs
    schema_kwargs['include_data'] = tuple()

    # collect sub-related_includes
    related_includes = {}

    if include:
        for include_path in include:
            field = include_path.split('.')[0]

            if field not in schema_cls._declared_fields:
                raise InvalidInclude("{} has no attribute {}".format(schema_cls.__name__, field))
            elif not isinstance(schema_cls._declared_fields[field], Relationship):
                raise InvalidInclude("{} is not a relationship attribute of {}".format(field, schema_cls.__name__))

            schema_kwargs['include_data'] += (field, )
            if field not in related_includes:
                related_includes[field] = []
            if '.' in include_path:
                related_includes[field] += ['.'.join(include_path.split('.')[1:])]

    # make sure id field is in only parameter unless marshamllow will raise an Exception
    if schema_kwargs.get('only') is not None and 'id' not in schema_kwargs['only']:
        schema_kwargs['only'] += ('id',)

    # create base schema instance
    schema = schema_cls(**schema_kwargs)

    # manage sparse fieldsets
    if schema.opts.type_ in qs.fields:
        tmp_only = set(schema.declared_fields.keys()) & set(qs.fields[schema.opts.type_])
        if schema.only:
            tmp_only &= set(schema.only)
        schema.only = tuple(tmp_only)

        # make sure again that id field is in only parameter unless marshamllow will raise an Exception
        if schema.only is not None and 'id' not in schema.only:
            schema.only += ('id',)

    # manage compound documents
    if include:
        for include_path in include:
            field = include_path.split('.')[0]
            relation_field = schema.declared_fields[field]
            related_schema_cls = schema.declared_fields[field].__dict__['_Relationship__schema']
            related_schema_kwargs = {}
            if 'context' in default_kwargs:
                related_schema_kwargs['context'] = default_kwargs['context']
            if isinstance(related_schema_cls, SchemaABC):
                related_schema_kwargs['many'] = related_schema_cls.many
                related_schema_cls = related_schema_cls.__class__
            if isinstance(related_schema_cls, str):
                related_schema_cls = class_registry.get_class(related_schema_cls)
            related_schema = compute_schema(related_schema_cls,
                                            related_schema_kwargs,
                                            qs,
                                            related_includes[field] or None)
            relation_field.__dict__['_Relationship__schema'] = related_schema

    return schema