forked from VimPlug/jedi
Make it possible to use inheritance on generics without always specifying type vars, see also discussion in #1593
This commit is contained in:
@@ -174,6 +174,9 @@ class Value(HelperValueMixin):
|
|||||||
def is_class(self):
|
def is_class(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def is_class_mixin(self):
|
||||||
|
return False
|
||||||
|
|
||||||
def is_instance(self):
|
def is_instance(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ class GenericClass(ClassMixin, DefineGenericBaseClass):
|
|||||||
@to_list
|
@to_list
|
||||||
def py__bases__(self):
|
def py__bases__(self):
|
||||||
for base in self._wrapped_value.py__bases__():
|
for base in self._wrapped_value.py__bases__():
|
||||||
yield _LazyGenericBaseClass(self, base)
|
yield _LazyGenericBaseClass(self, base, self._generics_manager)
|
||||||
|
|
||||||
def _create_instance_with_generics(self, generics_manager):
|
def _create_instance_with_generics(self, generics_manager):
|
||||||
return GenericClass(self._class_value, generics_manager)
|
return GenericClass(self._class_value, generics_manager)
|
||||||
@@ -241,9 +241,10 @@ class GenericClass(ClassMixin, DefineGenericBaseClass):
|
|||||||
|
|
||||||
|
|
||||||
class _LazyGenericBaseClass(object):
|
class _LazyGenericBaseClass(object):
|
||||||
def __init__(self, class_value, lazy_base_class):
|
def __init__(self, class_value, lazy_base_class, generics_manager):
|
||||||
self._class_value = class_value
|
self._class_value = class_value
|
||||||
self._lazy_base_class = lazy_base_class
|
self._lazy_base_class = lazy_base_class
|
||||||
|
self._generics_manager = generics_manager
|
||||||
|
|
||||||
@iterator_to_value_set
|
@iterator_to_value_set
|
||||||
def infer(self):
|
def infer(self):
|
||||||
@@ -255,6 +256,16 @@ class _LazyGenericBaseClass(object):
|
|||||||
base._wrapped_value,
|
base._wrapped_value,
|
||||||
TupleGenericManager(tuple(self._remap_type_vars(base))),
|
TupleGenericManager(tuple(self._remap_type_vars(base))),
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
if base.is_class_mixin():
|
||||||
|
# This case basically allows classes like `class Foo(List)`
|
||||||
|
# to be used like `Foo[int]`. The generics are not
|
||||||
|
# necessary and can be used later.
|
||||||
|
yield GenericClass.create_cached(
|
||||||
|
base.inference_state,
|
||||||
|
base,
|
||||||
|
self._generics_manager,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
yield base
|
yield base
|
||||||
|
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ class ClassMixin(object):
|
|||||||
def is_class(self):
|
def is_class(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def is_class_mixin(self):
|
||||||
|
return True
|
||||||
|
|
||||||
def py__call__(self, arguments=None):
|
def py__call__(self, arguments=None):
|
||||||
from jedi.inference.value import TreeInstance
|
from jedi.inference.value import TreeInstance
|
||||||
|
|
||||||
@@ -314,6 +317,7 @@ class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase
|
|||||||
def py__getitem__(self, index_value_set, contextualized_node):
|
def py__getitem__(self, index_value_set, contextualized_node):
|
||||||
from jedi.inference.gradual.base import GenericClass
|
from jedi.inference.gradual.base import GenericClass
|
||||||
if not index_value_set:
|
if not index_value_set:
|
||||||
|
debug.warning('Class indexes inferred to nothing. Returning class instead')
|
||||||
return ValueSet([self])
|
return ValueSet([self])
|
||||||
return ValueSet(
|
return ValueSet(
|
||||||
GenericClass(
|
GenericClass(
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ def _create_manager_for(cls, manager_cls='BaseManager'):
|
|||||||
('django', 'db', 'models', 'manager')
|
('django', 'db', 'models', 'manager')
|
||||||
).py__getattribute__(manager_cls)
|
).py__getattribute__(manager_cls)
|
||||||
for m in managers:
|
for m in managers:
|
||||||
if m.is_class() and not m.is_compiled():
|
if m.is_class_mixin():
|
||||||
generics_manager = TupleGenericManager((ValueSet([cls]),))
|
generics_manager = TupleGenericManager((ValueSet([cls]),))
|
||||||
for c in GenericClass(m, generics_manager).execute_annotation():
|
for c in GenericClass(m, generics_manager).execute_annotation():
|
||||||
return c
|
return c
|
||||||
|
|||||||
@@ -126,3 +126,19 @@ for p in typed_bound_generic_passthrough(untyped_list_str):
|
|||||||
for q in typed_bound_generic_passthrough(typed_list_str):
|
for q in typed_bound_generic_passthrough(typed_list_str):
|
||||||
#? str()
|
#? str()
|
||||||
q
|
q
|
||||||
|
|
||||||
|
|
||||||
|
class CustomList(List):
|
||||||
|
def get_first(self):
|
||||||
|
return self[0]
|
||||||
|
|
||||||
|
|
||||||
|
#? str()
|
||||||
|
CustomList[str]()[0]
|
||||||
|
#? str()
|
||||||
|
CustomList[str]().get_first()
|
||||||
|
|
||||||
|
#? str()
|
||||||
|
typed_fully_generic_passthrough(CustomList[str]())[0]
|
||||||
|
#?
|
||||||
|
typed_list_generic_passthrough(CustomList[str])[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user