如何在 IPython 中完成 win32com 代码? [英] How to have win32com code completion in IPython?

查看:36
本文介绍了如何在 IPython 中完成 win32com 代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过

导入 win32com.clientwordapp = win32com.client.gencache.EnsureDispatch('Word.Application')

我可以记录一个 Word Application 对象,例如

长话短说

但是请注意,虽然这确实为方法提供了代码补全,但对于属性却并非如此.可以使用 _prop_map_get_ 属性检查那些.例如,wordapp.Selection.Range.Font._prop_map_get_ 给出了字体的所有可用属性.

如果使用 IPython 不是一个强烈的要求,还要注意 PythonWin shell(位于 pkgspywin32Libsite-packagespythonwinPythonwin.exe 附近)有内置代码对属性和方法的完成支持.

这本身就表明在 IPython 中也可以实现相同的功能.

具体来说,依赖于_prop_map_get_的自动补全逻辑可以在scintilla.view.CScintillaView._AutoComplete中找到.另一方面,IPython 6.2.1 中的代码完成由 core.completer.IPCompleter 处理.添加自定义代码完成器的 API 由 IPython.utils.generics.complete_object,如上面第一个解决方案所示.一个问题是 complete_object 基于 simplegeneric,对于任何给定的类型只能提供一个完成者.幸运的是,makepy 生成的所有类型都将从 win32com.client.DispatchBaseClass 继承.

如果结果证明这是一个问题,你也可以完全绕过 complete_object 并简单地手动修补 IPython,方法是将以下五行添加到 core.completer.Completion.attr_matches代码>:

尝试:ole_props = set(obj._prop_map_get_).union(set(obj._prop_map_put_))单词 += 列表(ole_props)除了属性错误:经过

相反,IPython 基于 __dir__,所以你也可以修补 gencache,这是代码生成最终发生的地方,包括一些喜欢的东西

def __dir__(self):返回列表(设置(self._prop_map_get_).联合(设置(self._prop_map_put_)))

到每个生成的DispatchBaseClass.

Via

import win32com.client
wordapp = win32com.client.gencache.EnsureDispatch('Word.Application')

I can get a Word Application object documented e.g. here. However, ipython's autocompletion is not aware of that API, is there any way to add that?

解决方案

Quick solution

Perhaps the simplest way to achieve code completion in IPython (tested with 6.2.1, see the answer below for a snippet that works with 7.1) and Jupyter is to run the following snippet:

from IPython.utils.generics import complete_object
import win32com.client

@complete_object.when_type(win32com.client.DispatchBaseClass)
def complete_dispatch_base_class(obj, prev_completions):
    try:
        ole_props = set(obj._prop_map_get_).union(set(obj._prop_map_put_))
        return list(ole_props) + prev_completions
    except AttributeError:
        pass

Short story long

With some more details being outlined in this guide, win32com ships with a script, makepy.py for generating Python types corresponding to the type library of a given COM object.

In the case of Word 2016, we would proceed as follows:

C:UsersusernameAppDataLocalContinuumAnaconda3pkgspywin32-221-py36h9c10281_0Libsite-packageswin32comclient>python makepy.py -i "Microsoft Word 16.0 Object Library"

Microsoft Word 16.0 Object Library
 {00020905-0000-0000-C000-000000000046}, lcid=0, major=8, minor=7
 >>> # Use these commands in Python code to auto generate .py support
 >>> from win32com.client import gencache
 >>> gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 7)

The location of makepy.py will of course depend on your Python distribution. The script combrowse.py, available in the same directory, can be used to find the names of available type libraries.

With that in place, win32com.client will automatically make use of the generated types, rather than the raw IPyDispatch, and at this point, auto-completion is available in e.g. IPython or Jupyter, given that the COM object of interest actually publishes its available properties and methods (which is not a requirement).

Now, in your case, by invoking EnsureDispatch instead of Dispatch, the makepy part of the process is performed automatically, so you really should be able to obtain code completion in IPython for the published methods:

Note, though, that while this does give code completion for methods, the same will not be true for properties. It is possible to inspect those using the _prop_map_get_ attribute. For example, wordapp.Selection.Range.Font._prop_map_get_ gives all properties available on fonts.

If using IPython is not a strong requirement, note also that the PythonWin shell (located around pkgspywin32Libsite-packagespythonwinPythonwin.exe) has built-in code completion support for both properties and methods.

This, by itself, suggests that the same is achievable in IPython.

Concretely, the logic for auto-completion, which in turn relies on _prop_map_get_, can be found in scintilla.view.CScintillaView._AutoComplete. On the other hand, code completion in IPython 6.2.1 is handled by core.completer.IPCompleter. The API for adding custom code completers is provided by IPython.utils.generics.complete_object, as illustrated in the first solution above. One gotcha is that with complete_object being based on simplegeneric, only one completer may be provided for any given type. Luckily, all types generated by makepy will inherit from win32com.client.DispatchBaseClass.

If this turns out to ever be an issue, one can also circumvent complete_object entirely and simply manually patch IPython by adding the following five lines to core.completer.Completion.attr_matches:

try:
    ole_props = set(obj._prop_map_get_).union(set(obj._prop_map_put_))
    words += list(ole_props)
except AttributeError:
    pass

Conversely, IPython bases its code-completion on __dir__, so one could also patch gencache, which is where the code generation ultimately happens, to include something to like

def __dir__(self):
    return list(set(self._prop_map_get_).union(set(self._prop_map_put_)))

to each generated DispatchBaseClass.

这篇关于如何在 IPython 中完成 win32com 代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆