def test_list_fields_with_nested_inherited(self, app): api = Api(app) person = api.model('Person', { 'name': fields.String, 'age': fields.Integer }) child = api.inherit('Child', person, { 'attr': fields.String }) family = api.model('Family', { 'children': fields.List(fields.Nested(child)) }) result = mask.apply(family.resolved, 'children{name,attr}') data = {'children': [ {'name': 'John', 'age': 5, 'attr': 'value-john'}, {'name': 'Jane', 'age': 42, 'attr': 'value-jane'}, ]} expected = {'children': [ {'name': 'John', 'attr': 'value-john'}, {'name': 'Jane', 'attr': 'value-jane'}, ]} assert_data(marshal(data, result), expected) # Should leave th original mask untouched assert_data(marshal(data, family), data)
def get_api_dict(api: Api) -> Model: return api.model( 'ParagraphMetadata', { 'paragraph_type': fields.String( description= "paragraph type (header, list_item, list) and etc.", required=True, example="header"), 'predicted_classes': fields.Nested( api.model("Predicts", {'*': wild_any_fields}), allow_null=True, skip_none=True, required=False, description="classification result, where [{type_paragraph: " "probability}]. Probability is the probability that a " "paragraph belongs to a specific paragraph type, " "paragraph type values depends on the input document type" ), 'page_id': fields.Integer(description="page number of begin paragraph", required=False, example=0), 'line_id': fields.Integer(description="line number of begin paragraph", required=True, example=13), '_*': wild_forbid_fields, # don't get private fields '[a-z]*': wild_any_fields })
def test_marshal_with_handle_polymorph(self, app, client): api = Api(app) parent = api.model('Person', { 'name': fields.String, }) child1 = api.inherit('Child1', parent, { 'extra1': fields.String, }) child2 = api.inherit('Child2', parent, { 'extra2': fields.String, }) class Child1(object): name = 'child1' extra1 = 'extra1' class Child2(object): name = 'child2' extra2 = 'extra2' mapping = {Child1: child1, Child2: child2} thing = api.model('Thing', { 'owner': fields.Polymorph(mapping), }) @api.route('/thing-1/') class Thing1Resource(Resource): @api.marshal_with(thing) def get(self): return {'owner': Child1()} @api.route('/thing-2/') class Thing2Resource(Resource): @api.marshal_with(thing) def get(self): return {'owner': Child2()} data = client.get_json('/thing-1/', headers={'X-Fields': 'owner{name}'}) assert data == {'owner': {'name': 'child1'}} data = client.get_json('/thing-1/', headers={'X-Fields': 'owner{extra1}'}) assert data == {'owner': {'extra1': 'extra1'}} data = client.get_json('/thing-2/', headers={'X-Fields': 'owner{name}'}) assert data == {'owner': {'name': 'child2'}}
def get_api_dict(api: Api) -> Model: return api.model( 'DocumentMetadata', { 'file_name': fields.String(description='file name', example="example.odt"), 'size': fields.Integer(description='file size in bytes', example="20060"), 'modified_time': fields.Integer( description= 'modification time of the document in the format UnixTime', example="1590579805"), 'created_time': fields.Integer( description= 'creation time of the document in the format UnixTime', example="1590579805"), 'access_time': fields.Integer( description='file access time in format UnixTime', example="1590579805"), 'file_type': fields.String( description='mime-type file', example="application/vnd.oasis.opendocument.text"), '[a-z]*': wild_any_fields })
def test_marshal_with_expose_mask_header(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return {'name': 'John Doe', 'age': 42, 'boolean': True} specs = client.get_specs() op = specs['paths']['/test/']['get'] assert 'parameters' in op assert len(op['parameters']) == 1 param = op['parameters'][0] assert param['name'] == 'X-Fields' assert param['type'] == 'string' assert param['format'] == 'mask' assert param['in'] == 'header' assert 'required' not in param assert 'default' not in param
def test_marshal_handle_inheritance(self, app): api = Api(app) person = api.model('Person', { 'name': fields.String, 'age': fields.Integer, }) child = api.inherit('Child', person, { 'extra': fields.String, }) data = {'name': 'John Doe', 'age': 42, 'extra': 'extra'} values = ( ('name', { 'name': 'John Doe' }), ('name,extra', { 'name': 'John Doe', 'extra': 'extra' }), ('extra', { 'extra': 'extra' }), ) for value, expected in values: result = marshal(data, child, mask=value) assert result == expected
def test_marshal_does_not_hit_unrequired_attributes(self, app, client): api = Api(app) model = api.model( 'Person', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) class Person(object): def __init__(self, name, age): self.name = name self.age = age @property def boolean(self): raise Exception() @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return Person('John Doe', 42) data = client.get_json('/test/', headers={'X-Fields': '{name,age}'}) assert data == {'name': 'John Doe', 'age': 42}
def test_marshal_with_honour_field_mask_list(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return [{ 'name': 'John Doe', 'age': 42, 'boolean': True }, { 'name': 'Jane Doe', 'age': 33, 'boolean': False }] data = client.get_json('/test/', headers={'X-Fields': '{name,age}'}) assert data == [{ 'name': 'John Doe', 'age': 42, }, { 'name': 'Jane Doe', 'age': 33, }]
def test_marshal_with_expose_custom_mask_header(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return {'name': 'John Doe', 'age': 42, 'boolean': True} app.config['RESTPLUS_MASK_HEADER'] = 'X-Mask' specs = client.get_specs() op = specs['paths']['/test/']['get'] assert 'parameters' in op assert len(op['parameters']) == 1 param = op['parameters'][0] assert param['name'] == 'X-Mask'
def add_failed_validation_handler(api: flask_restx.Api): """ Subscribe error handler for the layaberr.flask_restx.ValidationFailed exception. :param api: The Flask-RestX API that will handle this exception. :return: A tuple that can be used to document this error handler in flask_restx. As in @api.response(*error_response) """ list_item_model = api.model("ValidationFailed", ValidationFailed.list_item_model()) @api.errorhandler(ValidationFailed) @api.response( code=http.HTTPStatus.BAD_REQUEST.value, description=None, model=[list_item_model], ) def handle_exception(failed_validation): return ( ValidationFailed.to_list(failed_validation.errors), http.HTTPStatus.BAD_REQUEST.value, ) return http.HTTPStatus.BAD_REQUEST.value, "Validation failed.", [ list_item_model ]
def get_api_dict(api: Api) -> Model: return api.model('DocumentContent', { 'structure': fields.Nested(TreeNode.get_api_dict(api), readonly=True, description='document content structure'), 'tables': fields.List(fields.Nested(Table.get_api_dict(api), description="tables structure")) })
def test_marshal_with_disabling_mask_header(self, app, client): api = Api(app) model = api.model('Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return { 'name': 'John Doe', 'age': 42, 'boolean': True } app.config['RESTX_MASK_SWAGGER'] = False specs = client.get_specs() op = specs['paths']['/test/']['get'] assert 'parameters' not in op
def get_api_dict(api: Api) -> Model: names = [ "style", "bold", "italic", "underlined", "size", "indentation", "alignment", "table" ] return api.model( 'Annotation', { 'start': fields.Integer(description='annotation start index', required=True, example=0), 'end': fields.Integer(description='annotation end index', required=True, example=4), 'name': fields.String(description='annotation name', required=True, example='bold', enum=names), 'value': fields.String( description= 'annotation value. For example, it may be font size value for size type ' 'or type of alignment for alignment type', required=True, example="left") })
def get_api_dict(api: Api) -> Model: return api.model('IndentationAnnotation', { 'start': fields.Integer(description='annotation start index', required=True, example=0), 'end': fields.Integer(description='annotation end index', required=True, example=4), 'value': fields.String(description='text indentation in twentieths of a point (1/1440 of an inch)', required=True, example="720") })
def get_api_dict(api: Api) -> Model: return api.model( 'AttachAnnotation', { 'value': fields.String(description='ref to table', required=True, example="table fafffa145agh") })
def test_with_readonly(self, app): api = Api(app) nested_fields = api.model('NestedModel', {'name': fields.String}) field = fields.Nested(nested_fields, readonly=True) assert field.__schema__ == { 'readOnly': True, 'allOf': [{'$ref': '#/definitions/NestedModel'}] }
def get_api_dict(api: Api) -> Model: return api.model('StyleAnnotation', { 'start': fields.Integer(description='annotation start index', required=True, example=0), 'end': fields.Integer(description='annotation end index', required=True, example=4), 'value': fields.String(description='style name', required=True, example="heading 1") })
def test_marshal_with_honour_complex_field_mask_header(self, app, client): api = Api(app) person = api.model('Person', person_fields) child = api.inherit('Child', person, { 'attr': fields.String }) family = api.model('Family', { 'father': fields.Nested(person), 'mother': fields.Nested(person), 'children': fields.List(fields.Nested(child)), 'free': fields.List(fields.Raw), }) house = api.model('House', { 'family': fields.Nested(family, attribute='people') }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(house) def get(self): return {'people': { 'father': {'name': 'John', 'age': 42}, 'mother': {'name': 'Jane', 'age': 42}, 'children': [ {'name': 'Jack', 'age': 5, 'attr': 'value-1'}, {'name': 'Julie', 'age': 7, 'attr': 'value-2'}, ], 'free': [ {'key-1': '1-1', 'key-2': '1-2'}, {'key-1': '2-1', 'key-2': '2-2'}, ] }} data = client.get_json('/test/', headers={ 'X-Fields': 'family{father{name},mother{age},children{name,attr},free{key-2}}' }) assert data == {'family': { 'father': {'name': 'John'}, 'mother': {'age': 42}, 'children': [{'name': 'Jack', 'attr': 'value-1'}, {'name': 'Julie', 'attr': 'value-2'}], 'free': [{'key-2': '1-2'}, {'key-2': '2-2'}] }}
def get_api_dict(api: Api) -> Model: return api.model( 'TableMetadata', { 'page_id': fields.Integer(readonly=False, description='table start page number'), 'uid': fields.String(description="table unique id") })
def auth_model(api: Api): return api.model( 'Auth', { '_id': fields.String, 'name': fields.String, 'email': fields.String, 'avatar': fields.String, 'tours': fields.List(fields.Nested(fields.String)) })
def get_api_dict(api: Api, depth: int = 0, name: str = 'TreeNode') -> Model: return api.model( name, { 'node_id': fields.String( description= "Document element identifier. It is unique within one tree (i.e. " "there will be no other such node_id in this tree, but in attachment " "it may occur) The identifier has the form 0.2.1 where each number " "means a serial number at the corresponding level of the hierarchy.", required=True, example="0.2.1"), 'text': fields.String(description="text of node", required=True, example="Закон"), 'annotations': fields.List( fields.Nested(Annotation.get_api_dict(api), description="Text annotations " "(font, size, bold, italic and etc)")), 'metadata': fields.Nested(ParagraphMetadata.get_api_dict(api), skip_none=True, allow_null=False, description="Paragraph meta information"), 'subparagraphs': fields.List( fields.Nested(api.model('others_TreeNode', {})), description= "Node childes (with type 'TreeNode') of structure tree") if depth == get_config()['recursion_deep_subparagraphs'] else fields.List( fields.Nested( TreeNode.get_api_dict( api, depth=depth + 1, name='refTreeNode' + str(depth))), description= "Node childes (with type 'TreeNode') of structure tree") })
def test_with_readonly(self, app): api = Api(app) nested_fields = api.model("NestedModel", {"name": fields.String}) field = fields.Nested(nested_fields, readonly=True) assert field.__schema__ == { "readOnly": True, "allOf": [{ "$ref": "#/definitions/NestedModel" }], }
def init_models(cls, api: Api): cls.label = api.model( 'Label', dict( label_id=fields.String(readOnly=True), name=fields.String(readOnly=True), uri=fields.Url('labels_label'), )) cls.box = api.model( 'Box', dict(top=fields.Float(), left=fields.Float(), bottom=fields.Float(), right=fields.Float())) cls.label_assignment = api.model( 'LabelAssignment', dict( label=fields.Nested(cls.label), label_assignment_id=fields.String(readOnly=True), box=fields.Nested(cls.box, allow_null=True), confidence=fields.Float(), origin=fields.String(), uri=fields.Url('labels_assignment'), )) cls.image = api.model( 'Image', dict( image_id=fields.String(readOnly=True, description='Image ID'), file=fields.String(readOnly=True, description='Image file name'), label_assignments=fields.List(fields.Nested( cls.label_assignment), readOnly=True), url=fields.String(readOnly=True, description='Image file url'), thumbnail_url=fields.String(readOnly=True, description='Thumbnail file url'), uri=fields.Url('images_image'), ))
def get_api_dict(api: Api) -> Model: return api.model( 'Table', { 'cells': fields.List(fields.List( fields.String(description="Cell contains text")), description="matrix of cells"), 'metadata': fields.Nested(TableMetadata.get_api_dict(api), readonly=True, description='Table meta information') })
def experience_model(api: Api): resource_fields = {'type': fields.String, 'source': fields.String} return api.model( 'Experience', { '_id': fields.String, 'content': fields.String, 'name': fields.String, 'rating': fields.Float, 'resources': fields.List(fields.Nested(resource_fields)), 'creationDate': fields.DateTime(), 'avatar': fields.String, })
def __init__(self, api: Api, db: SQLAlchemy, logger=getLogger(__name__)): self.logger = logger models = db.metadata.tables.items() for model in models: __table__ = model[1] table_name = __table__.fullname schema_name = table_name + '_schema' self.schema[schema_name] = ApiModelFactory.auto_generate_meta_form( model) self.entities[table_name] = api.model( table_name, self.schema[schema_name]) logger.info('Factory Online')
def tour_model(api: Api): return api.model( 'Tour', { '_id': fields.String(), 'image': fields.String, 'title': fields.String, 'brief': fields.String, 'description': fields.String, 'location': fields.String, 'duration': fields.String, 'transportType': fields.String, 'rating': fields.Float, 'ratingCount': fields.Integer })
def get_api_dict(api: Api, depth: int = 0, name: str = 'ParsedDocument') -> Model: return api.model( name, { 'content': fields.Nested(DocumentContent.get_api_dict(api), description='Document content structure'), 'metadata': fields.Nested(DocumentMetadata.get_api_dict(api), allow_null=False, skip_none=True, description='Document meta information'), 'version': fields.String( description= 'the version of the program that parsed this document', example="2020.07.11"), 'warnings': fields.List( fields.String( description='list of warnings and possible errors', example="DOCX: seems that document corrupted")), 'attachments': fields.List(fields.Nested( api.model('others_ParsedDocument', {})), description='structure of attachments', required=False) if depth == get_config()['recursion_deep_attachments'] else fields.List( fields.Nested(ParsedDocument.get_api_dict( api, depth=depth + 1, name='refParsedDocument' + str(depth)), description='Attachment structure', required=False)) })
def get_api_dict(api: Api) -> Model: return api.model( 'AlignmentAnnotation', { 'start': fields.Integer(description='annotation start index', required=True, example=0), 'end': fields.Integer(description='annotation end index', required=True, example=4), 'value': fields.String(description='alignment of the text', required=True, example="left", enum=AlignmentAnnotation.valid_values) })
def test_raise_400_on_invalid_mask(self, app, client): api = Api(app) model = api.model('Test', { 'name': fields.String, 'age': fields.Integer, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): pass response = client.get('/test/', headers={'X-Fields': 'name{,missing}'}) assert response.status_code == 400 assert response.content_type == 'application/json'