podhmo/swagger-marshmallow-codegen

customization

podhmo opened this issue · 5 comments

customization
  • overiding base schema class
  • adding type-format
  • adding custom hook

overriding base schema class

class MySchema(Schema):
    class Meta:
        ordered = True
        strict = True

Using Custom Schema class instead of marshmallow.Schema

answer:

from swagger_marshmallow_codegen.driver import Driver


class MyDriver(Driver):
    codegen_factory = Driver.codegen.override(schema_class_path="foo.bar.schema:MySchema"))

adding type-format

definitions:
  person:
    properties:
      id:
        type: string
        format: objectId
      name:
        type: string

then , treating a property type, format = "string", "objectId" as bson.ObjectId

answer

import bson
from swagger_marshmallow_codegen.driver import Driver
from swagger_marshmallow_codegen.dispatcher import TYPE_MAP, Pair, FormatDispatcher, ReprWrapString


class MyDispatcher(FormatDispatcher):
    type_map = {
        Pair(type="string", format="objectId"): "myschema:ObjectId",
        **TYPE_MAP,
    }

    def dispatch_default(self, c, value, field):
        if isinstance(value, bson.ObjectId) or field.get("format") == "objectId":
            c.import_("bson")
            return ReprWrapString("bson.{!r}".format(bson.ObjectId(value)))
        return value


class MyDriver(Driver):
    codegen_factory = Driver.codegen_factory.override(schema_class_path="myschema:MySchema")
    dispatcher_factory = MyDispatcher

myschema.py

import bson
from marshmallow import fields


class ObjectId(fields.String):
    default_error_messages = {
        'invalid_object_id': 'Not a valid bson.ObjectId.',
    }

    def _validated(self, value):
        """Format the value or raise a :exc:`ValidationError` if an error occurs."""
        if value is None:
            return None
        if isinstance(value, bson.ObjectId):
            return value
        try:
            return bson.ObjectId(value)
        except (ValueError, AttributeError):
            self.fail('invalid_object_id')

    def _deserialize(self, value, attr, data):
        return self._validated(value)

    def _serialize(self, value, attr, data):
        if not value:
            return value
        return str(value)

adding custom hook

maybe like below, adding the hook for custom modification.

definitions:
  person:
    properties:
      name:
        type: string
      age:
        type: integer
    required:
      - name
      - age
  person2:
    allOf:
      - $ref: "#/definitions/person"
      - x-override-required:
        - name

work-around, using --driver option.

$ swagger-marshmallow-codegen --driver foo.driver:MyDriver swagger.yaml