Work with a NameWrapper, so Django goto works better

This commit is contained in:
Dave Halter
2020-04-22 09:32:31 +02:00
parent f9176578ea
commit f3eaa418bb
2 changed files with 31 additions and 33 deletions

View File

@@ -5,29 +5,13 @@ Bugs:
- Can't infer ManyToManyField. - Can't infer ManyToManyField.
""" """
from jedi import debug from jedi import debug
from jedi.inference.base_value import LazyValueWrapper from jedi.inference.base_value import LazyValueWrapper, ValueSet, NO_VALUES
from jedi.inference.utils import safe_property from jedi.inference.utils import safe_property
from jedi.inference.filters import ParserTreeFilter, DictFilter from jedi.inference.filters import ParserTreeFilter, DictFilter
from jedi.inference.names import ValueName from jedi.inference.names import ValueName, NameWrapper
from jedi.inference.value.instance import TreeInstance from jedi.inference.value.instance import TreeInstance
class DjangoModelField(LazyValueWrapper):
def __init__(self, cls, name):
self.inference_state = cls.inference_state
self._cls = cls
self._name = name
self.tree_node = self._name.tree_name
@safe_property
def name(self):
return ValueName(self, self._name.tree_name)
def _get_wrapped_value(self):
obj, = self._cls.execute_with_values()
return obj
mapping = { mapping = {
'IntegerField': (None, 'int'), 'IntegerField': (None, 'int'),
'BigIntegerField': (None, 'int'), 'BigIntegerField': (None, 'int'),
@@ -59,14 +43,14 @@ def _infer_scalar_field(inference_state, field_name, field_tree_instance):
module = inference_state.import_module((module_name,)) module = inference_state.import_module((module_name,))
for attribute in module.py__getattribute__(attribute_name): for attribute in module.py__getattribute__(attribute_name):
return DjangoModelField(attribute, field_name) return attribute.execute_with_values()
def _infer_field(cls, field_name): def _infer_field(cls, field_name):
inference_state = cls.inference_state inference_state = cls.inference_state
for field_tree_instance in field_name.infer(): for field_tree_instance in field_name.infer():
scalar_field = _infer_scalar_field(inference_state, field_name, field_tree_instance) scalar_field = _infer_scalar_field(inference_state, field_name, field_tree_instance)
if scalar_field: if scalar_field is not None:
return scalar_field return scalar_field
if field_tree_instance.py__name__() == 'ForeignKey': if field_tree_instance.py__name__() == 'ForeignKey':
@@ -79,25 +63,34 @@ def _infer_field(cls, field_name):
if value.py__name__() == 'str': if value.py__name__() == 'str':
foreign_key_class_name = value.get_safe_value() foreign_key_class_name = value.get_safe_value()
module = cls.get_root_context() module = cls.get_root_context()
for v in module.py__getattribute__(foreign_key_class_name): return ValueSet.from_sets(
if v.is_class(): v.execute_with_values()
return DjangoModelField(v, field_name) for v in module.py__getattribute__(foreign_key_class_name)
if v.is_class()
)
elif value.is_class(): elif value.is_class():
return DjangoModelField(value, field_name) return value.execute_with_values()
debug.dbg('django plugin: fail to infer `%s` from class `%s`', debug.dbg('django plugin: fail to infer `%s` from class `%s`',
field_name.string_name, cls.py__name__()) field_name.string_name, cls.py__name__())
return None return field_name.infer()
class DjangoModelName(NameWrapper):
def __init__(self, cls, name):
super(DjangoModelName, self).__init__(name)
self._cls = cls
def infer(self):
return _infer_field(self._cls, self._wrapped_name)
def _new_dict_filter(cls): def _new_dict_filter(cls):
def iterate(): filter_ = ParserTreeFilter(parent_context=cls.as_context())
filter_ = ParserTreeFilter(parent_context=cls.as_context()) return DictFilter({
for name in filter_.values(): name.string_name: DjangoModelName(cls, name)
django_field = _infer_field(cls, name) for name in filter_.values()
if django_field is not None: })
yield name.string_name, django_field.name
return DictFilter(dict(iterate()))
def get_metaclass_filters(func): def get_metaclass_filters(func):

View File

@@ -18,6 +18,7 @@ class BusinessModel(models.Model):
category_fk3 = models.ForeignKey(1) category_fk3 = models.ForeignKey(1)
category_fk4 = models.ForeignKey('models') category_fk4 = models.ForeignKey('models')
category_fk5 = models.ForeignKey() category_fk5 = models.ForeignKey()
integer_field = models.IntegerField() integer_field = models.IntegerField()
big_integer_field = models.BigIntegerField() big_integer_field = models.BigIntegerField()
positive_integer_field = models.PositiveIntegerField() positive_integer_field = models.PositiveIntegerField()
@@ -70,6 +71,10 @@ model_instance.date_field
#? datetime.datetime() #? datetime.datetime()
model_instance.date_time_field model_instance.date_time_field
#! ['category_fk = models.ForeignKey(Category)']
model_instance.category_fk
#! ['category_name = models.CharField()']
model_instance.category_fk.category_name
#? Category() #? Category()
model_instance.category_fk model_instance.category_fk
#? str() #? str()
@@ -80,7 +85,7 @@ model_instance.category_fk2
model_instance.category_fk2.category_name model_instance.category_fk2.category_name
#? models.ForeignKey() #? models.ForeignKey()
model_instance.category_fk3 model_instance.category_fk3
#? models.ForeignKey() #?
model_instance.category_fk4 model_instance.category_fk4
#? models.ForeignKey() #? models.ForeignKey()
model_instance.category_fk5 model_instance.category_fk5