def get_trait_names(): global TRAIT_NAMES from enthought.traits.api import HasTraits if TRAIT_NAMES is None: TRAIT_NAMES = set( dir2(HasTraits()) ) - set( dir2(object()) ) else: return TRAIT_NAMES
def test_misbehaving_object_without_trait_names(): # dir2 shouldn't raise even when objects are dumb and raise # something other than AttribteErrors on bad getattr. class BadTraitNames(object): @property def trait_names(self): raise KeyboardInterrupt("This should be caught") def some_method(self): pass class MisbehavingGetattr(object): def __getattr__(self): raise KeyError("I should be caught") def some_method(self): pass class SillierWithDir(MisbehavingGetattr): def __dir__(self): return ['some_method'] for bad_klass in (BadTraitNames, MisbehavingGetattr, SillierWithDir): res = dir2(bad_klass()) assert('some_method' in res)
def test_misbehaving_object_without_trait_names(): # dir2 shouldn't raise even when objects are dumb and raise # something other than AttribteErrors on bad getattr. class MisbehavingGetattr: def __getattr__(self, attr): raise KeyError("I should be caught") def some_method(self): return True class SillierWithDir(MisbehavingGetattr): def __dir__(self): return ['some_method'] for bad_klass in (MisbehavingGetattr, SillierWithDir): obj = bad_klass() assert obj.some_method() with pytest.raises(KeyError): obj.other_method() res = dir2(obj) assert "some_method" in res
def __init__(self,obj,name_pattern="*",type_pattern="all",ignore_case=True, show_all=True): self.show_all = show_all #Hide names beginning with single _ self.object = obj self.name_pattern = name_pattern self.type_pattern = type_pattern self.ignore_case = ignore_case # We should only match EXACT dicts here, so DON'T use isinstance() if type(obj) == types.DictType: self._ns = obj else: kv = [] for key in dir2(obj): if isinstance(key, basestring): # This seemingly unnecessary try/except is actually needed # because there is code out there with metaclasses that # create 'write only' attributes, where a getattr() call # will fail even if the attribute appears listed in the # object's dictionary. Properties can actually do the same # thing. In particular, Traits use this pattern try: kv.append((key,getattr(obj,key))) except AttributeError: pass self._ns = dict(kv)
def __init__(self, obj, name_pattern="*", type_pattern="all", ignore_case=True, show_all=True): self.show_all = show_all #Hide names beginning with single _ self.object = obj self.name_pattern = name_pattern self.type_pattern = type_pattern self.ignore_case = ignore_case # We should only match EXACT dicts here, so DON'T use isinstance() if type(obj) == types.DictType: self._ns = obj else: kv = [] for key in dir2(obj): if isinstance(key, basestring): # This seemingly unnecessary try/except is actually needed # because there is code out there with metaclasses that # create 'write only' attributes, where a getattr() call # will fail even if the attribute appears listed in the # object's dictionary. Properties can actually do the same # thing. In particular, Traits use this pattern try: kv.append((key, getattr(obj, key))) except AttributeError: pass self._ns = dict(kv)
def test_base(): res = dir2(Base()) assert ('x' in res) assert ('z' in res) assert ('y' not in res) assert ('__class__' in res) nt.assert_equal(res.count('x'), 1) nt.assert_equal(res.count('__class__'), 1)
def test_SubClass(): class SubClass(Base): y = 2 res = dir2(SubClass()) assert ('y' in res) nt.assert_equal(res.count('y'), 1) nt.assert_equal(res.count('x'), 1)
def test_base(): res = dir2(Base()) assert "x" in res assert "z" in res assert "y" not in res assert "__class__" in res nt.assert_equal(res.count("x"), 1) nt.assert_equal(res.count("__class__"), 1)
def test_SubClass(): class SubClass(Base): y = 2 res = dir2(SubClass()) assert "y" in res nt.assert_equal(res.count("y"), 1) nt.assert_equal(res.count("x"), 1)
def test_base(): res = dir2(Base()) assert "x" in res assert "z" in res assert "y" not in res assert "__class__" in res assert res.count("x") == 1 assert res.count("__class__") == 1
def test_SubClass_with_trait_names_attr(): # usecase: trait_names is used in a class describing psychological classification class SubClass(Base): y = 2 trait_names = 44 res = dir2(SubClass()) assert('trait_names' in res)
def test_SubClass_with_trait_names_attr(): # usecase: trait_names is used in a class describing psychological classification class SubClass(Base): y = 2 trait_names = 44 res = dir2(SubClass()) assert "trait_names" in res
def test_SubClass(): class SubClass(Base): y = 2 res = dir2(SubClass()) assert "y" in res assert res.count("y") == 1 assert res.count("x") == 1
def trait_completer(self,event): """A custom IPython tab-completer that is traits-aware. It tries to hide the internal traits attributes, and reveal them only when it can reasonably guess that the user really is after one of them. """ #print '\nevent is:',event # dbg symbol_parts = event.symbol.split('.') base = '.'.join(symbol_parts[:-1]) #print 'base:',base # dbg oinfo = self._ofind(base) if not oinfo['found']: raise TryNext obj = oinfo['obj'] # OK, we got the object. See if it's traits, else punt if not looks_like_isinstance(obj, 'HasTraits'): raise TryNext # Defer import until here so as not to require Traits until we get something # that looks like it might be a HasTraits instance. from enthought.traits.api import HasTraits if not isinstance(obj, HasTraits): raise TryNext # it's a traits object, don't show the tr* attributes unless the completion # begins with 'tr' attrs = dir2(obj) # Now, filter out the attributes that start with the user's request attr_start = symbol_parts[-1] if attr_start: attrs = [a for a in attrs if a.startswith(attr_start)] # Let's also respect the user's readline_omit__names setting: omit__names = ipget().options.readline_omit__names if omit__names == 1: attrs = [a for a in attrs if not a.startswith('__')] elif omit__names == 2: attrs = [a for a in attrs if not a.startswith('_')] #print '\nastart:<%r>' % attr_start # dbg if len(attr_start)<COMPLETE_THRESHOLD: attrs = list(set(attrs) - get_trait_names()) # The base of the completion, so we can form the final results list bdot = base+'.' tcomp = [bdot+a for a in attrs] #print 'tcomp:',tcomp return tcomp
def attr_matches(self, text): """Compute matches when text contains a dot. Assuming the text is of the form NAME.NAME....[NAME], and is evaluatable in self.namespace or self.global_namespace, it will be evaluated and its attributes (as revealed by dir()) are used as possible completions. (For class instances, class members are are also considered.) WARNING: this can still invoke arbitrary C code, if an object with a __getattr__ hook is evaluated. """ #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg # Another option, seems to work great. Catches things like ''.<tab> m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) if m: expr, attr = m.group(1, 3) elif self.greedy: m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer) if not m2: return [] expr, attr = m2.group(1, 2) else: return [] try: obj = eval(expr, self.namespace) except: try: obj = eval(expr, self.global_namespace) except: return [] if self.limit_to__all__ and hasattr(obj, '__all__'): words = get__all__entries(obj) else: words = dir2(obj) try: words = generics.complete_object(obj, words) except TryNext: pass except Exception: # Silence errors from completion function #raise # dbg pass # Build match list to return n = len(attr) res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr] return res
def attr_matches(self, text): """Compute matches when text contains a dot. Assuming the text is of the form NAME.NAME....[NAME], and is evaluatable in self.namespace or self.global_namespace, it will be evaluated and its attributes (as revealed by dir()) are used as possible completions. (For class instances, class members are are also considered.) WARNING: this can still invoke arbitrary C code, if an object with a __getattr__ hook is evaluated. """ #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg # Another option, seems to work great. Catches things like ''.<tab> m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) if m: expr, attr = m.group(1, 3) elif self.greedy: m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer) if not m2: return [] expr, attr = m2.group(1,2) else: return [] try: obj = eval(expr, self.namespace) except: try: obj = eval(expr, self.global_namespace) except: return [] if self.limit_to__all__ and hasattr(obj, '__all__'): words = get__all__entries(obj) else: words = dir2(obj) try: words = generics.complete_object(obj, words) except TryNext: pass except Exception: # Silence errors from completion function #raise # dbg pass # Build match list to return n = len(attr) res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ] return res
def test_SubClass_with_trait_names_method(): class SubClass(Base): y = 2 def trait_names(self): return ['t', 'umbrella'] res = dir2(SubClass()) assert('trait_names' in res) assert('umbrella' in res) nt.assert_equal(res[-6:], ['t', 'trait_names','umbrella', 'x','y','z']) nt.assert_equal(res.count('t'), 1)
def attr_matches(self, text): """Compute matches when text contains a dot. Assuming the text is of the form NAME.NAME....[NAME], and is evaluatable in self.namespace or self.global_namespace, it will be evaluated and its attributes (as revealed by dir()) are used as possible completions. (For class instances, class members are are also considered.) WARNING: this can still invoke arbitrary C code, if an object with a __getattr__ hook is evaluated. """ force_complete = 1 #print 'Completer->attr_matches, txt=%r' % text # dbg lbuf = readline.get_line_buffer() # Another option, seems to work great. Catches things like ''.<tab> m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) if m: expr, attr = m.group(1, 3) else: # force match - eval anything that ends with colon if not force_complete: return [] m2 = re.match(r"(.+)\.(\w*)$", lbuf) if not m2: return [] expr, attr = m2.group(1,2) try: obj = eval(expr, self.namespace) except: try: obj = eval(expr, self.global_namespace) except: return [] words = dir2(obj) try: words = generics.complete_object(obj, words) except TryNext: pass # Build match list to return n = len(attr) res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ] return res
def attr_matches(self, text): """Compute matches when text contains a dot. MONKEYPATCHED VERSION (ipy_greedycompleter.py) Assuming the text is of the form NAME.NAME....[NAME], and is evaluatable in self.namespace or self.global_namespace, it will be evaluated and its attributes (as revealed by dir()) are used as possible completions. (For class instances, class members are are also considered.) WARNING: this can still invoke arbitrary C code, if an object with a __getattr__ hook is evaluated. """ import re force_complete = 1 # Another option, seems to work great. Catches things like ''.<tab> m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) if m: expr, attr = m.group(1, 3) else: # force match - eval anything that ends with colon if not force_complete: return [] m2 = re.match(r"(.+)\.(\w*)$", self.lbuf) if not m2: return [] expr, attr = m2.group(1, 2) try: obj = eval(expr, self.namespace) except: try: obj = eval(expr, self.global_namespace) except: return [] words = dir2(obj) try: words = generics.complete_object(obj, words) except TryNext: pass # Build match list to return n = len(attr) res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr] return res
def dict_dir(obj): """Produce a dictionary of an object's attributes. Builds on dir2 by checking that a getattr() call actually succeeds.""" ns = {} for key in dir2(obj): # This seemingly unnecessary try/except is actually needed # because there is code out there with metaclasses that # create 'write only' attributes, where a getattr() call # will fail even if the attribute appears listed in the # object's dictionary. Properties can actually do the same # thing. In particular, Traits use this pattern try: ns[key] = getattr(obj, key) except AttributeError: pass return ns
def test_misbehaving_object_without_trait_names(): # dir2 shouldn't raise even when objects are dumb and raise # something other than AttribteErrors on bad getattr. class MisbehavingGetattr(object): def __getattr__(self): raise KeyError("I should be caught") def some_method(self): pass class SillierWithDir(MisbehavingGetattr): def __dir__(self): return ["some_method"] for bad_klass in (MisbehavingGetattr, SillierWithDir): res = dir2(bad_klass()) assert "some_method" in res
def attr_matches(self, text): """Compute matches when text contains a dot. Assuming the text is of the form NAME.NAME....[NAME], and is evaluatable in self.namespace or self.global_namespace, it will be evaluated and its attributes (as revealed by dir()) are used as possible completions. (For class instances, class members are are also considered.) WARNING: this can still invoke arbitrary C code, if an object with a __getattr__ hook is evaluated. """ #print 'Completer->attr_matches, txt=%r' % text # dbg # Another option, seems to work great. Catches things like ''.<tab> m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) if not m: return [] expr, attr = m.group(1, 3) try: obj = eval(expr, self.namespace) except: try: obj = eval(expr, self.global_namespace) except: return [] words = dir2(obj) try: words = generics.complete_object(obj, words) except TryNext: pass # Build match list to return n = len(attr) res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr] return res