1#!/usr/bin/env python
2# coding=utf-8
3
4import click
5import pkg_resources
6import inspect
7
8from bob.extension.scripts.click_helper import (
9 verbosity_option,
10 AliasedGroup,
11)
12
13import logging
14logger = logging.getLogger(__name__)
15
16@click.group(cls=AliasedGroup)
17def config():
18 """Commands for listing, describing and copying configuration resources"""
19 pass
20
21@config.command(
22 epilog="""
23\b
24Examples:
25
26\b
27 1. Lists all configuration resources (type: bob.med.tb.config) installed:
28
29\b
30 $ bob tb config list
31
32
33\b
34 2. Lists all configuration resources and their descriptions (notice this may
35 be slow as it needs to load all modules once):
36
37\b
38 $ bob tb config list -v
39
40"""
41)
42@verbosity_option()
43def list(verbose):
44 """Lists configuration files installed"""
45
46 entry_points = pkg_resources.iter_entry_points("bob.med.tb.config")
47 entry_points = dict([(k.name, k) for k in entry_points])
48
49 # all modules with configuration resources
50 modules = set(
51 k.module_name.rsplit(".", 1)[0] for k in entry_points.values()
52 )
53 keep_modules = []
54 for k in sorted(modules):
55 if k not in keep_modules and \
56 not any(k.startswith(l) for l in keep_modules):
57 keep_modules.append(k)
58 modules = keep_modules
59
60 # sort data entries by originating module
61 entry_points_by_module = {}
62 for k in modules:
63 entry_points_by_module[k] = {}
64 for name, ep in entry_points.items():
65 if ep.module_name.startswith(k):
66 entry_points_by_module[k][name] = ep
67
68 for config_type in sorted(entry_points_by_module):
69
70 # calculates the longest config name so we offset the printing
71 longest_name_length = max(
72 len(k) for k in entry_points_by_module[config_type].keys()
73 )
74
75 # set-up printing options
76 print_string = " %%-%ds %%s" % (longest_name_length,)
77 # 79 - 4 spaces = 75 (see string above)
78 description_leftover = 75 - longest_name_length
79
80 print("module: %s" % (config_type,))
81 for name in sorted(entry_points_by_module[config_type]):
82 ep = entry_points[name]
83
84 if verbose >= 1:
85 module = ep.load()
86 doc = inspect.getdoc(module)
87 if doc is not None:
88 summary = doc.split("\n\n")[0]
89 else:
90 summary = "<DOCSTRING NOT AVAILABLE>"
91 else:
92 summary = ""
93
94 summary = (
95 (summary[: (description_leftover - 3)] + "...")
96 if len(summary) > (description_leftover - 3)
97 else summary
98 )
99
100 print(print_string % (name, summary))
101
102
103@config.command(
104 epilog="""
105\b
106Examples:
107
108\b
109 1. Describes the Montgomery dataset configuration:
110
111\b
112 $ bob tb config describe montgomery
113
114
115\b
116 2. Describes the Montgomery dataset configuration and lists its
117 contents:
118
119\b
120 $ bob tb config describe montgomery -v
121
122"""
123)
124@click.argument(
125 "name", required=True, nargs=-1,
126)
127@verbosity_option()
128def describe(name, verbose):
129 """Describes a specific configuration file"""
130
131 entry_points = pkg_resources.iter_entry_points("bob.med.tb.config")
132 entry_points = dict([(k.name, k) for k in entry_points])
133
134 for k in name:
135 if k not in entry_points:
136 logger.error("Cannot find configuration resource '%s'", k)
137 continue
138 ep = entry_points[k]
139 print("Configuration: %s" % (ep.name,))
140 print("Python Module: %s" % (ep.module_name,))
141 print("")
142 mod = ep.load()
143
144 if verbose >= 1:
145 fname = inspect.getfile(mod)
146 print("Contents:")
147 with open(fname, "r") as f:
148 print(f.read())
149 else: #only output documentation
150 print("Documentation:")
151 print(inspect.getdoc(mod))