|
16 | 16 | from __future__ import absolute_import |
17 | 17 |
|
18 | 18 | from contextlib import contextmanager |
| 19 | +from functools import wraps |
19 | 20 |
|
20 | 21 | try: |
21 | 22 | import httplib |
@@ -64,40 +65,63 @@ def __init__(self, uri='http://127.0.0.1:8270', timeout=None): |
64 | 65 | timeout = timestr_to_secs(timeout) |
65 | 66 | self._uri = uri |
66 | 67 | self._client = XmlRpcRemoteClient(uri, timeout) |
| 68 | + self._kw_cache = None |
| 69 | + |
| 70 | + def _cached(info_type=None, default=None): |
| 71 | + def decorator(f): |
| 72 | + @wraps(f) |
| 73 | + def wrapper(self, name=None): |
| 74 | + if self._kw_cache: |
| 75 | + return self._kw_cache.get(info_type, dict()).get(name, default) |
| 76 | + else: |
| 77 | + try: |
| 78 | + return f(self, name) |
| 79 | + except TypeError: |
| 80 | + return default |
| 81 | + return wrapper |
| 82 | + return decorator |
| 83 | + |
| 84 | + def _build_kw_info_cache(self): |
| 85 | + """ |
| 86 | + Single attempt to build the cache using get_library_information interface |
| 87 | + cache structure: |
| 88 | + { "keyword_name" : { 'args':[], 'tags':[], 'doc':"", 'types':[]}, |
| 89 | + "kw2" : {...}, etc. } |
| 90 | + """ |
| 91 | + try: |
| 92 | + self._kw_cache = self._client.get_library_information() |
| 93 | + self._kw_cache['__intro__'] = dict( |
| 94 | + doc=self._client.get_keyword_documentation('__intro__')) |
| 95 | + self._kw_cache['__init__'] = dict( |
| 96 | + doc=self._client.get_keyword_documentation('__init__')) |
| 97 | + except TypeError: |
| 98 | + pass # Best effort failed, fall back to regular loading |
67 | 99 |
|
68 | | - def get_keyword_names(self, attempts=2): |
69 | | - for i in range(attempts): |
70 | | - time.sleep(i) |
71 | | - try: |
72 | | - return self._client.get_keyword_names() |
73 | | - except TypeError as err: |
74 | | - error = err |
75 | | - raise RuntimeError('Connecting remote server at %s failed: %s' |
76 | | - % (self._uri, error)) |
| 100 | + def get_keyword_names(self): |
| 101 | + self._build_kw_info_cache() |
| 102 | + if self._kw_cache: |
| 103 | + return self._kw_cache.keys() |
| 104 | + try: |
| 105 | + return self._client.get_keyword_names() |
| 106 | + except TypeError as error: |
| 107 | + raise RuntimeError('Connecting remote server at %s failed: %s' |
| 108 | + % (self._uri, error)) |
77 | 109 |
|
| 110 | + @_cached('args', default=['*args']) |
78 | 111 | def get_keyword_arguments(self, name): |
79 | | - try: |
80 | | - return self._client.get_keyword_arguments(name) |
81 | | - except TypeError: |
82 | | - return ['*args'] |
| 112 | + return self._client.get_keyword_arguments(name) |
83 | 113 |
|
| 114 | + @_cached('types') |
84 | 115 | def get_keyword_types(self, name): |
85 | | - try: |
86 | | - return self._client.get_keyword_types(name) |
87 | | - except TypeError: |
88 | | - return None |
| 116 | + return self._client.get_keyword_types(name) |
89 | 117 |
|
| 118 | + @_cached('tags') |
90 | 119 | def get_keyword_tags(self, name): |
91 | | - try: |
92 | | - return self._client.get_keyword_tags(name) |
93 | | - except TypeError: |
94 | | - return None |
| 120 | + return self._client.get_keyword_tags(name) |
95 | 121 |
|
| 122 | + @_cached('doc') |
96 | 123 | def get_keyword_documentation(self, name): |
97 | | - try: |
98 | | - return self._client.get_keyword_documentation(name) |
99 | | - except TypeError: |
100 | | - return None |
| 124 | + return self._client.get_keyword_documentation(name) |
101 | 125 |
|
102 | 126 | def run_keyword(self, name, args, kwargs): |
103 | 127 | coercer = ArgumentCoercer() |
@@ -227,6 +251,10 @@ def _server(self): |
227 | 251 | finally: |
228 | 252 | server('close')() |
229 | 253 |
|
| 254 | + def get_library_information(self): |
| 255 | + with self._server as server: |
| 256 | + return server.get_library_information() |
| 257 | + |
230 | 258 | def get_keyword_names(self): |
231 | 259 | with self._server as server: |
232 | 260 | return server.get_keyword_names() |
|
0 commit comments