[IPython-dev] Tab-completion of data/properties and win32com fix for IPython

Jaco Schieke ipython at ml.schieke.net
Tue Aug 3 19:22:01 EDT 2004


Some clarifications:
1. The dictionary hack is simply to keep "matches" unique.  It took me a 
while to realize this, but pyreadline actually expects an unique array 
(see lib\site-packages\readline\pyreadline.py(788): if r and r not in 
completions:), otherwise it stops reading from the matches returned and 
simply exits.  This is not win32 specific and should be a usefull 
addition should be incorporated into rlcompleter.py.  An easy way to 
test this is to add matches.sort() just before you return matches in 
FlexCompleter.py.  Then try [].<tab> ... the results are disappointing.  
The reason for this is obviously that you first dir() the object and 
then the base classes, so you'd not notice this normally.  However 
sorting the array (or adding COM attributes after you dir()'ed the base 
classes) causes the issues, as duplicates appear very quickly.  It took 
me quite some time to figure this out. - so in short: matches must be 
unique'd and list2dict is the easiest way I know (I may be rusty.)  Let 
me know if you concur then I'll submit a bug report for rlcompleter.py.

2. I've rewritten the function to check for sys.platform and only run 
win32 hacks if on the right platform - patch follows..



Index: ipython/IPython/FlexCompleter.py
RCS file: /home/cvsroot/world/ipython/IPython/FlexCompleter.py,v
retrieving revision 1.3
diff -B -r1.3 FlexCompleter.py
 > import sys
<         instances, class members are are also considered.)
 >         instances, class members are are also considered.)  A unique 
array is returned
<         import re
 >         def list2dict(l):
 >             ret={}
 >             for i in l:
 >                 ret[i] = None
 >             return ret
 >         import re
 >         matches_dict = {}
 >         matches_dict.update(list2dict(matches)) # ensures uniqueness
 >         matches = matches_dict.keys()
 >         matches.sort()
 > if sys.platform == "win32":
 >     def get_class_members(klass):
 >     """Obtains class and base class members through dir()
 >     Additional query is also performed in the case that the class is a
 >     COM object instantiated by the win32 module of Mark Hammond,
 >     as dir() does not reveal the properties associated with
 >     the COM object. 
 >     """
 >     ret = dir(klass)
 >     if hasattr(klass,'__bases__'):
 >         for base in klass.__bases__:
 >         ret = ret + get_class_members(base)
 >     #Win32 specific code follows
 >     try:    # in case klass is a COM object from win32
 >         ret=ret+klass._prop_map_get_.keys()
 >         ret=ret+klass._prop_map_put_.keys()
 >         pass
 >     except AttributeError:
 >         pass
 >     #End of Win32 specific code
 >     return ret

Fernando Perez wrote:

> Jaco Schieke wrote:
>> (Patch follows at the end of email)
> I have some questions about this.  I'll also make some general 
> comments about patches in a separate mail, please heed them for the 
> future.
> Since I may keep FlexCompleter around, I want to clarify a few things 
> about your patch.
>>>        def list2dict(l):
>>>            ret={}
>>>            for i in l:
>>>             ret[i] = None
>>>            return ret
>> 185a191,194
>>>        matches_dict = {}
>>>        matches_dict.update(list2dict(matches))
>>>        matches = matches_dict.keys()
>>>        matches.sort()
> What exactly is all of this for?  If you want to return the matches 
> sorted, a simple
> matches.sort()
> before returning will do just fine, no?  Maybe I'm just tired now, but 
> the list2dict contortions seem unnecessary to me.
> Besides, I think readline sorts itself always, since I always see the 
> proposed completions come out sorted.  Could you clarify exactly what 
> this is doing? As far as I can tell, all of it is completely unnecessary.
>> 188a198
>> 192a203,208
>>>    try:
>>>        ret=ret+klass._prop_map_get_.keys()
>>>        ret=ret+klass._prop_map_put_.keys()
>>>        pass
>>>    except AttributeError:
>>>        pass
> This could be acceptable, I imagine, for the benefit of win32 users.  
> But not in this form: all Win-specific code should be isolated at 
> definition time, I have no intention of making Unix users pay at 
> runtime for windows-only stuff.  So you'd need to write instead 
> something like:
> def get_class_members():
>     --- current code ---
> if on_windows:
>   # redefine with win-specific hacks
>   def get_class_members():
>       --- your windows code ---
> or something similar.  Be mindful of the details about cygwin vs 
> non-cygwin environments when writing windows-specific code, please.  
> Also make sure you test it very well, since I can't test it myself.
> Best,
> f

More information about the IPython-dev mailing list