From cf923ec6deb1d154e03cd48c1af87a522a5b5359 Mon Sep 17 00:00:00 2001 From: yuan Date: Sun, 7 Jun 2020 11:48:21 +0800 Subject: [PATCH 1/3] Update MANIFEST.in --- MANIFEST.in | 1 - 1 file changed, 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 3b76f251..83368474 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -8,7 +8,6 @@ include conftest.py include pytest.ini include tox.ini include requirements.txt -include jedi/parser/python/grammar*.txt recursive-include jedi/third_party *.pyi include jedi/third_party/typeshed/LICENSE include jedi/third_party/django-stubs/LICENSE.txt From df7dd026d22caf34314efb090783863c62b29bd2 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 6 Jun 2020 01:23:14 +0200 Subject: [PATCH 2/3] Make it possible to use inheritance on generics without always specifying type vars, see also discussion in #1593 --- jedi/inference/base_value.py | 3 +++ jedi/inference/gradual/base.py | 17 ++++++++++++++--- jedi/inference/value/klass.py | 4 ++++ jedi/plugins/django.py | 2 +- test/completion/pep0484_generic_passthroughs.py | 16 ++++++++++++++++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/jedi/inference/base_value.py b/jedi/inference/base_value.py index dfa2c230..075de49a 100644 --- a/jedi/inference/base_value.py +++ b/jedi/inference/base_value.py @@ -174,6 +174,9 @@ class Value(HelperValueMixin): def is_class(self): return False + def is_class_mixin(self): + return False + def is_instance(self): return False diff --git a/jedi/inference/gradual/base.py b/jedi/inference/gradual/base.py index e7940800..44564f65 100644 --- a/jedi/inference/gradual/base.py +++ b/jedi/inference/gradual/base.py @@ -190,7 +190,7 @@ class GenericClass(ClassMixin, DefineGenericBaseClass): @to_list def py__bases__(self): 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): return GenericClass(self._class_value, generics_manager) @@ -241,9 +241,10 @@ class GenericClass(ClassMixin, DefineGenericBaseClass): 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._lazy_base_class = lazy_base_class + self._generics_manager = generics_manager @iterator_to_value_set def infer(self): @@ -256,7 +257,17 @@ class _LazyGenericBaseClass(object): TupleGenericManager(tuple(self._remap_type_vars(base))), ) else: - yield base + 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: + yield base def _remap_type_vars(self, base): from jedi.inference.gradual.type_var import TypeVar diff --git a/jedi/inference/value/klass.py b/jedi/inference/value/klass.py index ec51b24a..4a47da0e 100644 --- a/jedi/inference/value/klass.py +++ b/jedi/inference/value/klass.py @@ -135,6 +135,9 @@ class ClassMixin(object): def is_class(self): return True + def is_class_mixin(self): + return True + def py__call__(self, arguments=None): 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): from jedi.inference.gradual.base import GenericClass if not index_value_set: + debug.warning('Class indexes inferred to nothing. Returning class instead') return ValueSet([self]) return ValueSet( GenericClass( diff --git a/jedi/plugins/django.py b/jedi/plugins/django.py index 43cbaf01..89bc38c6 100644 --- a/jedi/plugins/django.py +++ b/jedi/plugins/django.py @@ -102,7 +102,7 @@ def _create_manager_for(cls, manager_cls='BaseManager'): ('django', 'db', 'models', 'manager') ).py__getattribute__(manager_cls) for m in managers: - if m.is_class() and not m.is_compiled(): + if m.is_class_mixin(): generics_manager = TupleGenericManager((ValueSet([cls]),)) for c in GenericClass(m, generics_manager).execute_annotation(): return c diff --git a/test/completion/pep0484_generic_passthroughs.py b/test/completion/pep0484_generic_passthroughs.py index 3ccdae7a..4fccc5ed 100644 --- a/test/completion/pep0484_generic_passthroughs.py +++ b/test/completion/pep0484_generic_passthroughs.py @@ -126,3 +126,19 @@ for p in typed_bound_generic_passthrough(untyped_list_str): for q in typed_bound_generic_passthrough(typed_list_str): #? str() 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] From 3a0a484fcb73b2a429913b394eadd4e902cc89df Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Wed, 10 Jun 2020 09:36:39 +0200 Subject: [PATCH 3/3] Try to get get the tests for Python 3.9 passing, fixes #1608 --- .travis.yml | 1 + test/test_api/test_api.py | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8c0b9a38..b31b114c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ dist: xenial language: python python: + - 3.9-dev - 3.8 - 3.7 - 3.6 diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index 0099eaa4..56516073 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -134,8 +134,19 @@ def test_infer_on_non_name(Script): assert Script('import x').infer(column=0) == [] -def test_infer_on_generator(Script): - def_, = Script('def x(): yield 1\ny=x()\ny').infer() +def test_infer_on_generator(Script, environment): + script = Script('def x(): yield 1\ny=x()\ny') + def_, = script.infer() + if environment.version_info >= (3, 9): + # The Generator in Python 3.9 is properly inferred, however once it is + # converted from stub to Python, the definition is + # Generator = _SpecialGenericAlias(collections.abc.Generator, 3) + # This is pretty normal for most typing types, like Sequence, List, + # etc. + assert def_.name == '_SpecialGenericAlias' + else: + assert def_.name == 'Generator' + def_, = script.infer(only_stubs=True) assert def_.name == 'Generator'