kinto 19.4.0__py3-none-any.whl → 19.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of kinto might be problematic. Click here for more details.

Files changed (45) hide show
  1. kinto/core/__init__.py +3 -3
  2. kinto/core/cornice/__init__.py +93 -0
  3. kinto/core/cornice/cors.py +144 -0
  4. kinto/core/cornice/errors.py +40 -0
  5. kinto/core/cornice/pyramidhook.py +373 -0
  6. kinto/core/cornice/renderer.py +89 -0
  7. kinto/core/cornice/resource.py +205 -0
  8. kinto/core/cornice/service.py +641 -0
  9. kinto/core/cornice/util.py +138 -0
  10. kinto/core/cornice/validators/__init__.py +94 -0
  11. kinto/core/cornice/validators/_colander.py +142 -0
  12. kinto/core/cornice/validators/_marshmallow.py +182 -0
  13. kinto/core/cornice_swagger/__init__.py +92 -0
  14. kinto/core/cornice_swagger/converters/__init__.py +21 -0
  15. kinto/core/cornice_swagger/converters/exceptions.py +6 -0
  16. kinto/core/cornice_swagger/converters/parameters.py +90 -0
  17. kinto/core/cornice_swagger/converters/schema.py +249 -0
  18. kinto/core/cornice_swagger/swagger.py +725 -0
  19. kinto/core/cornice_swagger/templates/index.html +73 -0
  20. kinto/core/cornice_swagger/templates/index_script_template.html +21 -0
  21. kinto/core/cornice_swagger/util.py +42 -0
  22. kinto/core/cornice_swagger/views.py +78 -0
  23. kinto/core/errors.py +6 -4
  24. kinto/core/openapi.py +2 -3
  25. kinto/core/permission/memory.py +3 -2
  26. kinto/core/permission/testing.py +6 -0
  27. kinto/core/resource/viewset.py +1 -1
  28. kinto/core/testing.py +1 -1
  29. kinto/core/utils.py +3 -2
  30. kinto/core/views/batch.py +1 -1
  31. kinto/core/views/openapi.py +1 -1
  32. kinto/plugins/admin/VERSION +1 -1
  33. kinto/plugins/admin/build/VERSION +1 -1
  34. kinto/plugins/admin/build/assets/{index-D8oiN37x.css → index-BdpYyatM.css} +1 -1
  35. kinto/plugins/admin/build/assets/{index-BKIg2XW8.js → index-n-QM_iZE.js} +65 -65
  36. kinto/plugins/admin/build/index.html +2 -2
  37. kinto/plugins/flush.py +1 -1
  38. kinto/plugins/openid/views.py +1 -1
  39. kinto/views/contribute.py +2 -1
  40. {kinto-19.4.0.dist-info → kinto-19.6.0.dist-info}/METADATA +3 -4
  41. {kinto-19.4.0.dist-info → kinto-19.6.0.dist-info}/RECORD +45 -24
  42. {kinto-19.4.0.dist-info → kinto-19.6.0.dist-info}/LICENSE +0 -0
  43. {kinto-19.4.0.dist-info → kinto-19.6.0.dist-info}/WHEEL +0 -0
  44. {kinto-19.4.0.dist-info → kinto-19.6.0.dist-info}/entry_points.txt +0 -0
  45. {kinto-19.4.0.dist-info → kinto-19.6.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,90 @@
1
+ """Converts from colander request chema to Swagger parameters."""
2
+
3
+ from kinto.core.cornice_swagger.converters.exceptions import NoSuchConverter
4
+
5
+
6
+ class ParameterConverter(object):
7
+ _in = None
8
+
9
+ def convert(self, schema_node, definition_handler):
10
+ """
11
+ Convert node schema into a parameter object.
12
+ """
13
+
14
+ converted = {"name": schema_node.name, "in": self._in, "required": schema_node.required}
15
+ if schema_node.description:
16
+ converted["description"] = schema_node.description
17
+
18
+ if schema_node.default:
19
+ converted["default"] = schema_node.default
20
+
21
+ schema = definition_handler(schema_node)
22
+ # Parameters shouldn't have a title
23
+ schema.pop("title", None)
24
+ converted.update(schema)
25
+
26
+ if schema.get("type") == "array":
27
+ converted["items"] = {"type": schema["items"]["type"]}
28
+
29
+ return converted
30
+
31
+
32
+ class PathParameterConverter(ParameterConverter):
33
+ _in = "path"
34
+
35
+ def convert(self, schema_node, definition_handler):
36
+ converted = super(PathParameterConverter, self).convert(schema_node, definition_handler)
37
+ # Extract regex pattern from name
38
+ template = converted["name"].split(":", 1)
39
+ if len(template) == 2:
40
+ converted["name"] = template[0]
41
+ converted["pattern"] = template[1]
42
+
43
+ return converted
44
+
45
+
46
+ class QueryParameterConverter(ParameterConverter):
47
+ _in = "query"
48
+
49
+
50
+ class HeaderParameterConverter(ParameterConverter):
51
+ _in = "header"
52
+
53
+
54
+ class BodyParameterConverter(ParameterConverter):
55
+ _in = "body"
56
+
57
+ def convert(self, schema_node, definition_handler):
58
+ converted = {"name": schema_node.name, "in": self._in, "required": schema_node.required}
59
+ if schema_node.description:
60
+ converted["description"] = schema_node.description
61
+
62
+ schema_node.title = schema_node.__class__.__name__
63
+ schema = definition_handler(schema_node)
64
+ converted["schema"] = schema
65
+
66
+ return converted
67
+
68
+
69
+ class ParameterConversionDispatcher(object):
70
+ converters = {
71
+ "body": BodyParameterConverter,
72
+ "path": PathParameterConverter,
73
+ "querystring": QueryParameterConverter,
74
+ "GET": QueryParameterConverter,
75
+ "header": HeaderParameterConverter,
76
+ "headers": HeaderParameterConverter,
77
+ }
78
+
79
+ def __init__(self, definition_handler):
80
+ self.definition_handler = definition_handler
81
+
82
+ def __call__(self, location, schema_node):
83
+ converter_class = self.converters.get(location)
84
+ if converter_class is None:
85
+ raise NoSuchConverter()
86
+
87
+ converter = converter_class()
88
+ converted = converter.convert(schema_node, self.definition_handler)
89
+
90
+ return converted
@@ -0,0 +1,249 @@
1
+ """
2
+ This module handles the conversion between colander object schemas and swagger
3
+ object schemas by converting types and node validators.
4
+ """
5
+
6
+ import colander
7
+
8
+ from kinto.core.cornice_swagger.converters.exceptions import NoSuchConverter
9
+
10
+
11
+ def convert_length_validator_factory(max_key, min_key):
12
+ def validator_converter(validator):
13
+ converted = None
14
+
15
+ if isinstance(validator, colander.Length):
16
+ converted = {}
17
+ if validator.max is not None:
18
+ converted[max_key] = validator.max
19
+ if validator.min is not None:
20
+ converted[min_key] = validator.min
21
+
22
+ return converted
23
+
24
+ return validator_converter
25
+
26
+
27
+ def convert_oneof_validator_factory():
28
+ def validator_converter(validator):
29
+ converted = None
30
+
31
+ if isinstance(validator, colander.OneOf):
32
+ converted = {"enum": list(validator.choices)}
33
+ return converted
34
+
35
+ return validator_converter
36
+
37
+
38
+ def convert_range_validator(validator):
39
+ converted = None
40
+
41
+ if isinstance(validator, colander.Range):
42
+ converted = {}
43
+
44
+ if validator.max is not None:
45
+ converted["maximum"] = validator.max
46
+ if validator.min is not None:
47
+ converted["minimum"] = validator.min
48
+
49
+ return converted
50
+
51
+
52
+ def convert_regex_validator(validator):
53
+ converted = None
54
+
55
+ if isinstance(validator, colander.Regex):
56
+ converted = {}
57
+
58
+ if hasattr(colander, "url") and validator is colander.url:
59
+ converted["format"] = "url"
60
+ elif isinstance(validator, colander.Email):
61
+ converted["format"] = "email"
62
+ else:
63
+ converted["pattern"] = validator.match_object.pattern
64
+
65
+ return converted
66
+
67
+
68
+ class ValidatorConversionDispatcher(object):
69
+ def __init__(self, *converters):
70
+ self.converters = converters
71
+
72
+ def __call__(self, schema_node, validator=None):
73
+ if validator is None:
74
+ validator = schema_node.validator
75
+
76
+ converted = {}
77
+ if validator is not None:
78
+ for converter in (self.convert_all_validator,) + self.converters:
79
+ ret = converter(validator)
80
+ if ret is not None:
81
+ converted = ret
82
+ break
83
+
84
+ return converted
85
+
86
+ def convert_all_validator(self, validator):
87
+ if isinstance(validator, colander.All):
88
+ converted = {}
89
+ for v in validator.validators:
90
+ ret = self(None, v)
91
+ converted.update(ret)
92
+ return converted
93
+ else:
94
+ return None
95
+
96
+
97
+ class TypeConverter(object):
98
+ type = ""
99
+
100
+ def __init__(self, dispatcher):
101
+ self.dispatcher = dispatcher
102
+
103
+ def convert_validator(self, schema_node):
104
+ return {}
105
+
106
+ def convert_type(self, schema_node):
107
+ converted = {"type": self.type}
108
+
109
+ if schema_node.title:
110
+ converted["title"] = schema_node.title
111
+ if schema_node.description:
112
+ converted["description"] = schema_node.description
113
+ if schema_node.missing not in (colander.required, colander.drop, colander.null):
114
+ converted["default"] = schema_node.missing
115
+ if "example" in schema_node.__dict__:
116
+ converted["example"] = schema_node.example
117
+
118
+ return converted
119
+
120
+ def __call__(self, schema_node):
121
+ converted = self.convert_type(schema_node)
122
+ converted.update(self.convert_validator(schema_node))
123
+
124
+ return converted
125
+
126
+
127
+ class BaseStringTypeConverter(TypeConverter):
128
+ type = "string"
129
+ format = None
130
+
131
+ def convert_type(self, schema_node):
132
+ converted = super(BaseStringTypeConverter, self).convert_type(schema_node)
133
+
134
+ if self.format is not None:
135
+ converted["format"] = self.format
136
+
137
+ return converted
138
+
139
+
140
+ class BooleanTypeConverter(TypeConverter):
141
+ type = "boolean"
142
+
143
+
144
+ class DateTypeConverter(BaseStringTypeConverter):
145
+ format = "date"
146
+
147
+
148
+ class DateTimeTypeConverter(BaseStringTypeConverter):
149
+ format = "date-time"
150
+
151
+
152
+ class NumberTypeConverter(TypeConverter):
153
+ type = "number"
154
+
155
+ convert_validator = ValidatorConversionDispatcher(
156
+ convert_range_validator,
157
+ convert_oneof_validator_factory(),
158
+ )
159
+
160
+
161
+ class IntegerTypeConverter(NumberTypeConverter):
162
+ type = "integer"
163
+
164
+
165
+ class StringTypeConverter(BaseStringTypeConverter):
166
+ convert_validator = ValidatorConversionDispatcher(
167
+ convert_length_validator_factory("maxLength", "minLength"),
168
+ convert_regex_validator,
169
+ convert_oneof_validator_factory(),
170
+ )
171
+
172
+
173
+ class TimeTypeConverter(BaseStringTypeConverter):
174
+ format = "time"
175
+
176
+
177
+ class ObjectTypeConverter(TypeConverter):
178
+ type = "object"
179
+
180
+ def convert_type(self, schema_node):
181
+ converted = super(ObjectTypeConverter, self).convert_type(schema_node)
182
+
183
+ properties = {}
184
+ required = []
185
+
186
+ for sub_node in schema_node.children:
187
+ properties[sub_node.name] = self.dispatcher(sub_node)
188
+ if sub_node.required:
189
+ required.append(sub_node.name)
190
+
191
+ if len(properties) > 0:
192
+ converted["properties"] = properties
193
+
194
+ if len(required) > 0:
195
+ converted["required"] = required
196
+
197
+ if schema_node.typ.unknown == "preserve":
198
+ converted["additionalProperties"] = {}
199
+
200
+ return converted
201
+
202
+
203
+ class ArrayTypeConverter(TypeConverter):
204
+ type = "array"
205
+
206
+ convert_validator = ValidatorConversionDispatcher(
207
+ convert_length_validator_factory("maxItems", "minItems"),
208
+ )
209
+
210
+ def convert_type(self, schema_node):
211
+ converted = super(ArrayTypeConverter, self).convert_type(schema_node)
212
+
213
+ converted["items"] = self.dispatcher(schema_node.children[0])
214
+
215
+ return converted
216
+
217
+
218
+ class TypeConversionDispatcher(object):
219
+ def __init__(self, custom_converters={}, default_converter=None):
220
+ self.converters = {
221
+ colander.Boolean: BooleanTypeConverter,
222
+ colander.Date: DateTypeConverter,
223
+ colander.DateTime: DateTimeTypeConverter,
224
+ colander.Float: NumberTypeConverter,
225
+ colander.Integer: IntegerTypeConverter,
226
+ colander.Mapping: ObjectTypeConverter,
227
+ colander.Sequence: ArrayTypeConverter,
228
+ colander.String: StringTypeConverter,
229
+ colander.Time: TimeTypeConverter,
230
+ }
231
+
232
+ self.converters.update(custom_converters)
233
+ self.default_converter = default_converter
234
+
235
+ def __call__(self, schema_node):
236
+ schema_type = schema_node.typ
237
+ schema_type = type(schema_type)
238
+
239
+ converter_class = self.converters.get(schema_type)
240
+ if converter_class is None:
241
+ if self.default_converter:
242
+ converter_class = self.default_converter
243
+ else:
244
+ raise NoSuchConverter
245
+
246
+ converter = converter_class(self)
247
+ converted = converter(schema_node)
248
+
249
+ return converted