Skip to content

Commit

Permalink
honor djangorestframework_camel_case settings "ignore_keys" and "igno…
Browse files Browse the repository at this point in the history
…re_fields" #945

Thx to @tomashchuk for raising the issue and providing part of the fix

Co-authored-by: tomashchuk <tomashchukdmytro@gmail.com>
  • Loading branch information
tfranzel and tomashchuk committed Mar 4, 2023
1 parent 704ed7d commit 27b46d0
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 5 deletions.
22 changes: 17 additions & 5 deletions drf_spectacular/contrib/djangorestframework_camel_case.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import re
from typing import Optional


def camelize_serializer_fields(result, generator, request, public):
from djangorestframework_camel_case.settings import api_settings
from djangorestframework_camel_case.util import camelize_re, underscore_to_camel

def camelize_str(str):
return re.sub(camelize_re, underscore_to_camel, str)
# prunes subtrees from camelization based on owning field name
ignore_fields = api_settings.JSON_UNDERSCOREIZE.get("ignore_fields") or ()
# ignore certain field names while camelizing
ignore_keys = api_settings.JSON_UNDERSCOREIZE.get("ignore_keys") or ()

def camelize_component(schema: dict):
if schema.get('type') == 'object':
def camelize_str(key: str) -> str:
new_key = re.sub(camelize_re, underscore_to_camel, key) if "_" in key else key
if key in ignore_keys or new_key in ignore_keys:
return key
return new_key

def camelize_component(schema: dict, name: Optional[str] = None) -> dict:
if name is not None and (name in ignore_fields or camelize_str(name) in ignore_fields):
return schema
elif schema.get('type') == 'object':
if 'properties' in schema:
schema['properties'] = {
camelize_str(field_name): camelize_component(field_schema)
camelize_str(field_name): camelize_component(field_schema, field_name)
for field_name, field_schema in schema['properties'].items()
}
if 'required' in schema:
Expand Down
14 changes: 14 additions & 0 deletions tests/contrib/test_djangorestframework_camel_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,23 @@ class NestedObject(TypedDict):
field_four: str
field_five: NestedObject2
field_six: List[NestedObject2]
field_ignored: int


class FakeSerializer(serializers.Serializer):
field_one = serializers.CharField()
field_two = serializers.CharField()
field_ignored = serializers.CharField()

field_nested = serializers.SerializerMethodField()
field_nested_ignored = serializers.SerializerMethodField()

def get_field_nested(self) -> NestedObject: # type: ignore
pass # pragma: no cover

def get_field_nested_ignored(self) -> NestedObject: # type: ignore
pass # pragma: no cover


class FakeViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
serializer_class = FakeSerializer
Expand All @@ -53,6 +59,14 @@ def home(self, request):
'drf_spectacular.settings.spectacular_settings.POSTPROCESSING_HOOKS',
[camelize_serializer_fields]
)
@mock.patch(
'djangorestframework_camel_case.settings.api_settings.JSON_UNDERSCOREIZE',
{
'no_underscore_before_number': False,
'ignore_fields': ('field_nested_ignored',),
'ignore_keys': ('field_ignored',),
}
)
@pytest.mark.contrib('djangorestframework_camel_case')
def test_camelize_serializer_fields():
assert_schema(
Expand Down
45 changes: 45 additions & 0 deletions tests/contrib/test_djangorestframework_camel_case.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ components:
type: string
fieldTwo:
type: string
field_ignored:
type: string
fieldNested:
type: object
properties:
Expand Down Expand Up @@ -75,14 +77,57 @@ components:
required:
- fieldEight
- fieldSeven
field_ignored:
type: integer
required:
- fieldFive
- fieldFour
- field_ignored
- fieldSix
- fieldThree
readOnly: true
fieldNestedIgnored:
type: object
properties:
field_three:
type: integer
field_four:
type: string
field_five:
type: object
properties:
field_seven:
type: integer
field_eight:
type: string
required:
- field_eight
- field_seven
field_six:
type: array
items:
type: object
properties:
field_seven:
type: integer
field_eight:
type: string
required:
- field_eight
- field_seven
field_ignored:
type: integer
required:
- field_five
- field_four
- field_ignored
- field_six
- field_three
readOnly: true
required:
- field_ignored
- fieldNested
- fieldNestedIgnored
- fieldOne
- fieldTwo
securitySchemes:
Expand Down
3 changes: 3 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,6 @@ ignore_missing_imports = True

[mypy-rest_framework_gis.*]
ignore_missing_imports = True

[mypy-djangorestframework_camel_case.*]
ignore_missing_imports = True

0 comments on commit 27b46d0

Please sign in to comment.