- Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgeneral.py
More file actions
Latest commit
109 lines (94 loc) · 3.89 KB
/
Copy pathgeneral.py
File metadata and controls
109 lines (94 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 20 18:44:38 2015
@author: Winand
"""
SOURCEDIR, DEF_MODULE="source", "default"
macro_tree, modules= {}, {}
comobj_cache= {}
fromwin32com.clientimportgencache
importpythoncom, string, sys, datetime, builtins, threading
fromfunctoolsimportwraps
importcontext
importcProfile, pstats, io#Profiling
fromthreaded_uiimportapp
run_lock=threading.Semaphore(2) #for macro interruption
COL= {} #dict of column names
foriinstring.ascii_uppercase:
COL[i] =ord(i)-ord("A")+1
COL["A"+i] =26+ord(i)-ord("A")+1
defprint(*args, **kwargs):
"print with timestamp"
builtins.print(datetime.datetime.now().strftime("%M:%S|"), *args, **kwargs)
defoptional_arguments(f):
"Allows to use any decorator with or w/o arguments \
http://stackoverflow.com/a/14412901/1119602"
@wraps(f)
defnew_dec(*args, **kwargs):
iflen(args) ==1andlen(kwargs) ==0andcallable(args[0]):
returnf(args[0])
else: returnlambdarealf: f(realf, *args, **kwargs)
returnnew_dec
@optional_arguments
defmacro(func, for_=context.Office):
iffunc.__module__.startswith(SOURCEDIR+"."):
module=func.__module__[len(SOURCEDIR+"."):]
else: module=func.__module__
ifmodulenotinmacro_tree:
macro_tree[module] = {}
iffunc.__name__notinmacro_tree[module]: #in case of duplicate macro names
macro_tree[module][func.__name__] =for_
@wraps(func)
defwrapper(doc):
doc_obj=getOpenedFileObject(doc)
ifdoc_obj:
context.context(doc_obj, modules[module])
try:
withrun_lock:
# with Profile():
ret=func()
whilenotrun_lock._value: pass#prevent interruption outside try block
returnret
exceptKeyboardInterrupt:
print("Macro '%s' interrupted"%func.__name__)
exceptExceptionase:
frame=sys.exc_info()[2].tb_next
ifnotframe: frame=sys.exc_info()[2]
print("Exception in macro '%s': %s[%s:%d] %s"%
(func.__name__, type(e).__name__, module, frame.tb_lineno, e))
showConsole() #Show exception to user
finally:
try: context.App.ScreenUpdating=True#Turn back updating!
except: print("Failed to turn on screen updating!")
else: print("Opened document '%s' not found"%doc)
returnwrapper
defgetOpenedFileObject(name):
ifnameincomobj_cache:
try:
#http://stackoverflow.com/questions/3500503/check-com-interface-still-alive
o=comobj_cache[name]
o._oleobj_.GetTypeInfoCount()
returno
except: delcomobj_cache[name]
ctx, rot=pythoncom.CreateBindCtx(0), pythoncom.GetRunningObjectTable()
foriinrot:
ifi.GetDisplayName(ctx, None) ==name:
comobj_cache[name] =gencache.EnsureDispatch(
rot.GetObject(i).QueryInterface(pythoncom.IID_IDispatch))
returncomobj_cache[name]
defgetMacroList(app):
l= [fifm==DEF_MODULEelsem+"."+fforminmacro_treeforfinmacro_tree[m] ifmacro_tree[m][f] in (app, context.Office)]
returnsorted(l, key=lambdas: s.lower())
classProfile():
def__enter__(self):
self.pr=cProfile.Profile()
self.pr.enable()
def__exit__(self, exc_type, exc_value, traceback):
self.pr.disable()
s=io.StringIO()
pstats.Stats(self.pr, stream=s).sort_stats('cumulative').print_stats()
print(s.getvalue())
defshowConsole():
app().form.showWindow(console=True)
context.macro=macro#so macro can be imported from context
context.print=lambda*args, **kwargs: print(">", *args, **kwargs) #macro prints are marked with ">" sign