names_dicts for instances.

This commit is contained in:
Dave Halter
2015-01-02 00:19:07 +01:00
parent 9de4a5479c
commit 0478ff907f

View File

@@ -182,6 +182,44 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
names += inst.get_self_attributes(add_mro=False) names += inst.get_self_attributes(add_mro=False)
return names return names
def _self_names_dict(self, add_mro=True):
names = {}
# This loop adds the names of the self object, copies them and removes
# the self.
for sub in self.base.subscopes:
if isinstance(sub, pr.Class):
continue
# Get the self name, if there's one.
self_name = self._get_func_self_name(sub)
if self_name is None:
continue
if sub.name.value == '__init__' and not self.is_generated:
# ``__init__`` is special because the params need are injected
# this way. Therefore an execution is necessary.
if not sub.get_decorators():
# __init__ decorators should generally just be ignored,
# because to follow them and their self variables is too
# complicated.
sub = self._get_method_execution(sub)
for name_list in sub.names_dict.values():
for name in name_list:
if name.value == self_name and name.prev_sibling() is None:
trailer = name.next_sibling()
if pr.is_node(trailer, 'trailer') \
and len(trailer.children) == 2:
name = trailer.children[1] # After dot.
if name.is_definition():
arr = names.setdefault(name.value, [])
arr.append(get_instance_el(self._evaluator, self, name))
if add_mro and False: # TODO ADD!!!!
for s in self.base.py__mro__(self._evaluator)[1:]:
if not isinstance(s, compiled.CompiledObject):
for inst in self._evaluator.execute(s):
names += inst.get_self_attributes(add_mro=False)
return names
def get_subscope_by_name(self, name): def get_subscope_by_name(self, name):
sub = self.base.get_subscope_by_name(name) sub = self.base.get_subscope_by_name(name)
return get_instance_el(self._evaluator, self, sub, True) return get_instance_el(self._evaluator, self, sub, True)
@@ -197,6 +235,13 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
args = [obj, obj.base] if isinstance(obj, Instance) else [compiled.none_obj, obj] args = [obj, obj.base] if isinstance(obj, Instance) else [compiled.none_obj, obj]
return self.execute_subscope_by_name('__get__', *args) return self.execute_subscope_by_name('__get__', *args)
@memoize_default([])
def names_dicts(self):
yield self._self_names_dict()
for names_dict in self.base.names_dicts():
yield LazyInstanceDict(self._evaluator, self, names_dict)
def scope_names_generator(self, position=None): def scope_names_generator(self, position=None):
""" """
An Instance has two scopes: The scope with self names and the class An Instance has two scopes: The scope with self names and the class
@@ -245,6 +290,27 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
self.var_args, dec) self.var_args, dec)
class LazyInstanceDict(object):
def __init__(self, evaluator, instance, dct):
self._evaluator = evaluator
self._instance = instance
self._dct = dct
def __getitem__(self, name):
return [get_instance_el(self._evaluator, self._instance, var, True)
for var in self._dct[name]]
class InstanceName(pr.Name):
def __init__(self, origin_name, parent):
super(InstanceName, self).__init__(origin_name.value, origin_name.start_pos)
self._origin_name = origin_name
self.parent = parent
def is_definition(self):
return self._origin_name.is_definition()
def get_instance_el(evaluator, instance, var, is_class_var=False): def get_instance_el(evaluator, instance, var, is_class_var=False):
""" """
Returns an InstanceElement if it makes sense, otherwise leaves the object Returns an InstanceElement if it makes sense, otherwise leaves the object
@@ -255,10 +321,8 @@ def get_instance_el(evaluator, instance, var, is_class_var=False):
if isinstance(var, pr.Name): if isinstance(var, pr.Name):
# TODO temp solution, remove later, Name should never get # TODO temp solution, remove later, Name should never get
# here? # here?
par = get_instance_el(evaluator, instance, var.parent, is_class_var) parent = get_instance_el(evaluator, instance, var.parent)
name = pr.Name(unicode(var), var.start_pos) return InstanceName(var, parent)
name.parent = par
return name
return var return var
var = wrap(evaluator, var) var = wrap(evaluator, var)
@@ -308,6 +372,9 @@ class InstanceElement(use_metaclass(CachedMetaClass, pr.Base)):
return get_instance_el(self._evaluator, self.instance, return get_instance_el(self._evaluator, self.instance,
self.var.get_rhs(), self.is_class_var) self.var.get_rhs(), self.is_class_var)
def is_definition(self):
return self.var.is_definition()
@property @property
def children(self): def children(self):
# Copy and modify the array. # Copy and modify the array.