def get_parameter_type(self, parameter: Dict[str, Union[str, Dict[str, Any]]], snake_case: bool) -> Argument: ref: Optional[str] = parameter.get('$ref') # type: ignore if ref: parameter = get_ref_body(ref, self.openapi_model_parser, self.components) name: str = parameter["name"] # type: ignore orig_name = name if snake_case: name = stringcase.snakecase(name) content = parameter.get('content') schema: Optional[JsonSchemaObject] = None if content and isinstance(content, dict): content_schema = [ c.get("schema") for c in content.values() if isinstance(c.get("schema"), dict) ] if content_schema: schema = JsonSchemaObject.parse_obj(content_schema[0]) if not schema: schema = JsonSchemaObject.parse_obj(parameter["schema"]) field = DataModelField( name=name, data_type=self.get_data_type(schema, 'parameter'), required=parameter.get("required") or parameter.get("in") == "path", ) self.imports.extend(field.imports) if orig_name != name: has_in = parameter.get('in') if has_in and isinstance(has_in, str): param_is = has_in.lower().capitalize() self.imports.append(Import(from_='fastapi', import_=param_is)) default: Optional[ str] = f"{param_is}({'...' if field.required else repr(schema.default)}, alias='{orig_name}')" else: # https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameterObject # the spec says 'in' is a str type raise TypeError( f'Issue processing parameter for "in", expected a str, but got something else: {str(parameter)}' ) else: default = repr(schema.default) if schema.has_default else None return Argument( name=field.name, type_hint=field.type_hint, default=default, # type: ignore default_value=schema.default, required=field.required, )
def test_json_schema_object_ref_url_json(mocker): parser = JsonSchemaParser('') obj = JsonSchemaObject.parse_obj( {'$ref': 'https://example.com/person.schema.json#/definitions/User'}) mock_get = mocker.patch('httpx.get') mock_get.return_value.text = json.dumps( { "$id": "https://example.com/person.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "User": { "type": "object", "properties": { "name": { "type": "string", } }, } }, }, ) parser.parse_ref(obj, ['Model']) assert (dump_templates(list(parser.results)) == '''class User(BaseModel): name: Optional[str] = None''') parser.parse_ref(obj, ['Model']) mock_get.assert_has_calls([ call('https://example.com/person.schema.json'), ])
def get_parameter_type( self, parameter: Dict[str, Union[str, Dict[str, str]]], snake_case: bool ) -> Argument: schema: JsonSchemaObject = JsonSchemaObject.parse_obj(parameter["schema"]) format_ = schema.format or "default" type_ = json_schema_data_formats[schema.type][format_] name: str = parameter["name"] # type: ignore orig_name = name if snake_case: name = stringcase.snakecase(name) field = DataModelField( name=name, data_type=type_map[type_], required=parameter.get("required") or parameter.get("in") == "path", ) self.imports.extend(field.imports) if orig_name != name: default: Optional[ str ] = f"Query({'...' if field.required else repr(schema.default)}, alias='{orig_name}')" self.imports.append(Import(from_='fastapi', import_='Query')) else: default = repr(schema.default) if 'default' in parameter["schema"] else None return Argument( name=field.name, type_hint=field.type_hint, default=default, # type: ignore default_value=schema.default, required=field.required, )
def response_objects(self) -> List[Response]: responses: List[Response] = [] for status_code, detail in self.responses.items(): ref: Optional[str] = detail.get('$ref') if ref and ref.startswith('#/components/'): content: Dict[str, Any] = get_model_by_path( self.components, ref[13:].split('/') ).get("content", {}) else: content = detail.get("content", {}) contents = {} for content_type, obj in content.items(): contents[content_type] = ( JsonSchemaObject.parse_obj(obj["schema"]) if "schema" in obj else None ) responses.append( Response( status_code=status_code, description=detail.get("description"), contents=contents, ) ) return responses
def test_parse_any_root_object(source_obj, generated_classes): parser = JsonSchemaParser(BaseModel, CustomRootType, data_model_field_type=DataModelField) parser.parse_root_type('AnyObject', JsonSchemaObject.parse_obj(source_obj), []) assert dump_templates(list(parser.results)) == generated_classes
def response_objects(self) -> List[Response]: responses: List[Response] = [] for status_code, detail in self.responses.items(): ref: Optional[str] = detail.get('$ref') if ref: ref_body = get_ref_body(ref, self.openapi_model_parser, self.components) content = ref_body.get("content", {}) description = ref_body.get("description") else: content = detail.get("content", {}) description = detail.get("description") contents = {} for content_type, obj in content.items(): contents[content_type] = ( JsonSchemaObject.parse_obj(obj["schema"]) if "schema" in obj else None ) responses.append( Response( status_code=status_code, description=description, contents=contents, ) ) return responses
def get_parameter_type( self, parameter: Dict[str, Union[str, Dict[str, str]]], snake_case: bool ) -> Argument: ref: Optional[str] = parameter.get('$ref') # type: ignore if ref: parameter = get_ref_body(ref, self.openapi_model_parser, self.components) name: str = parameter["name"] # type: ignore orig_name = name if snake_case: name = stringcase.snakecase(name) schema: JsonSchemaObject = JsonSchemaObject.parse_obj(parameter["schema"]) field = DataModelField( name=name, data_type=self.get_data_type(schema), required=parameter.get("required") or parameter.get("in") == "path", ) self.imports.extend(field.imports) if orig_name != name: default: Optional[ str ] = f"Query({'...' if field.required else repr(schema.default)}, alias='{orig_name}')" self.imports.append(Import(from_='fastapi', import_='Query')) else: default = repr(schema.default) if 'default' in parameter["schema"] else None return Argument( name=field.name, type_hint=field.type_hint, default=default, # type: ignore default_value=schema.default, required=field.required, )
def test_json_schema_object_ref_url(): parser = JsonSchemaParser(BaseModel, CustomRootType, data_model_field_type=DataModelField) obj = JsonSchemaObject.parse_obj({'$ref': 'https://example.org'}) with pytest.raises(NotImplementedError): parser.parse_ref(obj)
def test_json_schema_object_cached_ref_url_yaml(mocker): parser = JsonSchemaParser('') obj = JsonSchemaObject.parse_obj({ 'type': 'object', 'properties': { 'pet': { '$ref': 'https://example.org/schema.yaml#/definitions/Pet' }, 'user': { '$ref': 'https://example.org/schema.yaml#/definitions/User' }, }, }) mock_get = mocker.patch('httpx.get') mock_get.return_value.text = yaml.safe_dump( json.load((DATA_PATH / 'user.json').open())) parser.parse_ref(obj, []) assert (dump_templates(list(parser.results)) == '''class Pet(BaseModel): name: Optional[str] = Field(None, examples=['dog', 'cat']) class User(BaseModel): name: Optional[str] = Field(None, example='ken')''') mock_get.assert_called_once_with('https://example.org/schema.yaml', )
def test_parse_object(source_obj, generated_classes): parser = JsonSchemaParser( data_model_field_type=DataModelFieldBase, source='', ) parser.parse_object('Person', JsonSchemaObject.parse_obj(source_obj), []) assert dump_templates(list(parser.results)) == generated_classes
def get_parameter_type( self, parameter: Dict[str, Union[str, Dict[str, Any]]], snake_case: bool ) -> Argument: ref: Optional[str] = parameter.get('$ref') # type: ignore if ref: parameter = get_ref_body(ref, self.openapi_model_parser, self.components) name: str = parameter["name"] # type: ignore orig_name = name if snake_case: name = stringcase.snakecase(name) content = parameter.get('content') schema: Optional[JsonSchemaObject] = None if content and isinstance(content, dict): content_schema = [ c.get("schema") for c in content.values() if isinstance(c.get("schema"), dict) ] if content_schema: schema = JsonSchemaObject.parse_obj(content_schema[0]) if not schema: schema = JsonSchemaObject.parse_obj(parameter["schema"]) field = DataModelField( name=name, data_type=self.get_data_type(schema, 'parameter'), required=parameter.get("required") or parameter.get("in") == "path", ) self.imports.extend(field.imports) if orig_name != name: default: Optional[ str ] = f"Query({'...' if field.required else repr(schema.default)}, alias='{orig_name}')" self.imports.append(Import(from_='fastapi', import_='Query')) else: default = repr(schema.default) if schema.has_default else None return Argument( name=field.name, type_hint=field.type_hint, default=default, # type: ignore default_value=schema.default, required=field.required, )
def get_parameter_type( self, parameters: ParameterObject, snake_case: bool, path: List[str], ) -> Optional[Argument]: orig_name = parameters.name if snake_case: name = stringcase.snakecase(parameters.name) else: name = parameters.name schema: Optional[JsonSchemaObject] = None data_type: Optional[DataType] = None for content in parameters.content.values(): if isinstance(content.schema_, ReferenceObject): data_type = self.get_ref_data_type(content.schema_.ref) ref_model = self.get_ref_model(content.schema_.ref) schema = JsonSchemaObject.parse_obj(ref_model) else: schema = content.schema_ break if not data_type: if not schema: schema = parameters.schema_ data_type = self.parse_schema(name, schema, [*path, name]) if not schema: return None field = DataModelField( name=name, data_type=data_type, required=parameters.required or parameters.in_ == ParameterLocation.path, ) if orig_name != name: if parameters.in_: param_is = parameters.in_.value.lower().capitalize() self.imports_for_fastapi.append( Import(from_='fastapi', import_=param_is)) default: Optional[ str] = f"{param_is}({'...' if field.required else repr(schema.default)}, alias='{orig_name}')" else: default = repr(schema.default) if schema.has_default else None self.imports_for_fastapi.append(field.imports) self.data_types.append(field.data_type) return Argument( name=field.name, type_hint=field.type_hint, default=default, # type: ignore default_value=schema.default, required=field.required, )
def request_objects(self) -> List[Request]: requests: List[Request] = [] contents: Dict[str, JsonSchemaObject] = {} for content_type, obj in self.requestBody.get('content', {}).items(): contents[content_type] = (JsonSchemaObject.parse_obj(obj['schema']) if 'schema' in obj else None) requests.append( Request( description=self.requestBody.get("description"), contents=contents, required=self.requestBody.get("required") is True, )) return requests
def response_objects(self) -> List[Response]: responses: List[Response] = [] for status_code, detail in self.responses.items(): contents = {} for content_type, obj in detail.get("content", {}).items(): contents[content_type] = (JsonSchemaObject.parse_obj( obj["schema"]) if "schema" in obj else None) responses.append( Response( status_code=status_code, description=detail.get("description"), contents=contents, )) return responses
def test_json_schema_object_ref_url_yaml(mocker): parser = JsonSchemaParser(BaseModel, CustomRootType, data_model_field_type=DataModelField) obj = JsonSchemaObject.parse_obj( {'$ref': 'https://example.org/schema.yaml#/definitions/User'}) mock_get = mocker.patch('httpx.get') mock_get.return_value.text = yaml.safe_dump( json.load((DATA_PATH / 'user.json').open())) parser.parse_ref(obj, ['User']) assert (dump_templates(list(parser.results)) == '''class User(BaseModel): name: Optional[str] = None''') parser.parse_ref(obj, []) mock_get.assert_called_once_with('https://example.org/schema.yaml', )
def request_objects(self) -> List[Request]: requests: List[Request] = [] contents: Dict[str, JsonSchemaObject] = {} ref: Optional[str] = self.requestBody.get('$ref') if ref: request_body = get_ref_body(ref, self.openapi_model_parser, self.components) else: request_body = self.requestBody for content_type, obj in request_body.get('content', {}).items(): contents[content_type] = (JsonSchemaObject.parse_obj(obj['schema']) if 'schema' in obj else None) requests.append( Request( description=request_body.get("description"), contents=contents, required=request_body.get("required") is True, )) return requests
def test_parse_root_type(source_obj, generated_classes): parser = OpenAPIParser('') parser.parse_root_type('Name', JsonSchemaObject.parse_obj(source_obj), []) assert dump_templates(list(parser.results)) == generated_classes
def test_parse_array(source_obj, generated_classes): parser = OpenAPIParser('') parser.parse_array('Pets', JsonSchemaObject.parse_obj(source_obj), []) assert dump_templates(list(parser.results)) == generated_classes
def test_parse_object(source_obj, generated_classes): parser = OpenAPIParser(BaseModel, CustomRootType) parser.parse_object('Pets', JsonSchemaObject.parse_obj(source_obj), []) assert dump_templates(list(parser.results)) == generated_classes
def test_parse_root_type(source_obj, generated_classes): parser = OpenAPIParser(BaseModel, CustomRootType) parsed_templates = parser.parse_root_type( 'Name', JsonSchemaObject.parse_obj(source_obj)) assert dump_templates(list(parsed_templates)) == generated_classes
def test_parse_any_root_object(source_obj, generated_classes): parser = JsonSchemaParser('') parser.parse_root_type('AnyObject', JsonSchemaObject.parse_obj(source_obj), []) assert dump_templates(list(parser.results)) == generated_classes