def test_extensions_restapi_doc_responses_build(self):

        # when statuses are None or not a list|tuple
        #  200 and 500 statuses are defaults
        for status_codes in [None, 'bad']:
            doc_rsps = build_responses(status_codes)
            assert 200 in doc_rsps
            assert 500 in doc_rsps
            assert 404 not in doc_rsps
            assert doc_rsps == {
                200: {'description': 'successful operation'},
                500: {'description': 'internal server error'},
            }

        # statuses can be a list or a tuple of integers
        for status_codes in [[404, 500], (404, 500,)]:
            doc_rsps = build_responses(status_codes)
            assert 200 not in doc_rsps
            assert 404 in doc_rsps
            assert 500 in doc_rsps
            assert doc_rsps == {
                404: {'description': 'item not found', 'schema': ErrorSchema},
                500: {'description': 'internal server error'},
            }

        # status code can be a string (at least parsable to int)
        doc_rsps = build_responses(['200'])
        assert doc_rsps == {200: {'description': 'successful operation'}}
        # status code can also not be in default responses (a.k.a. _RESPONSES)
        doc_rsps = build_responses([300])
        assert doc_rsps == {300: {'description': ''}}

        doc_rsps = build_responses(['bad'])
        assert doc_rsps == {}
Example #2
0
class EventsById(MethodView):
    @auth_required(roles=['building_manager', 'module_data_processor'])
    @api.doc(
        summary='Get event by ID',
        description='''A specific entrypoint to retrieve events according to the
        the ID associated. Useful for testing purpose to ensure the event is
        stored and available as desired.''',
        responses=build_responses([200, 404, 422, 500]))
    @api.response(EventSchema)
    def get(self, event_id):
        """Return an item from its ID"""
        item = db.session.query(Event).get_or_404(event_id)
        # permissions checks
        verify_scope(sites=[item.site_id])
        return item

    @auth_required(roles=['module_data_processor'])
    @api.doc(
        summary='Update existing event',
        description='Update an event from its ID and return the updated event.',
        responses=build_responses([200, 404, 422, 500]))
    @api.arguments(EventSchema)
    @api.response(EventSchema)
    def put(self, update_data, event_id):
        """Update an item from its ID and return updated item"""
        item = db.session.query(Event).get_or_404(event_id)
        # permissions checks
        verify_scope(sites=[item.site_id])
        check_etag(item, etag_schema=EventSchema)
        EventSchema().update_obj(item, update_data)
        db.session.add(item)
        db.session.commit()
        return item

    @auth_required(roles=['module_data_processor'])
    @api.doc(summary='Delete event',
             description='''Delete an event. Requires to have its ID.''',
             responses=build_responses([200, 404, 422, 500]))
    @api.response(code=204)
    def delete(self, event_id):
        """Delete an item from its ID"""
        item = db.session.query(Event).get_or_404(event_id)
        # permissions checks
        verify_scope(sites=[item.site_id])
        check_etag(item, etag_schema=EventSchema)
        db.session.delete(item)
        db.session.commit()
Example #3
0
    def test_extensions_restapi_doc_responses_build_schemas(self):
        class DataSchema(ma.Schema):
            data = ma.fields.String()

        doc_rsps = build_responses([200, 204], schemas={200: DataSchema})
        assert 200 in doc_rsps
        assert 'schema' in doc_rsps[200]
        assert doc_rsps[200]['schema'] == DataSchema
        assert 204 in doc_rsps
        assert 'schema' not in doc_rsps[204]
Example #4
0
class Events(MethodView):
    @auth_required(roles=['building_manager', 'module_data_processor'])
    @api.doc(
        summary='List events',
        description='''This endpoint allows one to retrieve events by any service
plugged to the BEMServer running instance.

Because the set of generated events can be big, the use of filters is recommended. Typical filters can be:

+ localization: through the use of site_id, building_id, floor_id.
+ criticity level.
+ category or sub-category.

Also, ensure you correctly use the `page_size` and `page` parameters in your
calls to get the full list of generated events.''')
    @api.arguments(EventQueryArgsSchema, location='query')
    @api.response(EventSchema(many=True))
    @api.paginate(SQLCursorPage)
    def get(self, args):
        """Return event list"""
        sort = args.pop('sort', ())
        sensor_id = args.pop('sensor_id', None)
        min_start_time = args.pop('min_start_time', None)
        max_start_time = args.pop('max_start_time', None)
        min_end_time = args.pop('min_end_time', None)
        max_end_time = args.pop('max_end_time', None)
        items = db.session.query(Event).filter_by(**args)
        # permissions filter
        uacc = get_user_account()
        if uacc is not None and '*' not in uacc.sites:
            items = items.filter(Event.site_id.in_(uacc.sites))
        if sensor_id is not None:
            items = items.filter(
                Event.sensor_ids.contains('"{}"'.format(sensor_id)))
        if min_start_time is not None:
            items = items.filter(Event.start_time >= min_start_time)
        if max_start_time is not None:
            items = items.filter(Event.start_time < max_start_time)
        if min_end_time is not None:
            items = items.filter(Event.end_time >= min_end_time)
        if max_end_time is not None:
            items = items.filter(Event.end_time < max_end_time)
        # TODO: factorize sort logic (in Schema?)
        for name, direc in sort:
            criterion = getattr(getattr(Event, name),
                                'desc' if direc < 0 else 'asc')()
            items = items.order_by(criterion)
        return items

    @auth_required(roles=['module_data_processor'])
    @api.doc(
        summary='Add a new event',
        description='''Endpoint to be called by services when they output some
        event to BEMServer.<br>**Ensure you use the service_id of your service,
        after registering to the `/services` API!**<br>Additionally, the more
        information/fields are set, the easiest it is for other services to
        use the events you generate.''',
        responses=build_responses([201, 422, 500]))
    @api.arguments(EventSchema)
    @api.response(EventSchema, code=201)
    def post(self, new_data):
        """Create a new event"""
        item = EventSchema().make_obj(new_data)
        # permissions checks
        verify_scope(sites=[item.site_id])
        db.session.add(item)
        db.session.commit()
        return item