##// END OF EJS Templates
registrar: add delayregistrar class to register function in extensions...
FUJIWARA Katsunori -
r27585:60bf90eb default
parent child Browse files
Show More
@@ -1,96 +1,128 b''
1 # registrar.py - utilities to register function for specific purpose
1 # registrar.py - utilities to register function for specific purpose
2 #
2 #
3 # Copyright FUJIWARA Katsunori <foozy@lares.dti.ne.jp> and others
3 # Copyright FUJIWARA Katsunori <foozy@lares.dti.ne.jp> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from . import (
10 from . import (
11 util,
11 util,
12 )
12 )
13
13
14 class funcregistrar(object):
14 class funcregistrar(object):
15 """Base of decorator to register a fuction for specific purpose
15 """Base of decorator to register a fuction for specific purpose
16
16
17 The least derived class can be defined by overriding 'table' and
17 The least derived class can be defined by overriding 'table' and
18 'formatdoc', for example::
18 'formatdoc', for example::
19
19
20 symbols = {}
20 symbols = {}
21 class keyword(funcregistrar):
21 class keyword(funcregistrar):
22 table = symbols
22 table = symbols
23 formatdoc = ":%s: %s"
23 formatdoc = ":%s: %s"
24
24
25 @keyword('bar')
25 @keyword('bar')
26 def barfunc(*args, **kwargs):
26 def barfunc(*args, **kwargs):
27 '''Explanation of bar keyword ....
27 '''Explanation of bar keyword ....
28 '''
28 '''
29 pass
29 pass
30
30
31 In this case:
31 In this case:
32
32
33 - 'barfunc' is registered as 'bar' in 'symbols'
33 - 'barfunc' is registered as 'bar' in 'symbols'
34 - online help uses ":bar: Explanation of bar keyword"
34 - online help uses ":bar: Explanation of bar keyword"
35 """
35 """
36
36
37 def __init__(self, decl):
37 def __init__(self, decl):
38 """'decl' is a name or more descriptive string of a function
38 """'decl' is a name or more descriptive string of a function
39
39
40 Specification of 'decl' depends on registration purpose.
40 Specification of 'decl' depends on registration purpose.
41 """
41 """
42 self.decl = decl
42 self.decl = decl
43
43
44 table = None
44 table = None
45
45
46 def __call__(self, func):
46 def __call__(self, func):
47 """Execute actual registration for specified function
47 """Execute actual registration for specified function
48 """
48 """
49 name = self.getname()
49 name = self.getname()
50
50
51 if func.__doc__ and not util.safehasattr(func, '_origdoc'):
51 if func.__doc__ and not util.safehasattr(func, '_origdoc'):
52 doc = func.__doc__.strip()
52 doc = func.__doc__.strip()
53 func._origdoc = doc
53 func._origdoc = doc
54 if callable(self.formatdoc):
54 if callable(self.formatdoc):
55 func.__doc__ = self.formatdoc(doc)
55 func.__doc__ = self.formatdoc(doc)
56 else:
56 else:
57 # convenient shortcut for simple format
57 # convenient shortcut for simple format
58 func.__doc__ = self.formatdoc % (self.decl, doc)
58 func.__doc__ = self.formatdoc % (self.decl, doc)
59
59
60 self.table[name] = func
60 self.table[name] = func
61 self.extraaction(name, func)
61 self.extraaction(name, func)
62
62
63 return func
63 return func
64
64
65 def getname(self):
65 def getname(self):
66 """Return the name of the registered function from self.decl
66 """Return the name of the registered function from self.decl
67
67
68 Derived class should override this, if it allows more
68 Derived class should override this, if it allows more
69 descriptive 'decl' string than just a name.
69 descriptive 'decl' string than just a name.
70 """
70 """
71 return self.decl
71 return self.decl
72
72
73 def parsefuncdecl(self):
73 def parsefuncdecl(self):
74 """Parse function declaration and return the name of function in it
74 """Parse function declaration and return the name of function in it
75 """
75 """
76 i = self.decl.find('(')
76 i = self.decl.find('(')
77 if i > 0:
77 if i > 0:
78 return self.decl[:i]
78 return self.decl[:i]
79 else:
79 else:
80 return self.decl
80 return self.decl
81
81
82 def formatdoc(self, doc):
82 def formatdoc(self, doc):
83 """Return formatted document of the registered function for help
83 """Return formatted document of the registered function for help
84
84
85 'doc' is '__doc__.strip()' of the registered function.
85 'doc' is '__doc__.strip()' of the registered function.
86
86
87 If this is overridden by non-callable object in derived class,
87 If this is overridden by non-callable object in derived class,
88 such value is treated as "format string" and used to format
88 such value is treated as "format string" and used to format
89 document by 'self.formatdoc % (self.decl, doc)' for convenience.
89 document by 'self.formatdoc % (self.decl, doc)' for convenience.
90 """
90 """
91 raise NotImplementedError()
91 raise NotImplementedError()
92
92
93 def extraaction(self, name, func):
93 def extraaction(self, name, func):
94 """Execute exra action for registered function, if needed
94 """Execute exra action for registered function, if needed
95 """
95 """
96 pass
96 pass
97
98 class delayregistrar(object):
99 """Decorator to delay actual registration until uisetup or so
100
101 For example, the decorator class to delay registration by
102 'keyword' funcregistrar can be defined as below::
103
104 class extkeyword(delayregistrar):
105 registrar = keyword
106 """
107 def __init__(self):
108 self._list = []
109
110 registrar = None
111
112 def __call__(self, *args, **kwargs):
113 """Return the decorator to delay actual registration until setup
114 """
115 assert self.registrar is not None
116 def decorator(func):
117 # invocation of self.registrar() here can detect argument
118 # mismatching immediately
119 self._list.append((func, self.registrar(*args, **kwargs)))
120 return func
121 return decorator
122
123 def setup(self):
124 """Execute actual registration
125 """
126 while self._list:
127 func, decorator = self._list.pop(0)
128 decorator(func)
General Comments 0
You need to be logged in to leave comments. Login now