Browse Source

Merge pull request #17 from algoo/develop

Bastien Sevajol 6 years ago
parent
commit
09aa0598b6
5 changed files with 32 additions and 16 deletions
  1. 1 1
      example_a.py
  2. 11 7
      hapic/decorator.py
  3. 8 0
      hapic/doc.py
  4. 11 7
      hapic/hapic.py
  5. 1 1
      setup.py

+ 1 - 1
example_a.py View File

118
 # print(yaml.dump(ss, default_flow_style=False))
118
 # print(yaml.dump(ss, default_flow_style=False))
119
 # time.sleep(1)
119
 # time.sleep(1)
120
 
120
 
121
-hapic.set_context(hapic.ext.bottle.bottle_context)
121
+hapic.set_context(hapic.ext.bottle.BottleContext())
122
 print(json.dumps(hapic.generate_doc(app)))
122
 print(json.dumps(hapic.generate_doc(app)))
123
 
123
 
124
 app.run(host='localhost', port=8080, debug=True)
124
 app.run(host='localhost', port=8080, debug=True)

+ 11 - 7
hapic/decorator.py View File

4
 from http import HTTPStatus
4
 from http import HTTPStatus
5
 
5
 
6
 # TODO BS 20171010: bottle specific !  # see #5
6
 # TODO BS 20171010: bottle specific !  # see #5
7
+import marshmallow
7
 from bottle import HTTPResponse
8
 from bottle import HTTPResponse
8
 
9
 
9
 from hapic.data import HapicData
10
 from hapic.data import HapicData
338
         self,
339
         self,
339
         handled_exception_class: typing.Type[Exception],
340
         handled_exception_class: typing.Type[Exception],
340
         context: typing.Union[ContextInterface, typing.Callable[[], ContextInterface]],  # nopep8
341
         context: typing.Union[ContextInterface, typing.Callable[[], ContextInterface]],  # nopep8
342
+        schema: marshmallow.Schema,
341
         http_code: HTTPStatus=HTTPStatus.INTERNAL_SERVER_ERROR,
343
         http_code: HTTPStatus=HTTPStatus.INTERNAL_SERVER_ERROR,
342
     ) -> None:
344
     ) -> None:
343
         self.handled_exception_class = handled_exception_class
345
         self.handled_exception_class = handled_exception_class
344
         self._context = context
346
         self._context = context
345
         self.http_code = http_code
347
         self.http_code = http_code
348
+        self.schema = schema
346
 
349
 
347
     @property
350
     @property
348
     def context(self) -> ContextInterface:
351
     def context(self) -> ContextInterface:
363
                 func_kwargs,
366
                 func_kwargs,
364
             )
367
             )
365
         except self.handled_exception_class as exc:
368
         except self.handled_exception_class as exc:
366
-            # TODO: error_dict configurable name, see #4
367
-            # TODO: Who assume error structure ? We have to rethink it, see #4
368
-            error_dict = {
369
-                'error_message': str(exc),
369
+            # TODO: "error_detail" attribute name should be configurable
370
+            # TODO BS 20171013: use overrideable mechanism, error object given
371
+            #  to schema ? see #15
372
+            raw_response = {
373
+                'message': str(exc),
374
+                'code': None,
375
+                'detail': getattr(exc, 'error_detail', {}),
370
             }
376
             }
371
-            if hasattr(exc, 'error_dict'):
372
-                error_dict.update(exc.error_dict)
373
 
377
 
374
             error_response = self.context.get_response(
378
             error_response = self.context.get_response(
375
-                error_dict,
379
+                raw_response,
376
                 self.http_code,
380
                 self.http_code,
377
             )
381
             )
378
             return error_response
382
             return error_response

+ 8 - 0
hapic/doc.py View File

76
 
76
 
77
     if description.errors:
77
     if description.errors:
78
         for error in description.errors:
78
         for error in description.errors:
79
+            schema_class = type(error.wrapper.schema)
79
             method_operations.setdefault('responses', {})\
80
             method_operations.setdefault('responses', {})\
80
                 [int(error.wrapper.http_code)] = {
81
                 [int(error.wrapper.http_code)] = {
81
                     'description': str(error.wrapper.http_code),
82
                     'description': str(error.wrapper.http_code),
83
+                    'schema': {
84
+                        '$ref': '#/definitions/{}'.format(schema_class.__name__)  # nopep8
85
+                    }
82
                 }
86
                 }
83
 
87
 
84
     # jsonschema based
88
     # jsonschema based
155
                     description.output_body.wrapper.processor.schema
159
                     description.output_body.wrapper.processor.schema
156
                 ))
160
                 ))
157
 
161
 
162
+            if description.errors:
163
+                for error in description.errors:
164
+                    schemas.append(type(error.wrapper.schema))
165
+
158
         for schema in set(schemas):
166
         for schema in set(schemas):
159
             spec.definition(schema.__name__, schema=schema)
167
             spec.definition(schema.__name__, schema=schema)
160
 
168
 

+ 11 - 7
hapic/hapic.py View File

31
 from hapic.processor import MarshmallowInputProcessor
31
 from hapic.processor import MarshmallowInputProcessor
32
 from hapic.processor import MarshmallowOutputProcessor
32
 from hapic.processor import MarshmallowOutputProcessor
33
 
33
 
34
-# TODO: Gérer les cas ou c'est une liste la réponse (items, item_nb), see #12
35
-# TODO: Confusion nommage body/json/forms, see #13
36
 
34
 
37
-# _waiting = {}
38
-# _endpoints = {}
39
 class ErrorResponseSchema(marshmallow.Schema):
35
 class ErrorResponseSchema(marshmallow.Schema):
40
-    error_message = marshmallow.fields.String(required=True)
41
-    error_details = marshmallow.fields.Dict(required=True)
36
+    message = marshmallow.fields.String(required=True)
37
+    details = marshmallow.fields.Dict(required=False, missing={})
38
+    code = marshmallow.fields.Raw(missing=None)
39
+
42
 
40
 
43
 _default_global_error_schema = ErrorResponseSchema()
41
 _default_global_error_schema = ErrorResponseSchema()
44
 
42
 
45
 
43
 
44
+# TODO: Gérer les cas ou c'est une liste la réponse (items, item_nb), see #12
45
+# TODO: Confusion nommage body/json/forms, see #13
46
+
47
+
46
 class Hapic(object):
48
 class Hapic(object):
47
     def __init__(self):
49
     def __init__(self):
48
         self._buffer = DecorationBuffer()
50
         self._buffer = DecorationBuffer()
277
         decoration = ExceptionHandlerControllerWrapper(
279
         decoration = ExceptionHandlerControllerWrapper(
278
             handled_exception_class,
280
             handled_exception_class,
279
             context,
281
             context,
280
-            http_code,
282
+            # TODO BS 20171013: Permit schema overriding, see #15
283
+            schema=_default_global_error_schema,
284
+            http_code=http_code,
281
         )
285
         )
282
 
286
 
283
         def decorator(func):
287
         def decorator(func):

+ 1 - 1
setup.py View File

23
     # Versions should comply with PEP440.  For a discussion on single-sourcing
23
     # Versions should comply with PEP440.  For a discussion on single-sourcing
24
     # the version across setup.py and the project code, see
24
     # the version across setup.py and the project code, see
25
     # https://packaging.python.org/en/latest/single_source_version.html
25
     # https://packaging.python.org/en/latest/single_source_version.html
26
-    version='0.0.3.4',
26
+    version='0.0.4',
27
 
27
 
28
     description='HTTP api input/output manager',
28
     description='HTTP api input/output manager',
29
     # long_description=long_description,
29
     # long_description=long_description,