|
9 | 9 |
|
10 | 10 | from __future__ import absolute_import, print_function |
11 | 11 |
|
| 12 | +import importlib |
| 13 | +import inspect |
12 | 14 | import os |
13 | 15 | import sys |
14 | 16 | import types |
15 | 17 |
|
| 18 | +import importlib_metadata as metadata |
| 19 | + |
16 | 20 | from IPython.lib import pretty |
17 | 21 | from twisted.spread.jelly import unjellyableRegistry |
18 | 22 | from twisted.spread import pb |
@@ -126,26 +130,29 @@ def run(self): |
126 | 130 | device=self._device, |
127 | 131 | ) |
128 | 132 | if results: |
129 | | - for cls in set(unjellyableRegistry.values()): |
130 | | - if isinstance( |
131 | | - cls, (types.ClassType, types.TypeType) |
132 | | - ) and issubclass(cls, (pb.Copyable, pb.RemoteCopy)): |
133 | | - pretty.for_type(cls, _pp_hide_passwords) |
134 | | - else: |
135 | | - pretty.for_type(cls, _pp_default) |
136 | | - try: |
137 | | - pretty.pprint( |
138 | | - results.config, max_width=self._columns, max_seq_length=0 |
139 | | - ) |
140 | | - except IOError as ex: |
141 | | - if ex.errno != 32: # broken pipe |
142 | | - print(ex, file=sys.stderr) |
143 | | - except KeyboardInterrupt as ex: |
144 | | - print(ex, file=sys.stderr) |
| 133 | + pretty_print_device_config(results.config, self._columns) |
145 | 134 | else: |
146 | 135 | print(err, file=sys.stderr) |
147 | 136 |
|
148 | 137 |
|
| 138 | +def pretty_print_device_config(config, columns): |
| 139 | + _register_zenpack_device_config_classes() |
| 140 | + for item in set(unjellyableRegistry.values()): |
| 141 | + if isinstance(item, (types.ClassType, type)) and issubclass( |
| 142 | + item, (pb.Copyable, pb.RemoteCopy) |
| 143 | + ): |
| 144 | + pretty.for_type(item, _pp_hide_passwords) |
| 145 | + else: |
| 146 | + pretty.for_type(item, _pp_default) |
| 147 | + try: |
| 148 | + pretty.pprint(config, max_width=columns, max_seq_length=0) |
| 149 | + except IOError as ex: |
| 150 | + if ex.errno != 32: # broken pipe |
| 151 | + print(ex, file=sys.stderr) |
| 152 | + except KeyboardInterrupt as ex: |
| 153 | + print(ex, file=sys.stderr) |
| 154 | + |
| 155 | + |
149 | 156 | def _query_cache(store, service, monitor, device): |
150 | 157 | query = DeviceQuery(service=service, monitor=monitor, device=device) |
151 | 158 | results = store.search(query) |
@@ -192,3 +199,34 @@ def _printer(obj, p, cycle, vprint): |
192 | 199 |
|
193 | 200 | def _is_output_redirected(): |
194 | 201 | return os.fstat(0) != os.fstat(1) |
| 202 | + |
| 203 | + |
| 204 | +def _register_zenpack_device_config_classes(): |
| 205 | + """ |
| 206 | + Register all unregistered pb.Copyable and pb.RemoteCopy classes. |
| 207 | + """ |
| 208 | + service_modules = _identify_zenpack_hub_service_modules() |
| 209 | + for name, svcmod in service_modules.iteritems(): |
| 210 | + for clsname, cls in inspect.getmembers(svcmod, inspect.isclass): |
| 211 | + if not issubclass(cls, (pb.Copyable, pb.RemoteCopy)): |
| 212 | + continue |
| 213 | + fullname = "{}.{}".format(name, clsname) |
| 214 | + if fullname not in unjellyableRegistry: |
| 215 | + pb.setUnjellyableForClass(cls, cls) |
| 216 | + |
| 217 | + |
| 218 | +def _identify_zenpack_hub_service_modules(): |
| 219 | + service_modules = {} |
| 220 | + for ep in metadata.entry_points().get("zenoss.zenpacks", ()): |
| 221 | + paths = ( |
| 222 | + p |
| 223 | + for p in metadata.files(ep.name) |
| 224 | + if "/services/" in p.as_posix() |
| 225 | + and p.suffix == ".py" |
| 226 | + and p.stem != "__init__" |
| 227 | + ) |
| 228 | + for path in paths: |
| 229 | + svcmod = "{}.services.{}".format(ep.module, path.stem) |
| 230 | + svcm = importlib.import_module(svcmod) |
| 231 | + service_modules[svcm.__name__] = svcm |
| 232 | + return service_modules |
0 commit comments