diff --git a/evaluate.py b/evaluate.py index fc84e768..c58c0589 100644 --- a/evaluate.py +++ b/evaluate.py @@ -116,7 +116,7 @@ class CachedMetaClass(type): return super(CachedMetaClass, self).__call__(*args, **kwargs) -class Executable(object): +class Executable(parsing.Base): """ An instance is also an executable - because __init__ is called """ def __init__(self, base, var_args=parsing.Array(None, None)): self.base = base @@ -240,7 +240,7 @@ class Instance(Executable): (self.__class__.__name__, self.base, len(self.var_args or [])) -class InstanceElement(object): +class InstanceElement(): def __init__(self, instance, var): if isinstance(var, parsing.Function): var = Function(var) @@ -283,11 +283,14 @@ class InstanceElement(object): def __getattr__(self, name): return getattr(self.var, name) + def isinstance(self, *cls): + return isinstance(self.var, cls) + def __repr__(self): return "<%s of %s>" % (self.__class__.__name__, self.var) -class Class(object): +class Class(parsing.Base): __metaclass__ = CachedMetaClass def __init__(self, base): @@ -342,7 +345,7 @@ class Class(object): return "" % (self.__class__.__name__, self.base) -class Function(object): +class Function(parsing.Base): """ """ __metaclass__ = CachedMetaClass @@ -679,7 +682,7 @@ class Execution(Executable): (self.__class__.__name__, self.base) -class Generator(object): +class Generator(parsing.Base): def __init__(self, func, var_args): super(Generator, self).__init__() self.func = func @@ -719,7 +722,7 @@ class Generator(object): return "<%s of %s>" % (self.__class__.__name__, self.func) -class Array(object): +class Array(parsing.Base): """ Used as a mirror to parsing.Array, if needed. It defines some getter methods which are important in this module. @@ -852,11 +855,8 @@ def get_names_for_scope(scope, position=None, star_search=True, # `parsing.Class` is used, because the parent is never `Class`. # Ignore the Flows, because the classes and functions care for that. # InstanceElement of Class is ignored, if it is not the start scope. - if not (scope != start_scope and isinstance(scope, parsing.Class) - or isinstance(scope, parsing.Flow) - or scope != start_scope and isinstance(scope, InstanceElement) - and isinstance(scope.var, parsing.Class)): - + if not (scope != start_scope and scope.isinstance(parsing.Class) + or isinstance(scope, parsing.Flow)): try: yield scope, get_defined_names_for_position(scope, position, in_scope) @@ -895,9 +895,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False): """ res_new = [] for r in result: - if isinstance(r, parsing.Statement) \ - or isinstance(r, InstanceElement) \ - and isinstance(r.var, parsing.Statement): + if r.isinstance(parsing.Statement): # Global variables handling. if r.is_global(): for token_name in r.token_list[1:]: @@ -920,8 +918,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False): r = Class(r) elif isinstance(r, parsing.Function): r = Function(r) - if isinstance(r, Function) or isinstance(r, InstanceElement)\ - and isinstance(r.var, Function): + if r.isinstance(Function): try: r = r.get_decorated_func() except DecoratorNotFound: @@ -937,8 +934,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False): and scope.var == name.parent.parent: name = InstanceElement(scope.instance, name) par = name.parent - if isinstance(par, parsing.Flow) or isinstance(par, - InstanceElement) and isinstance(par.var, parsing.Flow) : + if par.isinstance(parsing.Flow): if par.command == 'for': # Take the first statement (for has always only # one, remember `in`). And follow it. After that, diff --git a/parsing.py b/parsing.py index bbd811af..b5632aff 100644 --- a/parsing.py +++ b/parsing.py @@ -52,7 +52,19 @@ def indent_block(text, indention=" "): return '\n'.join(map(lambda s: indention + s, lines)) + temp -class Simple(object): +class Base(object): + """ + This is just here to have an isinstance check, which is also used on + evaluate classes. But since they have sometimes a special type of + delegation, it is important for those classes to override this method. + + I know that there is a chance to do such things with __instancecheck__, but + since Python 2.5 doesn't support it, I decided to do it this way. + """ + def isinstance(self, *cls): + return isinstance(self, cls) + +class Simple(Base): """ The super class for Scope, Import, Name and Statement. Every object in the parser tree inherits from this class.