mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PyCharm debugger breaks django form validation (PY-14578)
Create a separate resolver for Django forms in order to prevent calling self.errors because it is a property and has side effects. Also We shouldn't call str(), because it also has side effects.
This commit is contained in:
@@ -100,9 +100,9 @@ class DefaultResolver:
|
||||
def resolve(self, var, attribute):
|
||||
return getattr(var, attribute)
|
||||
|
||||
def get_dictionary(self, var):
|
||||
def get_dictionary(self, var, names=None):
|
||||
if MethodWrapperType:
|
||||
return self._getPyDictionary(var)
|
||||
return self._getPyDictionary(var, names)
|
||||
else:
|
||||
return self._getJyDictionary(var)
|
||||
|
||||
@@ -162,15 +162,20 @@ class DefaultResolver:
|
||||
|
||||
return ret
|
||||
|
||||
def _getPyDictionary(self, var):
|
||||
def get_names(self, var):
|
||||
names = dir(var)
|
||||
if not names and hasattr(var, '__members__'):
|
||||
names = var.__members__
|
||||
return names
|
||||
|
||||
def _getPyDictionary(self, var, names=None):
|
||||
filterPrivate = False
|
||||
filterSpecial = True
|
||||
filterFunction = True
|
||||
filterBuiltIn = True
|
||||
|
||||
names = dir(var)
|
||||
if not names and hasattr(var, '__members__'):
|
||||
names = var.__members__
|
||||
if not names:
|
||||
names = self.get_names(var)
|
||||
d = {}
|
||||
|
||||
#Be aware that the order in which the filters are applied attempts to
|
||||
@@ -482,21 +487,34 @@ class MultiValueDictResolver(DictResolver):
|
||||
|
||||
raise UnableToResolveVariableException()
|
||||
|
||||
def get_dictionary(self, dict):
|
||||
ret = {}
|
||||
i = 0
|
||||
for key in dict_keys(dict):
|
||||
val = dict.getlist(key)
|
||||
i += 1
|
||||
#we need to add the id because otherwise we cannot find the real object to get its contents later on.
|
||||
key = '%s (%s)' % (self.key_to_str(key), id(key))
|
||||
ret[key] = val
|
||||
if i > MAX_ITEMS_TO_HANDLE:
|
||||
ret[TOO_LARGE_ATTR] = TOO_LARGE_MSG
|
||||
break
|
||||
|
||||
ret['__len__'] = len(dict)
|
||||
return ret
|
||||
|
||||
#=======================================================================================================================
|
||||
# DjangoFormResolver
|
||||
#=======================================================================================================================
|
||||
class DjangoFormResolver(DefaultResolver):
|
||||
has_errors_attr = False
|
||||
|
||||
def get_names(self, var):
|
||||
names = dir(var)
|
||||
if not names and hasattr(var, '__members__'):
|
||||
names = var.__members__
|
||||
|
||||
if "errors" in names:
|
||||
self.has_errors_attr = True
|
||||
names.remove("errors")
|
||||
return names
|
||||
|
||||
def get_dictionary(self, var, names=None):
|
||||
# Do not call self.errors because it is property and has side effects
|
||||
d = defaultResolver.get_dictionary(var, self.get_names(var))
|
||||
if self.has_errors_attr:
|
||||
try:
|
||||
errors_attr = getattr(var, "_errors")
|
||||
except:
|
||||
errors_attr = None
|
||||
d["errors"] = errors_attr
|
||||
return d
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
@@ -567,5 +585,6 @@ jyArrayResolver = JyArrayResolver()
|
||||
setResolver = SetResolver()
|
||||
ndarrayResolver = NdArrayResolver()
|
||||
multiValueDictResolver = MultiValueDictResolver()
|
||||
djangoFormResolver = DjangoFormResolver()
|
||||
dequeResolver = DequeResolver()
|
||||
frameResolver = FrameResolver()
|
||||
|
||||
@@ -81,6 +81,13 @@ def _update_type_map():
|
||||
except:
|
||||
pass #django may not be installed
|
||||
|
||||
try:
|
||||
from django.forms import BaseForm
|
||||
_TYPE_MAP.insert(0, (BaseForm, pydevd_resolver.djangoFormResolver))
|
||||
#we should put it before instance resolver
|
||||
except:
|
||||
pass #django may not be installed
|
||||
|
||||
try:
|
||||
from collections import deque
|
||||
_TYPE_MAP.append((deque, pydevd_resolver.dequeResolver))
|
||||
@@ -181,6 +188,11 @@ def var_to_xml(val, name, doTrim=True, additionalInXml=''):
|
||||
|
||||
_type, typeName, resolver = get_type(v)
|
||||
|
||||
do_not_call_value_str = False
|
||||
if isinstance(resolver, pydevd_resolver.djangoFormResolver.__class__):
|
||||
# do not call str() of Django form objects because has side effects and breaks self.errors
|
||||
do_not_call_value_str = True
|
||||
|
||||
try:
|
||||
if hasattr(v, '__class__'):
|
||||
if v.__class__ == frame_type:
|
||||
@@ -204,7 +216,11 @@ def var_to_xml(val, name, doTrim=True, additionalInXml=''):
|
||||
cName = cName[:-2]
|
||||
except:
|
||||
cName = str(v.__class__)
|
||||
value = '%s: %s' % (cName, v)
|
||||
|
||||
if do_not_call_value_str:
|
||||
value = '%s: %r' % (cName, v)
|
||||
else:
|
||||
value = '%s: %s' % (cName, v)
|
||||
else:
|
||||
value = str(v)
|
||||
except:
|
||||
|
||||
Reference in New Issue
Block a user