Skip to content

Commit

Permalink
add config for camelizing names #138
Browse files Browse the repository at this point in the history
  • Loading branch information
tfranzel committed Sep 7, 2020
1 parent ea4c569 commit 9e9a40a
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 7 deletions.
9 changes: 6 additions & 3 deletions drf_spectacular/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

from drf_spectacular.extensions import OpenApiViewExtension
from drf_spectacular.plumbing import (
ComponentRegistry, alpha_operation_sorter, build_root_object, error, is_versioning_supported,
modify_for_versioning, normalize_result_object, operation_matches_version,
reset_generator_stats, warn,
ComponentRegistry, alpha_operation_sorter, build_root_object, camelize_operation, error,
is_versioning_supported, modify_for_versioning, normalize_result_object,
operation_matches_version, reset_generator_stats, warn,
)
from drf_spectacular.settings import spectacular_settings

Expand Down Expand Up @@ -154,6 +154,9 @@ def parse(self, request, public):
path = path[1:]
path = urljoin(self.url or '/', path)

if spectacular_settings.CAMELIZE_NAMES:
path, operation = camelize_operation(path, operation)

result.setdefault(path, {})
result[path][method.lower()] = operation

Expand Down
7 changes: 4 additions & 3 deletions drf_spectacular/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,10 @@ def _resolve_path_parameters(self, variables):
schema = resolved_parameter['schema']
elif not model:
warn(
f'could not derive type of path parameter "{variable}" because '
f'{self.view.__class__} has no queryset. consider annotating the '
f'parameter type with @extend_schema. defaulting to "string".'
f'could not derive type of path parameter "{variable}" because because it '
f'is untyped and {self.view.__class__} has no queryset. consider adding a '
f'type to the path (e.g. <int:{variable}>) or annotating the parameter '
f'type with @extend_schema. defaulting to "string".'
)
else:
try:
Expand Down
17 changes: 17 additions & 0 deletions drf_spectacular/plumbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from enum import Enum
from typing import DefaultDict, Generic, List, Optional, Type, TypeVar, Union

import inflection
import uritemplate
from django import __version__ as DJANGO_VERSION
from django.apps import apps
Expand Down Expand Up @@ -700,3 +701,19 @@ def normalize_result_object(result):
if isinstance(result, Promise):
return str(result)
return result


def camelize_operation(path, operation):
for path_variable in re.findall(r'\{(\w+)\}', path):
path = path.replace(
f'{{{path_variable}}}',
f'{{{inflection.camelize(path_variable, False)}}}'
)

for parameter in operation.get('parameters', []):
if parameter['in'] == OpenApiParameter.PATH:
parameter['name'] = inflection.camelize(parameter['name'], False)

operation['operationId'] = inflection.camelize(operation['operationId'], False)

return path, operation
5 changes: 4 additions & 1 deletion drf_spectacular/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# Split components into request and response parts where appropriate
'COMPONENT_SPLIT_REQUEST': False,
# Aid client generator targets that have trouble with read-only properties.
"COMPONENT_NO_READ_ONLY_REQUIRED": False,
'COMPONENT_NO_READ_ONLY_REQUIRED': False,

# Configuration for serving the schema with SpectacularAPIView
'SERVE_URLCONF': None,
Expand Down Expand Up @@ -50,6 +50,9 @@
# function that returns a list of all classes that should be excluded from doc string extraction
'GET_LIB_DOC_EXCLUDES': 'drf_spectacular.plumbing.get_lib_doc_excludes',

# Camelize names like operationId and path parameter names
'CAMELIZE_NAMES': False,

# General schema metadata. Refer to spec for valid inputs
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#openapi-object
'TITLE': '',
Expand Down
13 changes: 13 additions & 0 deletions tests/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -909,3 +909,16 @@ def one_off(request, foo):
'#/components/schemas/NestedInlineOneOff'
)
assert len(one_off_nested['properties']) == 2


@mock.patch('drf_spectacular.settings.spectacular_settings.CAMELIZE_NAMES', True)
def test_camelize_names(no_warnings):
@extend_schema(responses=OpenApiTypes.FLOAT)
@api_view(['GET'])
def view_func(request, format=None):
pass # pragma: no cover

schema = generate_schema('/multi/step/path/<str:some_name>/', view_function=view_func)
operation = schema['paths']['/multi/step/path/{someName}/']['get']
assert operation['parameters'][0]['name'] == 'someName'
assert operation['operationId'] == 'multiStepPathRetrieve'

0 comments on commit 9e9a40a

Please sign in to comment.