| """ | |
| TODO Some parts of this module are still not well documented. | |
| """ | |
| from jedi.inference import compiled | |
| from jedi.inference.base_value import ValueSet | |
| from jedi.inference.filters import ParserTreeFilter, MergedFilter | |
| from jedi.inference.names import TreeNameDefinition | |
| from jedi.inference.compiled import mixed | |
| from jedi.inference.compiled.access import create_access_path | |
| from jedi.inference.context import ModuleContext | |
| def _create(inference_state, obj): | |
| return compiled.create_from_access_path( | |
| inference_state, create_access_path(inference_state, obj) | |
| ) | |
| class NamespaceObject: | |
| def __init__(self, dct): | |
| self.__dict__ = dct | |
| class MixedTreeName(TreeNameDefinition): | |
| def infer(self): | |
| """ | |
| In IPython notebook it is typical that some parts of the code that is | |
| provided was already executed. In that case if something is not properly | |
| inferred, it should still infer from the variables it already knows. | |
| """ | |
| inferred = super().infer() | |
| if not inferred: | |
| for compiled_value in self.parent_context.mixed_values: | |
| for f in compiled_value.get_filters(): | |
| values = ValueSet.from_sets( | |
| n.infer() for n in f.get(self.string_name) | |
| ) | |
| if values: | |
| return values | |
| return inferred | |
| class MixedParserTreeFilter(ParserTreeFilter): | |
| name_class = MixedTreeName | |
| class MixedModuleContext(ModuleContext): | |
| def __init__(self, tree_module_value, namespaces): | |
| super().__init__(tree_module_value) | |
| self.mixed_values = [ | |
| self._get_mixed_object( | |
| _create(self.inference_state, NamespaceObject(n)) | |
| ) for n in namespaces | |
| ] | |
| def _get_mixed_object(self, compiled_value): | |
| return mixed.MixedObject( | |
| compiled_value=compiled_value, | |
| tree_value=self._value | |
| ) | |
| def get_filters(self, until_position=None, origin_scope=None): | |
| yield MergedFilter( | |
| MixedParserTreeFilter( | |
| parent_context=self, | |
| until_position=until_position, | |
| origin_scope=origin_scope | |
| ), | |
| self.get_global_filter(), | |
| ) | |
| for mixed_object in self.mixed_values: | |
| yield from mixed_object.get_filters(until_position, origin_scope) | |