Skip to content

Commit 46d40be

Browse files
committed
fix hashable field.
1 parent 1150c9b commit 46d40be

File tree

5 files changed

+58
-6
lines changed

5 files changed

+58
-6
lines changed

CHANGES.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
## Version 0.13.1
2+
3+
* Fix hashable field.
4+
5+
## Version 0.13.0
6+
7+
* Fix exceptions structure.
8+
19
## Version 0.12.1
210

311
* Fix arguments validation.
412

5-
* ## Version 0.12.0
13+
## Version 0.12.0
614

715
* Validating and serializing arguments from `request.view_args` to `request.first_view_args`.
816
* Validating and serializing arguments from `request.args` to `request.first_args`.

src/flask_first/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from .schema.tools import convert_schemas
3030
from .schema.tools import resolving_refs
3131

32-
__version__ = '0.13.0'
32+
__version__ = '0.13.1'
3333

3434

3535
class First:

src/flask_first/schema/schema_maker.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
from typing import Any
2+
13
from marshmallow import fields
24
from marshmallow import INCLUDE
35
from marshmallow import Schema
46
from marshmallow import validate
57
from marshmallow import ValidationError
8+
from marshmallow.fields import Boolean
9+
from marshmallow.fields import Field
10+
from marshmallow.fields import Nested
611

712
from .custom_fields import AllOf
813
from .custom_fields import AnyOf
@@ -20,6 +25,10 @@ def _validate(self, value):
2025
raise ValidationError('Invalid value')
2126

2227

28+
class HashmapField(fields.Field):
29+
pass
30+
31+
2332
FIELDS_VIA_TYPES = {
2433
'boolean': fields.Boolean,
2534
'number': fields.Float,
@@ -47,12 +56,16 @@ class Meta:
4756

4857

4958
def _make_object_field(schema: dict, as_nested: bool = True) -> fields.Nested | type:
50-
if schema.get('properties') is None and schema['additionalProperties'].get('oneOf'):
51-
return HashmapSchema
5259

5360
fields_obj = {}
5461
for field_name, field_schema in schema['properties'].items():
55-
if field_schema['type'] == 'object':
62+
if (
63+
field_schema.get('additionalProperties')
64+
and isinstance(field_schema['additionalProperties'], dict)
65+
and field_schema['additionalProperties'].get('oneOf')
66+
):
67+
field = HashmapField()
68+
elif field_schema['type'] == 'object':
5669
field = make_marshmallow_schema(field_schema, as_nested=True)
5770
else:
5871
field = make_marshmallow_schema(field_schema)
@@ -107,7 +120,9 @@ def _make_field_validators(schema: dict) -> list[validate.Validator]:
107120
return validators
108121

109122

110-
def make_marshmallow_schema(schema: dict, as_nested: bool = False) -> fields.Field:
123+
def make_marshmallow_schema(
124+
schema: dict, as_nested: bool = False
125+
) -> type[HashmapSchema] | Field | Nested | type | Boolean | Any:
111126
if 'nullable' in schema and schema.get('type', ...) is ...:
112127
field = FIELDS_VIA_TYPES['boolean']()
113128
elif 'allOf' in schema:
@@ -118,6 +133,12 @@ def make_marshmallow_schema(schema: dict, as_nested: bool = False) -> fields.Fie
118133
field = _make_multiple_field(schema['oneOf'], 'oneOf')
119134
elif schema.get('format'):
120135
field = FIELDS_VIA_FORMATS[schema['format']]()
136+
elif (
137+
schema.get('properties') is None
138+
and schema['type'] == 'object'
139+
and schema['additionalProperties'].get('oneOf')
140+
):
141+
field = HashmapSchema
121142
elif schema['type'] == 'object':
122143
field = _make_object_field(schema, as_nested=as_nested)
123144
elif schema['type'] == 'array':

tests/specs/v3.0/not_defined_name_key.openapi.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ paths:
1313
application/json:
1414
schema:
1515
$ref: "#/components/schemas/ObjectSchema"
16+
/sub_hashable_obj:
17+
get:
18+
operationId: sub_hashable_obj
19+
responses:
20+
"200":
21+
description: OK
22+
content:
23+
application/json:
24+
schema:
25+
$ref: "#/components/schemas/SubObjectSchema"
1626
components:
1727
schemas:
1828
ObjectSchema:
@@ -22,3 +32,11 @@ components:
2232
oneOf:
2333
- type: string
2434
example: "{'unknown_name': 'Value'}"
35+
SubObjectSchema:
36+
type: object
37+
nullable: true
38+
additionalProperties: false
39+
properties:
40+
any_field:
41+
$ref: "#/components/schemas/ObjectSchema"
42+
example: "{'unknown_name': 'Nested hashmap'}"

tests/test_flask_first.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,12 @@ def test_specification__not_defined_name_key():
399399
def one_of_endpoint() -> dict:
400400
return {'name': 'Test_name'}
401401

402+
def sub_hashable_obj() -> dict:
403+
return {'any_field': 'Test_name'}
404+
402405
first.add_view_func(one_of_endpoint)
406+
first.add_view_func(sub_hashable_obj)
403407

404408
with app.test_client() as test_client:
405409
assert test_client.get('/one_of_endpoint').status_code == 200
410+
assert test_client.get('/sub_hashable_obj').status_code == 200

0 commit comments

Comments
 (0)