Skip to content

Instantly share code, notes, and snippets.

@p--q
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save p--q/a45198b8be4e9ae20105 to your computer and use it in GitHub Desktop.
Save p--q/a45198b8be4e9ae20105 to your computer and use it in GitHub Desktop.
def libreoffice52():
# obj = XSCRIPTCONTEXT.getDocument() # 調査対象のオブジェクトを取得。old-styleサービスの例。LibreOfficeドキュメントを開いておく必要がある。
# obj = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getContainerWindow().getToolkit() # 調査対象のオブジェクトを取得。new-styleサービスの例。
obj = XSCRIPTCONTEXT.getComponentContext() # 調査対象のオブジェクトを取得。サービスがないオブジェクトの例。
ObjInsp(obj).get_dic()
class ObjInsp:
def __init__(self, obj):
self.s_dic = dict() # サービス辞書。key:子サービス名、value:親サービスのタプル。以下辞書のvalueは全てXTypeDescriptionオブジェクトのタプル。
self.sa_dic = dict() # サービス属性辞書。key:サービス名、value:サービスの属性のタプル。
self.i_dic = dict() # インターフェイス辞書。key:子インターフェイス名または子サービス名、value:親インターフェイスのタプル。
self.im_dic = dict() # メソッド辞書。key:インターフェイス名、value:インターフェイスのメソッドのタプル。
self.s_omi = {'com.sun.star.uno.XInterface', 'com.sun.star.uno.XWeak', 'com.sun.star.lang.XTypeProvider'} # 結果を出力しないインターフェイス名の集合。'com.sun.star.uno.XInterface'は必ず指定が必要。
self.tdm = XSCRIPTCONTEXT.getComponentContext().getByName('/singletons/com.sun.star.reflection.theTypeDescriptionManager') # TypeDescriptionManagerをシングルトンでインスタンス化。
if hasattr(obj, "getSupportedServiceNames"): # hasattr()は属性の有無をチェックするPythonの組み込み関数。
t_ss = obj.getSupportedServiceNames() # サポートしているサービス名のタプルを取得。
if t_ss: # サポートしているサービス名がある場合。
for ss in t_ss: # 各サービス名について親のサービスを得る。
std = self.tdm.getByHierarchicalName(ss) # サービス名からXServiceTypeDescription2インターフェイスをもつオブジェクトを取得。
self.sa_dic_g(std) # サービス属性辞書追加関数。
self.i_dic_g2(std) # サービスからインターフェイス辞書追加関数。
t_std = std.getMandatoryServices()+std.getOptionalServices() # 直に継承しているサービス(親サービス)のタプルを得る。
if t_std: self.s_dic[std.Name] = t_std # 親サービスがあるときサービス辞書に追加。
lst_buf = t_std # バッファリストに親サービスのタプルを代入。有無をみるだけなのでリストに変換しない。
while lst_buf: # バッファリストがある間継続。
lst_buf = list() # バッファリストを初期化。
for std in t_std: # 各親サービスについて。
self.sa_dic_g(std) # サービス属性辞書追加関数。
self.i_dic_g2(std) # サービスからインターフェイス辞書追加関数。
t_std = std.getMandatoryServices()+std.getOptionalServices() # さらなる親サービスを取得。
if t_std: # 親サービスがあるなら。
self.s_dic[std.Name] = t_std # サービス辞書に追加。
lst_buf.extend(t_std) # バッファリストに親サービスのタプルを追加。
t_std = lst_buf # バッファリストから次の階層のサービスのリストを得る。
self.lst_des(t_ss) # サービス名からサービスの末裔を得る関数。
else: # サポートしているサービスがないときはインターフェイス名一覧を得る。
if hasattr(obj, "getTypes"):
lst_si = obj.getTypes()
if lst_si: # サポートしているインターフェイスがあるとき。
s_si = set([i.typeName for i in obj.getTypes()]) # インターフェイス名一覧を集合型に変換。
self.lst_des = s_si.intersection(s_si ^ self.s_omi) # s_omiのインターフェイス名を除いてインターフェイス名(=末裔)をリストで取得。
if self.lst_des: # 残ったインターフェイスのリストがあるとき
lst_itd = list(map(self.tdm.getByHierarchicalName, self.lst_des)) # lst_siの要素のインターフェイス名からXInterfaceTypeDescription2インターフェイスをもつオブジェクトのリストを取得。
self.i_dic_g(lst_itd)
def sa_dic_g(self, std): # サービス辞書追加関数。
t_sp = std.Properties # サービスからXPropertyTypeDescriptionインターフェイスをもつオブジェクトのタプルを取得。
if t_sp: self.sa_dic[std.Name] = t_sp # サービス属性辞書に追加。
def im_dic_g(self, itd): # メソッド辞書追加関数。
t_im = itd.Members # XInterfaceMemberTypeDescription型のオブジェクトのタプルを取得。メンバーがメソッドならXInterfaceMethodTypeDescriptionインターフェイスをもつ、属性ならXInterfaceAttributeTypeDescription2 インターフェイスをもつ。
if t_im: self.im_dic[itd.Name] = t_im # メソッドがあるならメソッド辞書に追加。 
def lst_des(self, t_ss): # サービス名からサービスの末裔を得る関数。
if self.s_dic: # サービス辞書に項目があるとき。
s_ss = set(t_ss) # サービス名のリストを集合型に変換。
self.lst_des = s_ss.intersection(s_ss ^ set([j.Name for i in self.s_dic.values() for j in i])) # オブジェクトから得たサービスのうち、サービス辞書のvalueにない(親になっていない)サービス名(=末裔)をリストで取得。
else: # サービス辞書に項目がないとき
self.lst_des = t_ss # サポートしているサービス名を末裔とする。
def i_dic_g2(self, std): # サービスからインターフェイス辞書追加関数。
if std.isSingleInterfaceBased(): # new-style(single-interface–based)サービスのとき
lst_itd = [std.getInterface()] # サービスがもつインターフェイスをXInterfaceTypeDescription2インターフェイスをもつオブジェクトでリストにして取得。
else: # old-style(accumulation-based)サービスのとき
lst_itd = [i for i in std.getMandatoryInterfaces() + std.getOptionalInterfaces() if i.Name not in self.s_omi] # s_omiを除いてサービスがもつインターフェイスをXInterfaceTypeDescription2インターフェイスをもつオブジェクトのリストを取得。
if lst_itd: self.i_dic[std.Name] = lst_itd # サービス名をkeyにしてその親インターフェイスのリストを得る。
self.i_dic_g(lst_itd) # インターフェイス辞書追加関数。
def i_dic_g(self, lst_itd): # インターフェイス辞書追加関数。
lst_buf = lst_itd # バッファリストに親インターフェイスのタプルを代入。有無をみるだけなのでリストに変換しない。
while lst_buf: # バッファリストがある間継続。
lst_buf = list() # バッファリストを初期化。
for itd in lst_itd: # 各親インターフェイスについて。
self.im_dic_g(itd) # メソッド辞書追加関数。
lst_itd = [i for i in itd.getBaseTypes()+itd.getOptionalBaseTypes() if i.Name not in self.s_omi] # さらなる親インターフェイスのリストをo_omiを除いて取得。
if lst_itd: # 親インターフェイスがあるなら。
self.i_dic[itd.Name] = lst_itd # インターフェイス辞書に追加。
lst_buf.extend(lst_itd) # バッファリストに親インターフェイスのリストを追加。
lst_itd = lst_buf # バッファリストから次の階層のインターフェイスのリストを得る。
def get_dic(self): # 辞書の内容を出力する
print(self.lst_des) # 最初の階層を出力。
self.lst_des = list(map(self.tdm.getByHierarchicalName, self.lst_des)) # XTypeDescriptionオブジェクトに変換。
dic = self.s_dic # サービス辞書を取得。
if dic: # 辞書があるのなら。
# self.sa_dic_out(self.lst_des) # サービス属性辞書出力関数。
self.i_dic_out(self.lst_des) # インターフェイス辞書出力関数。
lst_buf = True # whileループの継続判定に使うリスト。
lst_val = self.lst_des # whileループ内で展開するリスト。
while lst_buf:
lst_buf = list()
for i in lst_val:
if i.Name in dic:
lst_val = list(dic[i.Name])
lst_val.sort(key=lambda x: x.Name) # リストの要素のオブジェクトのName属性でソートする。
print(i.Name, [j.Name for j in lst_val])
# del dic[i.Name] # 出力したkeyを辞書から削除。
# self.sa_dic_out(lst_val)
self.i_dic_out(lst_val)
lst_buf.extend(lst_val)
lst_val = lst_buf
else:
self.i_dic_out(self.lst_des)
def sa_dic_out(self, lst_val):
dic = self.sa_dic
if dic:
for i in lst_val:
if i.Name in dic:
lst_val = list(dic[i.Name])
lst_val.sort(key=lambda x: x.Name)
print(i.Name, [j.Name for j in lst_val])
# self.im_dic_out(lst_val)
# del dic[i.Name] # 出力したkeyを辞書から削除。'com.sun.star.frame.XModel'が複数でてくるため。
lst_buf = lst_val
while lst_buf:
lst_buf = list()
for i in lst_val:
if i.Name in dic:
lst_val = list(dic[i.Name])
lst_val.sort(key=lambda x: x.Name)
print(i.Name, [j.Name for j in lst_val])
# self.im_dic_out(lst_val)
# del dic[i.Name] # 出力したkeyを辞書から削除。
lst_buf.extend(lst_val)
lst_val = lst_buf
def i_dic_out(self, lst_val):
dic = self.i_dic
if dic:
lst_buf = True
while lst_buf:
lst_buf = list()
for i in lst_val:
if i.Name in dic:
lst_val = list(dic[i.Name])
lst_val.sort(key=lambda x: x.Name)
print(i.Name, [j.Name for j in lst_val])
# self.im_dic_out(lst_val)
# del dic[i.Name] # 出力したkeyを辞書から削除。
lst_buf.extend(lst_val)
lst_val = lst_buf
def im_dic_out(self, lst_val):
dic = self.im_dic
if dic:
for i in lst_val:
if i.Name in dic:
lst_val = list(dic[i.Name])
lst_val.sort(key=lambda x: x.Name)
print(i.Name, [j.MemberName for j in lst_val])
# del dic[i.Name] # 出力したkeyを辞書から削除。
lst_buf = lst_val
while lst_buf:
lst_buf = list()
for i in lst_val:
if i.Name in self.im_dic:
lst_val = list(dic[i.Name])
lst_val.sort(key=lambda x: x.Name)
print(i.Name, [j.MemberName for j in lst_val])
# del dic[i.Name] # 出力したkeyを辞書から削除。
lst_buf.extend(lst_val)
lst_val = lst_buf
if __name__ == "__main__":
import unopy
XSCRIPTCONTEXT = unopy.connect()
if not XSCRIPTCONTEXT:
print("Failed to connect.")
import sys
sys.exit(0)
libreoffice52()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment