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

+ 11 - 7
hapic/decorator.py View File

@@ -4,6 +4,7 @@ import typing
4 4
 from http import HTTPStatus
5 5
 
6 6
 # TODO BS 20171010: bottle specific !  # see #5
7
+import marshmallow
7 8
 from bottle import HTTPResponse
8 9
 
9 10
 from hapic.data import HapicData
@@ -338,11 +339,13 @@ class ExceptionHandlerControllerWrapper(ControllerWrapper):
338 339
         self,
339 340
         handled_exception_class: typing.Type[Exception],
340 341
         context: typing.Union[ContextInterface, typing.Callable[[], ContextInterface]],  # nopep8
342
+        schema: marshmallow.Schema,
341 343
         http_code: HTTPStatus=HTTPStatus.INTERNAL_SERVER_ERROR,
342 344
     ) -> None:
343 345
         self.handled_exception_class = handled_exception_class
344 346
         self._context = context
345 347
         self.http_code = http_code
348
+        self.schema = schema
346 349
 
347 350
     @property
348 351
     def context(self) -> ContextInterface:
@@ -363,16 +366,17 @@ class ExceptionHandlerControllerWrapper(ControllerWrapper):
363 366
                 func_kwargs,
364 367
             )
365 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 378
             error_response = self.context.get_response(
375
-                error_dict,
379
+                raw_response,
376 380
                 self.http_code,
377 381
             )
378 382
             return error_response

+ 8 - 0
hapic/doc.py View File

@@ -76,9 +76,13 @@ def bottle_generate_operations(
76 76
 
77 77
     if description.errors:
78 78
         for error in description.errors:
79
+            schema_class = type(error.wrapper.schema)
79 80
             method_operations.setdefault('responses', {})\
80 81
                 [int(error.wrapper.http_code)] = {
81 82
                     'description': str(error.wrapper.http_code),
83
+                    'schema': {
84
+                        '$ref': '#/definitions/{}'.format(schema_class.__name__)  # nopep8
85
+                    }
82 86
                 }
83 87
 
84 88
     # jsonschema based
@@ -155,6 +159,10 @@ class DocGenerator(object):
155 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 166
         for schema in set(schemas):
159 167
             spec.definition(schema.__name__, schema=schema)
160 168
 

+ 11 - 7
hapic/hapic.py View File

@@ -31,18 +31,20 @@ from hapic.processor import ProcessorInterface
31 31
 from hapic.processor import MarshmallowInputProcessor
32 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 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 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 48
 class Hapic(object):
47 49
     def __init__(self):
48 50
         self._buffer = DecorationBuffer()
@@ -277,7 +279,9 @@ class Hapic(object):
277 279
         decoration = ExceptionHandlerControllerWrapper(
278 280
             handled_exception_class,
279 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 287
         def decorator(func):

+ 1 - 1
setup.py View File

@@ -23,7 +23,7 @@ setup(
23 23
     # Versions should comply with PEP440.  For a discussion on single-sourcing
24 24
     # the version across setup.py and the project code, see
25 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 28
     description='HTTP api input/output manager',
29 29
     # long_description=long_description,