diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index 705e356b..82229ba7 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -22,6 +22,15 @@ def builtin_from_name(evaluator, string): return create(evaluator, bltn_obj) +def create_simple_object(evaluator, obj): + """ + Only allows creations of objects that are easily picklable across Python + versions. + """ + assert isinstance(obj, (int, float, str, bytes, slice, complex, type(Ellipsis))) + return create(evaluator, obj) + + def create(evaluator, obj): return create_from_access( evaluator, create_access(evaluator, obj) diff --git a/jedi/evaluate/context/instance.py b/jedi/evaluate/context/instance.py index ca92b012..cba0199c 100644 --- a/jedi/evaluate/context/instance.py +++ b/jedi/evaluate/context/instance.py @@ -124,7 +124,7 @@ class AbstractInstanceContext(Context): debug.warning('No __getitem__, cannot access the array.') return NO_CONTEXTS else: - index_obj = compiled.create(self.evaluator, index) + index_obj = compiled.create_simple_object(self.evaluator, index) return self.execute_function_slots(names, index_obj) def py__iter__(self): diff --git a/jedi/evaluate/context/iterable.py b/jedi/evaluate/context/iterable.py index 352738c5..0536bf69 100644 --- a/jedi/evaluate/context/iterable.py +++ b/jedi/evaluate/context/iterable.py @@ -443,7 +443,7 @@ class FakeDict(_FakeArray): def py__iter__(self): for key in self._dct: - yield LazyKnownContext(compiled.create(self.evaluator, key)) + yield LazyKnownContext(compiled.create_simple_object(self.evaluator, key)) def py__getitem__(self, index): return self._dct[index].infer() diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 96032ae9..d94add4a 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -140,7 +140,7 @@ class NameFinder(object): def _check_getattr(self, inst): """Checks for both __getattr__ and __getattribute__ methods""" # str is important, because it shouldn't be `Name`! - name = compiled.create(self._evaluator, self._string_name) + name = compiled.create_simple_object(self._evaluator, self._string_name) # This is a little bit special. `__getattribute__` is in Python # executed before `__getattr__`. But: I know no use case, where diff --git a/jedi/evaluate/pep0484.py b/jedi/evaluate/pep0484.py index 4d575308..419cf400 100644 --- a/jedi/evaluate/pep0484.py +++ b/jedi/evaluate/pep0484.py @@ -167,7 +167,7 @@ def py__getitem__(context, typ, node): if isinstance(child, tree.Class)) if type_name not in valid_classnames: return None - compiled_classname = compiled.create(context.evaluator, type_name) + compiled_classname = compiled.create_simple_object(context.evaluator, type_name) from jedi.evaluate.context.iterable import FakeSequence args = FakeSequence( diff --git a/jedi/evaluate/syntax_tree.py b/jedi/evaluate/syntax_tree.py index f23dff87..b03a1f06 100644 --- a/jedi/evaluate/syntax_tree.py +++ b/jedi/evaluate/syntax_tree.py @@ -174,7 +174,7 @@ def eval_atom(context, atom): elif isinstance(atom, tree.Literal): string = parser_utils.safe_literal_eval(atom.value) - return ContextSet(compiled.create(context.evaluator, string)) + return ContextSet(compiled.create_simple_object(context.evaluator, string)) else: c = atom.children if c[0].type == 'string': @@ -313,7 +313,7 @@ def eval_factor(context_set, operator): value = context.py__bool__() if value is None: # Uncertainty. return - yield compiled.create(context.evaluator, not value) + yield compiled.create_simple_object(context.evaluator, not value) else: yield context