'Compute matches when text contains a dot.
Assuming the text is of the form NAME.NAME....[NAME], and is
evaluable in self.namespace, it will be evaluated and its attributes
(as revealed by dir()) are used as possible completions.  (For class
instances, class members are also considered.)
WARNING: this can still invoke arbitrary C code, if an object
with a __getattr__ hook is evaluated.'

def attr_matches(self, text):

    import re
    m = re.match('(\\w+(\\.\\w+)*)\\.(\\w*)', text)
    if (not m):
        return []
    (expr, attr) = m.group(1, 3)
    try:
        thisobject = eval(expr, self.namespace)
    except Exception:
        return []
    words = set(dir(thisobject))
    words.discard('__builtins__')
    if hasattr(thisobject, '__class__'):
        words.add('__class__')
        words.update(get_class_members(thisobject.__class__))
    matches = []
    n = len(attr)
    if (attr == ''):
        noprefix = '_'
    elif (attr == '_'):
        noprefix = '__'
    else:
        noprefix = None
    while True:
        for word in words:
            if ((word[:n] == attr) and (not (noprefix and (word[:(n + 1)] == noprefix)))):
                match = ('%s.%s' % (expr, word))
                try:
                    val = getattr(thisobject, word)
                except Exception:
                    pass
                else:
                    match = self._callable_postfix(val, match)
                matches.append(match)
        if (matches or (not noprefix)):
            break
        if (noprefix == '_'):
            noprefix = '__'
        else:
            noprefix = None
    matches.sort()
    return matches
