def iter_schemas(marshmallow_schema): """ Build zero or more JSON schemas for a marshmallow schema. Generates: name, schema pairs. """ if not marshmallow_schema: return base_schema = build_schema(marshmallow_schema) base_schema_name = type_name(name_for(marshmallow_schema)) yield base_schema_name, base_schema for name, field in iter_fields(marshmallow_schema): if isinstance(field, fields.Nested): nested_schema = build_schema(field.schema) nested_schema_name = type_name(name_for(field.schema)) yield nested_schema_name, nested_schema for subname, subfield in iter_schemas(field.schema): yield subname, subfield if isinstance(field, fields.List) and isinstance( field.container, fields.Nested): nested_schema = build_schema(field.container.schema) nested_schema_name = type_name(name_for(field.container.schema)) yield nested_schema_name, nested_schema for subname, subfield in iter_schemas(field.container.schema): yield subname, subfield
def make_media_type(self, event_info, discard_event_type=False): if discard_event_type: return created("{}".format(name_for( self.event_store.model_class), )) return created("{}.{}".format( name_for(self.event_store.model_class), event_info.event.event_type.name, ))
def parse_ref(self, field: Field) -> str: """ Parse the reference type for nested fields, if any. """ ref_name = type_name(name_for(field.schema)) return f"#/definitions/{ref_name}"
def build_parameter(field): """ Build a parameter from a marshmallow field. See: https://github.com/marshmallow-code/apispec/blob/dev/apispec/ext/marshmallow/swagger.py#L81 """ if hasattr(field, SWAGGER_TYPE): parameter = resolve_tagged_field(field) elif getattr(field, "enum", None): parameter = resolve_enum_field(field) elif getattr(field, 'as_string', None): parameter = resolve_numeric_string_field(field) elif isinstance(field, TimestampField): parameter = resolve_timestamp_field(field) else: parameter = resolve_default_for_field(field) if field.metadata.get("description"): parameter["description"] = field.metadata["description"] if field.default: parameter["default"] = field.default # nested if isinstance(field, fields.Nested): parameter["$ref"] = "#/definitions/{}".format( type_name(name_for(field.schema))) # arrays if isinstance(field, fields.List): parameter["items"] = build_parameter(field.container) return parameter
def add_responses(swagger_operation, operation, ns, func): """ Add responses to an operation. """ # default error swagger_operation.responses["default"] = build_response( description="An error occcurred", resource=type_name(name_for(ErrorSchema())), ) if getattr(func, "__doc__", None): description = func.__doc__.strip().splitlines()[0] else: description = "{} {}".format(operation.value.name, ns.subject_name) # resource request request_resource = get_request_schema(func) if isinstance(request_resource, string_types): if not hasattr(swagger_operation, "consumes"): swagger_operation.consumes = [] swagger_operation.consumes.append(request_resource) # resources response response_resource = get_response_schema(func) if isinstance(response_resource, string_types): if not hasattr(swagger_operation, "produces"): swagger_operation.produces = [] swagger_operation.produces.append(response_resource) else: swagger_operation.responses[str(operation.value.default_code)] = build_response( description=description, resource=response_resource, )
def body_param(schema): return swagger.BodyParameter(**{ "name": "body", "in": "body", "schema": swagger.JsonReference({ "$ref": "#/definitions/{}".format(type_name(name_for(schema))), }), })
def retrieve(**path_data): resource = definition.func(**path_data) kwargs = dict() identifier = "{}_id".format(name_for(ns.subject)) kwargs[identifier] = resource.id url = ns.url_for(Operation.Retrieve, **kwargs) return redirect(url)
def build_parameter(field): """ Build a parameter from a marshmallow field. See: https://github.com/marshmallow-code/apispec/blob/dev/apispec/ext/marshmallow/swagger.py#L81 """ try: field_type, field_format = FIELD_MAPPINGS[type(field)] except KeyError: if hasattr(field, SWAGGER_TYPE): field_type = getattr(field, SWAGGER_TYPE) field_format = getattr(field, SWAGGER_FORMAT, None) else: logger.exception( "No mapped swagger type for marshmallow field: {}".format( field, )) raise parameter = {} if field_type: parameter["type"] = field_type if field.metadata.get("description"): parameter["description"] = field.metadata["description"] if field_format: parameter["format"] = field_format if field.default: parameter["default"] = field.default # enums enum = getattr(field, "enum", None) if enum: enum_values = [ choice.value if field.by_value else choice.name for choice in enum ] if all((isinstance(enum_value, string_types) for enum_value in enum_values)): enum_type = "string" elif all((is_int(enum_value) for enum_value in enum_values)): enum_type = "integer" else: raise Exception("Cannot infer enum type for field: {}".format( field.name)) parameter["type"] = enum_type parameter["enum"] = enum_values # nested if isinstance(field, fields.Nested): parameter["$ref"] = "#/definitions/{}".format( type_name(name_for(field.schema))) # arrays if isinstance(field, fields.List): parameter["items"] = build_parameter(field.container) return parameter
def test_name_for(): cases = [ ("foo", "foo"), (FooBar, "foo_bar"), (FooBar(), "foo_bar"), (TheBaz, "baz"), (TheBaz(), "baz"), ] for obj, name in cases: assert_that(name_for(obj), is_(equal_to(name)))
def build_response(description, resource=None): """ Build a response definition. """ response = swagger.Response(description=description, ) if resource is not None: response.schema = swagger.JsonReference({ "$ref": "#/definitions/{}".format(type_name(name_for(resource))), }) return response
def retrieve(**path_data): # request_schema is optional for Alias request_data = (load_query_string_data(definition.request_schema) if definition.request_schema else dict()) resource = definition.func(**merge_data(path_data, request_data)) kwargs = dict() identifier = "{}_id".format(name_for(ns.subject)) kwargs[identifier] = resource.id url = ns.url_for(Operation.Retrieve, **kwargs) return redirect(url)
def encode_id_header(resource): """ Generate a header for a newly created resource. Assume `id` attribute convention. """ if not hasattr(resource, "id"): return {} return { "X-{}-Id".format(camelize(name_for(resource))): str(resource.id), }
def build_response(description, resource=None): """ Build a response definition. """ response = swagger.Response( description=description, ) if resource is not None: response.schema = swagger.JsonReference({ "$ref": "#/definitions/{}".format(type_name(name_for(resource))), }) return response
def retrieve(**path_data): # request_schema is optional for Alias request_data = ( load_query_string_data(definition.request_schema) if definition.request_schema else dict() ) resource = definition.func(**merge_data(path_data, request_data)) kwargs = dict() identifier = "{}_id".format(name_for(ns.subject)) kwargs[identifier] = resource.id url = ns.url_for(Operation.Retrieve, **kwargs) return redirect(url)
def encode_id_header(resource): """ Generate a header for a newly created resource. Assume `id` attribute convention. """ if not hasattr(resource, "id"): return {} return { "X-{}-Id".format( camelize(name_for(resource)) ): str(resource.id), }
def add_responses(swagger_operation, operation, ns, func): """ Add responses to an operation. """ # default error swagger_operation.responses["default"] = build_response( description="An error occurred", resource=type_name(name_for(ErrorSchema())), ) if getattr(func, "__doc__", None): description = func.__doc__.strip().splitlines()[0] else: description = "{} {}".format(operation.value.name, ns.subject_name) if operation in (Operation.Upload, Operation.UploadFor): swagger_operation.consumes = [ "multipart/form-data" ] # resource request request_resource = get_request_schema(func) if isinstance(request_resource, str): if not hasattr(swagger_operation, "consumes"): swagger_operation.consumes = [] swagger_operation.consumes.append(request_resource) # resources response response_resource = get_response_schema(func) if isinstance(response_resource, str): if not hasattr(swagger_operation, "produces"): swagger_operation.produces = [] swagger_operation.produces.append(response_resource) elif not response_resource: response_code = ( 204 if operation.value.default_code == 200 else operation.value.default_code ) swagger_operation.responses[str(response_code)] = build_response( description=description, ) else: swagger_operation.responses[str(operation.value.default_code)] = build_response( description=description, resource=response_resource, )
def object_name(self): return name_for(self.object_)
def subject_name(self): return name_for(self.subject)
def identifier_key(self): return "{}_id".format(name_for(self.store.model_class))
def to_tuple(self, schema: Schema) -> Tuple[str, Any]: return type_name(name_for(schema)), self.build(schema)
def definition_name_for_schema(schema_cls): return type_name(name_for(schema_cls))