marshmallow-oneofschema icon indicating copy to clipboard operation
marshmallow-oneofschema copied to clipboard

Pass constructor arguments to new schema instances

Open djlambert opened this issue 5 years ago • 5 comments

Type specific schemas don't respect excludes passed to OneOfSchema.

This adds an __init__ method to the OneOfSchema class so the instantiation arguments can be saved and passed to the type specific schemas when they are created.

djlambert avatar Jul 26 '18 18:07 djlambert

👍 Could really use this!

Clee681 avatar May 02 '19 21:05 Clee681

Closing this, as it has gone stale. Feel free to re-open if this is still relevant.

sloria avatar Jul 14 '19 17:07 sloria

@sloria This is a PR. Rather than closing this as a stale issue, shouldn't you evaluate the PR and the corresponding test?

Clee681 avatar Jul 16 '19 19:07 Clee681

My availability for reviewing PRs for this project has been quite low, unfortunately. I close stale PRs to reduce the maintenance burden. My thought is that if the PRs are still relevant, the author will either re-make the PR or someone will speak up, which you've just done.. so I'll re-open 😅

sloria avatar Jul 16 '19 20:07 sloria

Any updates on this?

I am encountering this problem because I want to do this:

from marshmallow_oneofschema import OneOfSchema
from marshmallow import Schema, fields


class BaseSchema(Schema):
    type = fields.Str()
    status = fields.Str()

class ChildOneSchema(BaseSchema):
    child_one_attr = fields.Str()

class ChildTwoSchema(BaseSchema):
    child_two_attr = fields.Str()

class ChildSchema(OneOfSchema):
    type_field = "type"
    type_schemas = {
        "child_one": ChildOneSchema,
        "child_two": ChildTwoSchema
    }


ChildSchema(only=("status",)).load({"type": "child_one", "status": "updated"})

which raises ValueError: Invalid fields for <ChildSchema(many=False)>: {'status'}.

Note: The PR in its current form would still raise this ValueError because "only" would get passed to the parent Schema, where the field isn't defined.

So it might need to be updated as:

    def __init__(self, *args, **kwargs):
        self._schema_args = args
        self._schema_kwargs = kwargs

        super().__init__(
            many=kwargs.get("many", False),
            partial=kwargs.get("partial", False),
            context=kwargs.get("context", {})
        )

As a workaround I am currently using:

from marshmallow_oneofschema import OneOfSchema as _OneOfSchema

class OneOfSchema(_OneOfSchema):
    def __init__(self, *args, **kwargs):
        self._init_args = args
        self._init_kwargs = kwargs

        # Init with attrs required by OneOfSchema
        super().__init__(
            many=kwargs.get("many", {}),
            partial=kwargs.get("partials", {}),
            context=kwargs.get("context", {})
        )

    @property
    def type_schemas(self):
        _map =  getattr(self, "type_schema_map")

        class _Getter:
            @staticmethod
            def get(key):
                return _map[key](*self._init_args, **self._init_kwargs)

        return _Getter

reritom avatar Jul 14 '22 12:07 reritom