Skip to content
This repository has been archived by the owner on Oct 19, 2022. It is now read-only.

Add support for Apispec / OpenApi #24

Open
bustawin opened this issue Jun 24, 2018 · 7 comments · May be fixed by #25
Open

Add support for Apispec / OpenApi #24

bustawin opened this issue Jun 24, 2018 · 7 comments · May be fixed by #25

Comments

@bustawin
Copy link

OpenApi spec allows defining enumerations, following the JSON Schema validation. Apispec allows generating such OpenApi spec from Marshmallow schemas.

Currently Apispec does not get enumeration information from MarshmallowEnum. It is easy to add support by doing something like the following in the __init__ of the EnumField class:

self.metadata['enum'] = [e.name for e in enum]

metadata is a property of Field that apispec uses to retrieve OpenApi-related fields.

Currently I am achieving the same by doing:

class ApispecEnumField(EnumField):
    def __init__(self, enum, by_value=False, load_by=None, dump_by=None, error='', *args,
                 **kwargs):
        super().__init__(enum, by_value, load_by, dump_by, error, *args, **kwargs)
        self.metadata['enum'] = [e.name for e in enum]

Finally I would like to thank you for your package :-)

@justanr
Copy link
Owner

justanr commented Jun 24, 2018

I'm +1 on this, I'd accept that PR too. One thing it'd need to keep in mind is that the field might expect the enum values to be either their names OR their values and it could change depending on if things are being dumped or loaded.

I've not looked at Apispec so I'm not sure if it supports that particular situation.

@Birne94 Birne94 linked a pull request Aug 15, 2018 that will close this issue
@spumer
Copy link

spumer commented Sep 26, 2019

I think fix should looks like this:

class ApispecEnumField(ma_enum.EnumField):
    def __init__(self, enum_value, by_value=False, load_by=None, dump_by=None, error='', *args, **kwargs):
        super().__init__(enum_value, by_value, load_by, dump_by, error, *args, **kwargs)
        if self.load_by == ma_enum.LoadDumpOptions.name:
            enum_meta = [e.name for e in enum_value]
        elif self.load_by == ma_enum.LoadDumpOptions.value:
            enum_meta = [e.value for e in enum_value]
        else:
            raise NotImplementedError

        self.metadata['enum'] = enum_meta

to show correct Enum values in Openapi/Swagger cause we depends on how data will be dumped or loaded

PS: i rename enum -> enum_value cause it shadows builtin package name

@acoffman
Copy link

acoffman commented Oct 9, 2019

I've run into this exact issue as well, is there any word on merging either #25 or #27 to resolve it? Or anything we can do to help it along? Thanks for a great project!

@h
Copy link

h commented Mar 12, 2020

I added a fork (based on #25) that fixes this issue (while removing the load_by/dump_by ambiguity) at https://github.com/h/marshmallow_enum

This issue hasn't been fixed/merged since 2018, so if anyone else needs support for APISpec with marshmallow, simply run:

$ pip install -e git+https://github.com/h/marshmallow_enum#egg=marshmallow-enum

@Bangertm
Copy link

Just an FYI - as of version 3.0 of APISpec there is support for adding custom extensions for converting fields to OpenAPI properties. See the documentation for an example and the api.

Instead of changing the internal structure of the EnumField to match what builtin function in APISpec it may be simpler to provide a function that translates EnumField to an OpenAPI enum. It may be convenient to include that function in this library as a convenience for users and so that it is always easy to change the internal structure of EnumField without impacting documentation.

@jitka
Copy link

jitka commented May 28, 2020

Hi I also need this feature. Is there any plan to add this feature?

@h would you consider adding your fork with new name to pip?

@avilaton
Copy link

Thanks @Bangertm, here is what your suggestion gives

from marshmallow_enum import EnumField

ma_plugin = MarshmallowPlugin()

def enumfield_custom_field2properties(self, field, **kwargs):
    ret = {}
    if isinstance(field, EnumField):
        ret["type"] = "string"
        if field.by_value:
            values = [e.value for e in field.enum]
        else:
            values = [e.name for e in field.enum]
        ret["enum"] = values
    return ret

ma_plugin.converter.add_attribute_function(enumfield_custom_field2properties)

@jitka consider this workaround.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants