mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 08:29:59 +03:00
so far so good
all tests pass
This commit is contained in:
parent
efc7c1d664
commit
e7ecbf92c4
|
@ -140,7 +140,7 @@ if markdown is not None and pygments is not None:
|
|||
code = m.group(2).replace('\t', ' ')
|
||||
code = pygments.highlight(code, lexer, self.formatter)
|
||||
code = code.replace('\n\n', '\n \n').replace('\n', '<br />').replace('\\@', '@')
|
||||
return '\n\n%s\n\n' % code
|
||||
return f'\n\n{code}\n\n'
|
||||
ret = self.pattern.sub(repl, "\n".join(lines))
|
||||
return ret.split("\n")
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ def api_view(http_method_names=None):
|
|||
|
||||
# api_view applied with eg. string instead of list of strings
|
||||
assert isinstance(http_method_names, (list, tuple)), \
|
||||
'@api_view expected a list of strings, received %s' % type(http_method_names).__name__
|
||||
f'@api_view expected a list of strings, received {type(http_method_names).__name__}'
|
||||
|
||||
allowed_methods = set(http_method_names) | {'options'}
|
||||
WrappedAPIView.http_method_names = [method.lower() for method in allowed_methods]
|
||||
|
@ -199,7 +199,7 @@ class MethodMapper(dict):
|
|||
|
||||
def _map(self, method, func):
|
||||
assert method not in self, (
|
||||
"Method '%s' has already been mapped to '.%s'." % (method, self[method]))
|
||||
f"Method '{method}' has already been mapped to '.{self[method]}'.")
|
||||
assert func.__name__ != self.action.__name__, (
|
||||
"Method mapping does not behave like the property decorator. You "
|
||||
"cannot use the same method name for each mapping declaration.")
|
||||
|
|
|
@ -84,10 +84,8 @@ class ErrorDetail(str):
|
|||
return not self.__eq__(other)
|
||||
|
||||
def __repr__(self):
|
||||
return 'ErrorDetail(string=%r, code=%r)' % (
|
||||
str(self),
|
||||
self.code,
|
||||
)
|
||||
return f"ErrorDetail(string='{str(self)}', code='{self.code}')"
|
||||
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
|
|
|
@ -280,7 +280,7 @@ class CreateOnlyDefault:
|
|||
return self.default
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (self.__class__.__name__, repr(self.default))
|
||||
return f'{self.__class__.__name__}({repr(self.default)})'
|
||||
|
||||
|
||||
class CurrentUserDefault:
|
||||
|
@ -290,7 +290,7 @@ class CurrentUserDefault:
|
|||
return serializer_field.context['request'].user
|
||||
|
||||
def __repr__(self):
|
||||
return '%s()' % self.__class__.__name__
|
||||
return f'{self.__class__.__name__}()'
|
||||
|
||||
|
||||
class SkipField(Exception):
|
||||
|
|
|
@ -294,8 +294,8 @@ class OrderingFilter(BaseFilterBackend):
|
|||
'param': self.ordering_param,
|
||||
}
|
||||
for key, label in self.get_valid_fields(queryset, view, context):
|
||||
options.append((key, '%s - %s' % (label, _('ascending'))))
|
||||
options.append(('-' + key, '%s - %s' % (label, _('descending'))))
|
||||
options.append((key, f'{label} - {_("ascending")}'))
|
||||
options.append(('-' + key, f'{label} - {_("descending")}'))
|
||||
context['options'] = options
|
||||
return context
|
||||
|
||||
|
|
|
@ -61,9 +61,9 @@ class GenericAPIView(views.APIView):
|
|||
(Eg. return a list of items that is specific to the user)
|
||||
"""
|
||||
assert self.queryset is not None, (
|
||||
"'%s' should either include a `queryset` attribute, "
|
||||
"or override the `get_queryset()` method."
|
||||
% self.__class__.__name__
|
||||
f"'{self.__class__.__name__}' should either include a `queryset` attribute, "
|
||||
f"or override the `get_queryset()` method."
|
||||
|
||||
)
|
||||
|
||||
queryset = self.queryset
|
||||
|
@ -120,9 +120,8 @@ class GenericAPIView(views.APIView):
|
|||
(Eg. admins get full serialization, others get basic serialization)
|
||||
"""
|
||||
assert self.serializer_class is not None, (
|
||||
"'%s' should either include a `serializer_class` attribute, "
|
||||
f"'{self.__class__.__name__}' should either include a `serializer_class` attribute, "
|
||||
"or override the `get_serializer_class()` method."
|
||||
% self.__class__.__name__
|
||||
)
|
||||
|
||||
return self.serializer_class
|
||||
|
|
|
@ -64,7 +64,7 @@ class JSONParser(BaseParser):
|
|||
parse_constant = json.strict_constant if self.strict else None
|
||||
return json.load(decoded_stream, parse_constant=parse_constant)
|
||||
except ValueError as exc:
|
||||
raise ParseError('JSON parse error - %s' % str(exc))
|
||||
raise ParseError(f'JSON parse error - {str(exc)}')
|
||||
|
||||
|
||||
class FormParser(BaseParser):
|
||||
|
@ -109,7 +109,7 @@ class MultiPartParser(BaseParser):
|
|||
data, files = parser.parse()
|
||||
return DataAndFiles(data, files)
|
||||
except MultiPartParserError as exc:
|
||||
raise ParseError('Multipart form parse error - %s' % str(exc))
|
||||
raise ParseError(f'Multipart form parse error - {str(exc)}')
|
||||
|
||||
|
||||
class FileUploadParser(BaseParser):
|
||||
|
|
|
@ -46,6 +46,7 @@ class Hyperlink(str):
|
|||
We use this for hyperlinked URLs that may render as a named link
|
||||
in some contexts, or render as a plain URL in others.
|
||||
"""
|
||||
|
||||
def __new__(cls, url, obj):
|
||||
ret = super().__new__(cls, url)
|
||||
ret.obj = obj
|
||||
|
@ -70,11 +71,12 @@ class PKOnlyObject:
|
|||
instance, but still want to return an object with a .pk attribute,
|
||||
in order to keep the same interface as a regular model instance.
|
||||
"""
|
||||
|
||||
def __init__(self, pk):
|
||||
self.pk = pk
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % self.pk
|
||||
return f"{self.pk}"
|
||||
|
||||
|
||||
# We assume that 'validators' are intended for the child serializer,
|
||||
|
@ -376,9 +378,9 @@ class HyperlinkedRelatedField(RelatedField):
|
|||
|
||||
def to_representation(self, value):
|
||||
assert 'request' in self.context, (
|
||||
"`%s` requires the request in the serializer"
|
||||
f"`{self.__class__.__name__}` requires the request in the serializer"
|
||||
" context. Add `context={'request': request}` when instantiating "
|
||||
"the serializer." % self.__class__.__name__
|
||||
"the serializer."
|
||||
)
|
||||
|
||||
request = self.context['request']
|
||||
|
|
|
@ -197,7 +197,7 @@ class TemplateHTMLRenderer(BaseRenderer):
|
|||
return self.resolve_template(template_names)
|
||||
except Exception:
|
||||
# Fall back to using eg '404 Not Found'
|
||||
body = '%d %s' % (response.status_code, response.status_text.title())
|
||||
body = f'{response.status_code} {response.status_text.title()}'
|
||||
template = engines['django'].from_string(body)
|
||||
return template
|
||||
|
||||
|
@ -414,9 +414,9 @@ class BrowsableAPIRenderer(BaseRenderer):
|
|||
|
||||
render_style = getattr(renderer, 'render_style', 'text')
|
||||
assert render_style in ['text', 'binary'], 'Expected .render_style ' \
|
||||
'"text" or "binary", but got "%s"' % render_style
|
||||
f'"text" or "binary", but got "{render_style}"'
|
||||
if render_style == 'binary':
|
||||
return '[%d bytes of binary content]' % len(content)
|
||||
return f'[{len(content)} bytes of binary content]'
|
||||
|
||||
return content.decode('utf-8') if isinstance(content, bytes) else content
|
||||
|
||||
|
@ -660,9 +660,9 @@ class BrowsableAPIRenderer(BaseRenderer):
|
|||
response_headers = OrderedDict(sorted(response.items()))
|
||||
renderer_content_type = ''
|
||||
if renderer:
|
||||
renderer_content_type = '%s' % renderer.media_type
|
||||
renderer_content_type = f'{renderer.media_type}'
|
||||
if renderer.charset:
|
||||
renderer_content_type += ' ;%s' % renderer.charset
|
||||
renderer_content_type += f' ;{renderer.charset}'
|
||||
response_headers['Content-Type'] = renderer_content_type
|
||||
|
||||
if getattr(view, 'paginator', None) and view.paginator.display_page_controls:
|
||||
|
|
|
@ -180,11 +180,8 @@ class Request:
|
|||
self.authenticators = (forced_auth,)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s.%s: %s %r>' % (
|
||||
self.__class__.__module__,
|
||||
self.__class__.__name__,
|
||||
self.method,
|
||||
self.get_full_path())
|
||||
return f'<{self.__class__.__module__}.{self.__class__.__name__}: ' \
|
||||
f"{self.method} '{self.get_full_path()}'>"
|
||||
|
||||
def _default_negotiator(self):
|
||||
return api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS()
|
||||
|
|
|
@ -1105,20 +1105,17 @@ class ModelSerializer(Serializer):
|
|||
if fields and fields != ALL_FIELDS and not isinstance(fields, (list, tuple)):
|
||||
raise TypeError(
|
||||
'The `fields` option must be a list or tuple or "__all__". '
|
||||
'Got %s.' % type(fields).__name__
|
||||
f'Got {type(fields).__name__}.'
|
||||
)
|
||||
|
||||
if exclude and not isinstance(exclude, (list, tuple)):
|
||||
raise TypeError(
|
||||
'The `exclude` option must be a list or tuple. Got %s.' %
|
||||
type(exclude).__name__
|
||||
f'The `exclude` option must be a list or tuple. Got {type(exclude).__name__}.'
|
||||
)
|
||||
|
||||
assert not (fields and exclude), (
|
||||
"Cannot set both 'fields' and 'exclude' options on "
|
||||
"serializer {serializer_class}.".format(
|
||||
serializer_class=self.__class__.__name__
|
||||
)
|
||||
f"Cannot set both 'fields' and 'exclude' options on "
|
||||
f"serializer {self.__class__.__name__}."
|
||||
)
|
||||
|
||||
assert not (fields is None and exclude is None), (
|
||||
|
|
|
@ -91,7 +91,7 @@ class SimpleRateThrottle(BaseThrottle):
|
|||
try:
|
||||
return self.THROTTLE_RATES[self.scope]
|
||||
except KeyError:
|
||||
msg = "No default throttle rate set for '%s' scope" % self.scope
|
||||
msg = f"No default throttle rate set for '{self.scope}' scope"
|
||||
raise ImproperlyConfigured(msg)
|
||||
|
||||
def parse_rate(self, rate):
|
||||
|
|
|
@ -9,7 +9,7 @@ def _get_format_path_converter(suffix_kwarg, allowed):
|
|||
if len(allowed) == 1:
|
||||
allowed_pattern = allowed[0]
|
||||
else:
|
||||
allowed_pattern = '(?:%s)' % '|'.join(allowed)
|
||||
allowed_pattern = f'(?:{"|".join(allowed)})'
|
||||
suffix_pattern = r"\.%s/?" % allowed_pattern
|
||||
else:
|
||||
suffix_pattern = r"\.[a-z0-9]+/?"
|
||||
|
@ -99,7 +99,7 @@ def format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None):
|
|||
if len(allowed) == 1:
|
||||
allowed_pattern = allowed[0]
|
||||
else:
|
||||
allowed_pattern = '(%s)' % '|'.join(allowed)
|
||||
allowed_pattern = f'({"|".join(allowed)})'
|
||||
suffix_pattern = r'\.(?P<%s>%s)/?$' % (suffix_kwarg, allowed_pattern)
|
||||
else:
|
||||
suffix_pattern = r'\.(?P<%s>[a-z0-9]+)/?$' % suffix_kwarg
|
||||
|
@ -107,6 +107,6 @@ def format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None):
|
|||
converter_name, suffix_converter = _get_format_path_converter(suffix_kwarg, allowed)
|
||||
register_converter(suffix_converter, converter_name)
|
||||
|
||||
suffix_route = '<%s:%s>' % (converter_name, suffix_kwarg)
|
||||
suffix_route = f'<{converter_name}:{suffix_kwarg}>'
|
||||
|
||||
return apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required, suffix_route)
|
||||
|
|
|
@ -48,7 +48,7 @@ class UniqueValidator:
|
|||
"""
|
||||
Filter the queryset to all instances matching the given attribute.
|
||||
"""
|
||||
filter_kwargs = {'%s__%s' % (field_name, self.lookup): value}
|
||||
filter_kwargs = {f'{field_name}__{self.lookup}': value}
|
||||
return qs_filter(queryset, **filter_kwargs)
|
||||
|
||||
def exclude_current_instance(self, queryset, instance):
|
||||
|
@ -74,10 +74,7 @@ class UniqueValidator:
|
|||
raise ValidationError(self.message, code='unique')
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s(queryset=%s)>' % (
|
||||
self.__class__.__name__,
|
||||
smart_repr(self.queryset)
|
||||
)
|
||||
return f'<{self.__class__.__name__}(queryset={smart_repr(self.queryset)})>'
|
||||
|
||||
|
||||
class UniqueTogetherValidator:
|
||||
|
@ -160,11 +157,7 @@ class UniqueTogetherValidator:
|
|||
raise ValidationError(message, code='unique')
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s(queryset=%s, fields=%s)>' % (
|
||||
self.__class__.__name__,
|
||||
smart_repr(self.queryset),
|
||||
smart_repr(self.fields)
|
||||
)
|
||||
return f'<{self.__class__.__name__}(queryset={smart_repr(self.queryset)}, fields={smart_repr(self.fields)})>'
|
||||
|
||||
|
||||
class ProhibitSurrogateCharactersValidator:
|
||||
|
@ -231,12 +224,8 @@ class BaseUniqueForValidator:
|
|||
}, code='unique')
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s(queryset=%s, field=%s, date_field=%s)>' % (
|
||||
self.__class__.__name__,
|
||||
smart_repr(self.queryset),
|
||||
smart_repr(self.field),
|
||||
smart_repr(self.date_field)
|
||||
)
|
||||
return f'<{self.__class__.__name__}(queryset={smart_repr(self.queryset)}, ' \
|
||||
f'field={smart_repr(self.field)}, date_field={smart_repr(self.date_field)})>'
|
||||
|
||||
|
||||
class UniqueForDateValidator(BaseUniqueForValidator):
|
||||
|
@ -246,11 +235,10 @@ class UniqueForDateValidator(BaseUniqueForValidator):
|
|||
value = attrs[self.field]
|
||||
date = attrs[self.date_field]
|
||||
|
||||
filter_kwargs = {}
|
||||
filter_kwargs[field_name] = value
|
||||
filter_kwargs['%s__day' % date_field_name] = date.day
|
||||
filter_kwargs['%s__month' % date_field_name] = date.month
|
||||
filter_kwargs['%s__year' % date_field_name] = date.year
|
||||
filter_kwargs = {field_name: value,
|
||||
f'{date_field_name}__day': date.day,
|
||||
f'{date_field_name}__month': date.month,
|
||||
f'{date_field_name}__year': date.year}
|
||||
return qs_filter(queryset, **filter_kwargs)
|
||||
|
||||
|
||||
|
@ -263,7 +251,7 @@ class UniqueForMonthValidator(BaseUniqueForValidator):
|
|||
|
||||
filter_kwargs = {}
|
||||
filter_kwargs[field_name] = value
|
||||
filter_kwargs['%s__month' % date_field_name] = date.month
|
||||
filter_kwargs[f'{date_field_name}__month'] = date.month
|
||||
return qs_filter(queryset, **filter_kwargs)
|
||||
|
||||
|
||||
|
@ -274,7 +262,5 @@ class UniqueForYearValidator(BaseUniqueForValidator):
|
|||
value = attrs[self.field]
|
||||
date = attrs[self.date_field]
|
||||
|
||||
filter_kwargs = {}
|
||||
filter_kwargs[field_name] = value
|
||||
filter_kwargs['%s__year' % date_field_name] = date.year
|
||||
filter_kwargs = {field_name: value, f'{date_field_name}__year': date.year}
|
||||
return qs_filter(queryset, **filter_kwargs)
|
||||
|
|
|
@ -197,7 +197,7 @@ class ViewSetMixin:
|
|||
|
||||
for action in actions:
|
||||
try:
|
||||
url_name = '%s-%s' % (self.basename, action.url_name)
|
||||
url_name = f'{self.basename}-{action.url_name}'
|
||||
url = reverse(url_name, self.args, self.kwargs, request=self.request)
|
||||
view = self.__class__(**action.kwargs)
|
||||
action_urls[view.get_view_name()] = url
|
||||
|
|
|
@ -70,9 +70,9 @@ class ErrorDetailTests(TestCase):
|
|||
|
||||
def test_repr(self):
|
||||
assert repr(ErrorDetail('msg1')) == \
|
||||
'ErrorDetail(string={!r}, code=None)'.format('msg1')
|
||||
f"ErrorDetail(string='msg1', code='None')"
|
||||
assert repr(ErrorDetail('msg1', 'code')) == \
|
||||
'ErrorDetail(string={!r}, code={!r})'.format('msg1', 'code')
|
||||
f"ErrorDetail(string='msg1', code='code')"
|
||||
|
||||
def test_str(self):
|
||||
assert str(ErrorDetail('msg1')) == 'msg1'
|
||||
|
|
|
@ -208,7 +208,7 @@ class SearchFilterTests(TestCase):
|
|||
|
||||
def as_sql(self, compiler, connection):
|
||||
sql, params = compiler.compile(self.lhs)
|
||||
return "trim(%s, 'a')" % sql, params
|
||||
return f"trim({sql}, 'a')", params
|
||||
|
||||
with register_lookup(CharField, TrimA):
|
||||
# Search including `a`
|
||||
|
|
|
@ -13,7 +13,7 @@ class MockObject:
|
|||
'%s=%s' % (key, value)
|
||||
for key, value in sorted(self._kwargs.items())
|
||||
])
|
||||
return '<MockObject %s>' % kwargs_str
|
||||
return f'<MockObject {kwargs_str}>'
|
||||
|
||||
|
||||
class MockQueryset:
|
||||
|
|
Loading…
Reference in New Issue
Block a user