1"""configure.py script to get / set some session configurable values; mp.py is
2an alias for this command.
3"""
4
5import sys
6
7import fs
8import mpexceptions
9
10
11template_cmd = (
12"""
13Usage
14
15    &cmd subcommand [args]
16
17Subcommands
18
19    new session [playlist] : Creates a new session, sets it as the active one
20    activate session : activates a session
21    deactivate : no session will be active
22    protect [target]: forbids overwrite of session data
23    status : prints configuration for the active session
24    help [subcommand] : prints help for the given subcommand or topic
25    list : list all sessions associated the current samples_dir
26
27Creates and manages pyglet media_player debug session configurations.
28
29Most commands and subcommands need an environment variable pyglet_mp_samples_dir
30to be set to the directory where the media samples reside.
31
32The configuration stores some values used when other commands are executed.
33
34    samples_dir: directory where the samples reside
35    session: a name to identify a particular session
36    session_dir: directory to store all the session's output files, set to
37                 samples_dir/session
38    permissions to overwrite or not raw data collected or generated reports
39    playlist: subset of samples to play
40
41This command can be called both as 'configure.py' or 'mp.py', they do the same.
42
43"""
44)
45
46template_subcommands = (
47"""
48new
49Usage
50
51    &cmd new session [playlist_file]
52
53Arguments
54
55    session       : a name to identify this particular session
56    playlist_file : file with a list of samples
57
58Creates a new session and a directory to save session outputs.
59
60The configuration is saved to disk and the session is made the active one.
61
62If playlist_file os specified, only the samples in the playlist will be
63considered as targets for a general command.
64
65General commands will use the configuration of the active session to know from
66where to read and write data.
67
68@
69activate
70Usage
71
72    &cmd activate session
73
74Arguments
75
76    session: name of session to activate.
77
78Sets the session as the active one.
79
80General commands will use the configuration of the active session to know from
81where to read and write data.
82
83@
84deactivate
85Usage
86
87    &cmd deactivate
88
89Makes the current session inactive.
90
91No session will be active, so general commands will not modify any session data.
92
93Mostly as a precaution so that a slip in shell history does not overwrite
94anything.
95@
96protect
97Usage
98
99    &cmd protect target
100
101Arguments
102
103target: one of
104
105"raw_data"
106    Forbids general commands to overwrite session's raw data captured.
107    Helps to not mix in the same session results obtained in different conditions.
108
109"reports"
110    Forbids general commands to overwrite session's generated reports.
111    Useful if the reports are manually annotated.
112
113@
114status
115Usage
116
117    &cmd status [session]
118
119Arguments
120
121    session: name of session
122
123Prints the configuration for the active session.
124
125@
126help
127Usage
128
129    &cmd help [subcommand or topic]
130
131Subcommands
132
133    new session [playlist] : Creates a new session, sets it as the active one
134    activate session : activates a session
135    deactivate : no session will be active
136    protect [target]: forbids overwrite of session data
137    status : prints configuration for the active session
138    help [subcommand] : prints help for the given subcommand or topic
139    list : list all sessions associated the current samples_dir
140
141Topics
142
143    layout  : data layout on disk
144    session : sessions what and whys
145    workflow: common workflows
146    gencmds : general commands
147@
148list
149Usage
150
151    &cmd list
152
153List all sessions associated with the current sample_dir
154
155
156"""
157)
158
159
160def sub_and_template_from_section(s):
161    subcommand, template = s[1:].split("\n", 1)
162    return subcommand, template
163
164
165def help_texts_from_template(cmd):
166    cmd_help = template_cmd.replace("&cmd", cmd)
167
168    all_subcommands = template_subcommands.replace("&cmd", cmd)
169    parts = all_subcommands.split("@")
170    pairs = [sub_and_template_from_section(s) for s in parts]
171    subcommands_help = {a: b for a, b in pairs}
172
173    return cmd_help, subcommands_help
174
175
176def test_help_strings():
177    cmd_help, subcommands_help = help_texts_from_template('mp')
178    print(cmd_help)
179    for e in subcommands_help:
180        print("sub:", repr(e))
181        print("|%s|" % subcommands_help[e])
182
183
184def show_configuration(keys_to_show=None):
185    pathserv = fs.get_path_info_for_active_session()
186    conf = fs.json_load(pathserv.configuration_filename())
187    if keys_to_show is None:
188        keys_to_show = conf.keys()
189    print("session:", pathserv.session)
190    for k in sorted(keys_to_show):
191        print("\t%s: %s" % (k, conf[k]))
192
193
194def sub_activate():
195    if len(sys.argv) < 3:
196        print("*** Error, missing argument.\n")
197        print(subcommands_help["activate"])
198        return 1
199    session = sys.argv[2]
200    fs.activation_set_to(session)
201    return 0
202
203
204def sub_deactivate():
205    session = None
206    fs.activation_set_to(session)
207    return 0
208
209
210def sub_help():
211    if len(sys.argv) < 3:
212        topic = "help"
213    else:
214        topic = sys.argv[2]
215    print(subcommands_help[topic])
216    return 0
217
218
219def sub_list():
220    samples_dir = fs.get_current_samples_dir()
221    sessions = fs.get_sessions(samples_dir)
222    for session in sorted(sessions):
223        print(session)
224    return 0
225
226
227def sub_new():
228    if len(sys.argv) < 3:
229        print("*** Error, missing argument.\n")
230        print(subcommands_help["new"])
231        return 1
232
233    session = sys.argv[2]
234    if len(sys.argv) > 3:
235        playlist_file = sys.argv[3]
236    else:
237        playlist_file = None
238    fs.new_session(session, playlist_file)
239    return 0
240
241
242def sub_protect():
243    if len(sys.argv) < 3:
244        print("*** Error, missing argument.\n")
245        print(subcommands_help["protect"])
246        return 1
247
248    name = sys.argv[2]
249    if name not in {"raw_data", "reports"}:
250        print("*** Error, unknown name to protect. name:", name)
251        print(subcommands_help["protect"])
252        return 1
253    modify = {("protect_" + name): True}
254    fs.update_active_configuration(modify)
255    return 0
256
257
258def sub_status():
259    show_configuration()
260    return 0
261
262
263def dispatch_subcommand(caller):
264    global cmd_help, subcommands_help
265    cmd_help, subcommands_help = help_texts_from_template(caller)
266    if len(sys.argv) < 2:
267        sub = "help"
268    else:
269        sub = sys.argv[1]
270    try:
271        returncode = globals()["sub_" + sub]()
272    except KeyError:
273        print("*** Error, unknown subcommand:", sub)
274        returncode = 1
275    except mpexceptions.ExceptionUndefinedSamplesDir:
276        print("The env var 'pyglet_mp_samples_dir' is not defined")
277        returncode = 1
278    except mpexceptions.ExceptionSamplesDirDoesNotExist as ex:
279        print("The env var 'pyglet_mp_samples_dir' does not point to an existing directory")
280        returncode = 1
281    except mpexceptions.ExceptionNoSessionIsActive:
282        print("*** Error, no session is active.")
283        returncode = 1
284    except mpexceptions.ExceptionNoSessionWithThatName:
285        print("*** Error, no session by that name")
286        returncode = 1
287    except mpexceptions.ExceptionSessionExistWithSameName:
288        print("*** Error, session exists")
289        returncode = 1
290    except mpexceptions.ExceptionPlaylistFileDoNotExists:
291        print("*** Error, playlist_file does not exist")
292        returncode = 1
293    except mpexceptions.ExceptionBadSampleInPlaylist as ex:
294        print("*** Error, bad sample(s) name in playlist (bad extension or non-existent):")
295        for sample in ex.rejected:
296            print("\t%s" % sample)
297        returncode = 1
298
299    sys.exit(returncode)
300
301if __name__ == "__main__":
302    dispatch_subcommand("configure.py")
303