Don't deepcopy 'regex' arguments, instead treat as immutable.

This commit is contained in:
Tom Christie 2016-09-15 11:56:22 +01:00
parent 9833afa795
commit 82847c2c12

View File

@ -252,6 +252,8 @@ class SkipField(Exception):
pass pass
REGEX_TYPE = type(re.compile(''))
NOT_READ_ONLY_WRITE_ONLY = 'May not set both `read_only` and `write_only`' NOT_READ_ONLY_WRITE_ONLY = 'May not set both `read_only` and `write_only`'
NOT_READ_ONLY_REQUIRED = 'May not set both `read_only` and `required`' NOT_READ_ONLY_REQUIRED = 'May not set both `read_only` and `required`'
NOT_REQUIRED_DEFAULT = 'May not set both `required` and `default`' NOT_REQUIRED_DEFAULT = 'May not set both `required` and `default`'
@ -581,16 +583,17 @@ class Field(object):
When cloning fields we instantiate using the arguments it was When cloning fields we instantiate using the arguments it was
originally created with, rather than copying the complete state. originally created with, rather than copying the complete state.
""" """
args = copy.deepcopy(self._args) # Treat regexes and validators as immutable.
kwargs = dict(self._kwargs)
# Bit ugly, but we need to special case 'validators' as Django's
# RegexValidator does not support deepcopy.
# We treat validator callables as immutable objects.
# See https://github.com/tomchristie/django-rest-framework/issues/1954 # See https://github.com/tomchristie/django-rest-framework/issues/1954
validators = kwargs.pop('validators', None) # and https://github.com/tomchristie/django-rest-framework/pull/4489
kwargs = copy.deepcopy(kwargs) args = [
if validators is not None: copy.deepcopy(item) if not isinstance(item, REGEX_TYPE) else item
kwargs['validators'] = validators for item in self._args
]
kwargs = {
key: (copy.deepcopy(value) if (key not in ('validators', 'regex')) else value)
for key, value in self._kwargs.items()
}
return self.__class__(*args, **kwargs) return self.__class__(*args, **kwargs)
def __repr__(self): def __repr__(self):