petal-qc 0.0.8__py3-none-any.whl → 0.0.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of petal-qc might be problematic. Click here for more details.

@@ -0,0 +1,758 @@
1
+ #!/usr/bin/env python3
2
+ """Uploads data from AVS pdf."""
3
+ import json
4
+ import sys
5
+ from argparse import ArgumentParser
6
+ from datetime import datetime, timezone
7
+ from pathlib import Path
8
+ import dateutil.parser
9
+ import gi
10
+
11
+ gi.require_version("Gtk", "3.0")
12
+ from gi.repository import Gtk, Gio
13
+
14
+ try:
15
+ import itkdb_gtk
16
+
17
+ except ImportError:
18
+ cwd = Path(__file__).parent.parent
19
+ sys.path.append(cwd.as_posix())
20
+
21
+ from itkdb_gtk import ITkDBlogin, ITkDButils, dbGtkUtils
22
+ from petal_qc.metrology import readAVSdata
23
+
24
+ __HELP_LINK__="https://petal-qc.docs.cern.ch/uploadPetalInformation.html"
25
+
26
+ def create_scrolled_dictdialog(the_dict, hidden=("component", "testType")):
27
+ """Create a DictDialog within a scrolled window.
28
+
29
+ Return:
30
+ ------
31
+ scrolled: the scrolled window
32
+ gM: the DictDialog
33
+
34
+ """
35
+ gM = dbGtkUtils.DictDialog(the_dict, hidden)
36
+ scrolled = Gtk.ScrolledWindow()
37
+ scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
38
+ scrolled.add(gM)
39
+ return scrolled, gM
40
+
41
+
42
+ def get_type(child):
43
+ """Return object type
44
+
45
+ Args:
46
+ child (): object
47
+
48
+ Returns:
49
+ str: object type
50
+
51
+ """
52
+ if child["type"] is not None:
53
+ ctype = child["type"]["code"]
54
+ else:
55
+ ctype = child["componentType"]["code"]
56
+
57
+ return ctype
58
+
59
+
60
+ class AVSPanel(dbGtkUtils.ITkDBWindow):
61
+ """Dialog for interaction with DB."""
62
+
63
+ def __init__(self, session, options):
64
+ """Initialization."""
65
+ super().__init__(session=session, title="Upload AVS Data", show_search="Click to search SN in DB", help_link=__HELP_LINK__)
66
+ self.test_uploaded = {}
67
+ self.test_list = []
68
+ self.test_index = {}
69
+ self.test_panel = {}
70
+ self.test_map = {}
71
+ self.petal_core = None
72
+ self.alias = None
73
+ self.petal_weight = -1
74
+ self.DESY_comp = {}
75
+ # self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
76
+
77
+ #
78
+ # Prepare HeaderBar
79
+ self.hb.props.title = "DB Upload Petal Data"
80
+
81
+ button = Gtk.Button()
82
+ icon = Gio.ThemedIcon(name="document-send-symbolic")
83
+ image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
84
+ button.add(image)
85
+ button.set_tooltip_text("Click to upload test shown in notebook.")
86
+ button.connect("clicked", self.upload_current_test)
87
+ self.hb.pack_end(button)
88
+
89
+ button = Gtk.Button()
90
+ icon = Gio.ThemedIcon(name="emblem-documents-symbolic")
91
+ image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
92
+ button.add(image)
93
+ button.set_tooltip_text("Click to upload AVS files.")
94
+ button.connect("clicked", self.upload_avs_files)
95
+ self.hb.pack_end(button)
96
+
97
+ # PS file entry and search button
98
+ self.btnPSF = Gtk.FileChooserButton()
99
+ self.btnPSF.connect("file-set", self.on_psf_set)
100
+ if options.PS:
101
+ ifile = Path(options.PS).expanduser().resolve().as_posix()
102
+ self.btnPSF.set_filename(ifile)
103
+ self.on_psf_set()
104
+
105
+ # FAT file entry and seach buttin
106
+ self.btnFAT = Gtk.FileChooserButton()
107
+ self.btnFAT.connect("file-set", self.on_fat_set)
108
+ if options.FAT:
109
+ ifile = Path(options.FAT).expanduser().resolve().as_posix()
110
+ self.btnFAT.set_filename(ifile)
111
+
112
+ # The Serial number
113
+ self.SN = Gtk.Entry()
114
+ # self.SN.connect("changed", self.SN_changed)
115
+ if options.SN:
116
+ self.SN.set_text(options.SN)
117
+
118
+ # Put the 3 objects in a Grid
119
+ grid = Gtk.Grid(column_spacing=5, row_spacing=1)
120
+ self.mainBox.pack_start(grid, False, True, 0)
121
+
122
+ self.btn_state = Gtk.Button(label="Undef")
123
+ self.btn_state.set_name("btnState")
124
+ self.btn_state.connect("clicked", self.show_state)
125
+ self.btn_state.set_tooltip_text("If green all good. Click to see commnets and defects.")
126
+
127
+ grid.attach(Gtk.Label(label="Serial No."), 0, 0, 1, 1)
128
+ grid.attach(self.SN, 1, 0, 1, 1)
129
+ grid.attach(self.btn_state, 2, 0, 1, 1)
130
+
131
+
132
+ grid.attach(Gtk.Label(label="Prod. Sheet"), 0, 1, 1, 1)
133
+ grid.attach(self.btnPSF, 1, 1, 1, 1)
134
+
135
+ btn = Gtk.Button(label="Reset")
136
+ btn.connect("clicked", self.on_reset)
137
+ grid.attach(btn, 2, 1, 1, 1)
138
+
139
+ grid.attach(Gtk.Label(label="FAT file"), 0, 2, 1, 1)
140
+ grid.attach(self.btnFAT, 1, 2, 1, 1)
141
+
142
+ # Add a Separator
143
+ self.mainBox.pack_start(Gtk.Separator(orientation=Gtk.Orientation.VERTICAL), False, True, 0)
144
+
145
+ # The notebook
146
+ self.notebook = Gtk.Notebook()
147
+ self.notebook.set_tab_pos(Gtk.PositionType.LEFT)
148
+ self.mainBox.pack_start(self.notebook, True, True, 20)
149
+
150
+ # Create the Notebook pages
151
+ defaults = {
152
+ "institution": "AVS",
153
+ "runNumber": 1,
154
+ }
155
+
156
+ self.manufacture = self.create_test_window(
157
+ ITkDButils.get_test_skeleton(
158
+ self.session, "CORE_PETAL", "MANUFACTURING", defaults),
159
+ "manufacture", "Manufacture")
160
+
161
+ self.weights = self.create_test_window(
162
+ ITkDButils.get_test_skeleton(
163
+ self.session, "CORE_PETAL", "WEIGHING", defaults),
164
+ "weights", "Weights")
165
+
166
+ self.delamination = self.create_test_window(
167
+ ITkDButils.get_test_skeleton(
168
+ self.session, "CORE_PETAL", "DELAMINATION", defaults),
169
+ "delamination", "Delamination")
170
+
171
+ self.grounding = self.create_test_window(
172
+ ITkDButils.get_test_skeleton(
173
+ self.session, "CORE_PETAL", "GROUNDING_CHECK", defaults),
174
+ "grounding", "Grounding")
175
+
176
+ self.metrology = self.create_test_window(
177
+ ITkDButils.get_test_skeleton(
178
+ self.session, "CORE_PETAL", "METROLOGY_AVS", defaults),
179
+ "metrology", "Metrology")
180
+
181
+ self.visual_inspection = self.create_test_window(
182
+ ITkDButils.get_test_skeleton(
183
+ self.session, "CORE_PETAL", "VISUAL_INSPECTION", defaults),
184
+ "visual_inspection", "Visual Inspection")
185
+
186
+ # List componentes
187
+ self.components = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
188
+ self.components.set_border_width(5)
189
+ self.notebook.append_page(self.components, Gtk.Label(label="Components"))
190
+
191
+ # The button box
192
+ btnBox = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL)
193
+
194
+ # btn = Gtk.Button(label="Reload AVS files")
195
+ # btn.connect("clicked", self.read_avs_files)
196
+ # btnBox.add(btn)
197
+
198
+ btn = Gtk.Button(label="Assemble")
199
+ btn.set_tooltip_text("Assemble components in DB")
200
+ btn.connect("clicked", self.on_assembly)
201
+ btnBox.add(btn)
202
+
203
+ btn = Gtk.Button(label="Check Components")
204
+ btn.set_tooltip_text("Check components in DB")
205
+ btn.connect("clicked", self.on_check_components)
206
+ btnBox.add(btn)
207
+
208
+ btn = Gtk.Button(label="Check Tests")
209
+ btn.set_tooltip_text("Check test results")
210
+ btn.connect("clicked", self.on_check_tests)
211
+ btnBox.add(btn)
212
+
213
+ btn = Gtk.Button(label="Upload Tests")
214
+ btn.set_tooltip_text("Upload all tests")
215
+
216
+ btn.connect("clicked", self.on_upload)
217
+ btnBox.add(btn)
218
+
219
+ self.mainBox.pack_start(btnBox, False, True, 0)
220
+ self.connect("destroy", Gtk.main_quit)
221
+
222
+
223
+ # The text view
224
+ self.mainBox.pack_start(self.message_panel.frame, True, True, 5)
225
+
226
+ self.show_all()
227
+
228
+
229
+ def show_state(self, *arg):
230
+ """Shows the status"""
231
+ msg = ""
232
+ for test in self.test_list:
233
+ values = test.values
234
+ ndef = len(values["defects"])
235
+ ncomm = len(values["comments"])
236
+ if ndef==0 and ncomm==0:
237
+ continue
238
+
239
+ msg += "{}\n".format(values["testType"])
240
+ if ndef:
241
+ msg += "Defects\n"
242
+
243
+ for D in values["defects"]:
244
+ msg += "{}: {}\n".format(D["name"], D["description"])
245
+
246
+ if ncomm:
247
+ msg += "Comments\n"
248
+
249
+ for C in values["comments"]:
250
+ msg += "{}\n".format(C)
251
+
252
+ msg += "\n"
253
+
254
+ dialog = Gtk.MessageDialog(
255
+ transient_for=self,
256
+ flags=0,
257
+ message_type=Gtk.MessageType.INFO,
258
+ buttons=Gtk.ButtonsType.OK,
259
+ text="Problems found",
260
+ )
261
+
262
+ dialog.format_secondary_text(msg)
263
+ dialog.run()
264
+ dialog.destroy()
265
+
266
+ def on_reset(self, *args):
267
+ """Reset SN"""
268
+ self.petal_core = None
269
+ self.alias = None
270
+ self.SN.set_text("")
271
+ self.btnPSF.unselect_all()
272
+ self.btnFAT.unselect_all()
273
+
274
+ def create_test_window(self, test_json, test_name, label):
275
+ """Create the dialog for a DB test and add it to the notebook.
276
+
277
+ Args:
278
+ test_json: The JSon-like dict with the values
279
+ test_name: The name of the test for internal indexing
280
+ label: The label for the Notebook
281
+
282
+ Returns:
283
+ The box containing the data.
284
+
285
+ """
286
+ scrolled, gM = create_scrolled_dictdialog(test_json)
287
+ self.test_list.append(gM)
288
+ self.test_index[test_name] = len(self.test_list) - 1
289
+ self.test_map[test_json["testType"]] = test_name
290
+
291
+ box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
292
+ box.set_border_width(5)
293
+ box.pack_end(scrolled, True, True, 0)
294
+ box.dict_dialog = gM
295
+ gM.box = box
296
+ self.test_panel[test_name] = box
297
+ self.notebook.append_page(box, Gtk.Label(label=label))
298
+
299
+ return box
300
+
301
+ def update_scroll_window(self, key, data):
302
+ """Update panel for a given test."""
303
+ scrolled, gM = create_scrolled_dictdialog(data, ("component", "testType"))
304
+ self.test_list[self.test_index[key]] = gM
305
+ dbGtkUtils.replace_in_container(self.test_panel[key], scrolled)
306
+
307
+ def check_register_petal(self, SN):
308
+ """Register petal core in DB.
309
+
310
+ Args:
311
+ SN: The petal Serial Number.
312
+
313
+ """
314
+ if self.petal_core:
315
+ return
316
+
317
+ self.find_petal(SN, silent=True)
318
+ if self.petal_core:
319
+ return
320
+
321
+ dialog = Gtk.MessageDialog(
322
+ transient_for=self,
323
+ flags=0,
324
+ message_type=Gtk.MessageType.INFO,
325
+ text="Register Petal Core\n{}".format(SN)
326
+ )
327
+ dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
328
+ Gtk.STOCK_OK, Gtk.ResponseType.OK)
329
+ dialog.set_border_width(10)
330
+ dialog.format_secondary_text("Enter Petal Core Alias")
331
+ alias = Gtk.Entry(text=self.alias)
332
+ box = dialog.get_content_area()
333
+ box.add(alias)
334
+ dialog.show_all()
335
+ out = dialog.run()
336
+ if out == Gtk.ResponseType.OK:
337
+ petal_alias = alias.get_text().strip()
338
+ if len(petal_alias) == 0:
339
+ petal_alias = self.alias
340
+
341
+ rc = ITkDButils.registerPetalCore(self.session, SN, petal_alias)
342
+ if rc is None:
343
+ dbGtkUtils.complain("Could not Register petal {} ({})".format(SN, petal_alias))
344
+
345
+ dialog.hide()
346
+ dialog.destroy()
347
+
348
+ def get_app_petal_serial_number(self):
349
+ """Get the SN from the text box."""
350
+ txt_SN = self.SN.get_text().strip()
351
+ return txt_SN
352
+
353
+ def check_petal_serial_number(self, SN):
354
+ """Check tha the given SN is consistent."""
355
+ txt_SN = self.get_app_petal_serial_number()
356
+ if txt_SN and len(txt_SN):
357
+ if txt_SN != SN.strip():
358
+ return False
359
+
360
+ else:
361
+ return True
362
+
363
+ else:
364
+ self.check_register_petal(SN)
365
+ self.SN.set_text(SN)
366
+ return True
367
+
368
+ def on_psf_set(self, *args):
369
+ """Production Sheet file selected."""
370
+ PSF = self.btnPSF.get_filename()
371
+ if PSF is None or not Path(PSF).exists():
372
+ dbGtkUtils.complain("Could not find Production File", PSF, parent=self)
373
+ return
374
+
375
+ try:
376
+ manuf_json, weights_json, self.DESY_comp, self.alias = readAVSdata.readProductionSheet(self.session, PSF, "SNnnnn")
377
+ if self.petal_weight > 0:
378
+ weights_json["results"]["WEIGHT_CORE"] = self.petal_weight
379
+
380
+ except readAVSdata.AVSDataException as E:
381
+ dbGtkUtils.complain("Wrong Production Sheet file", str(E))
382
+ self.btnPSF.unselect_all()
383
+ return
384
+
385
+ SN = manuf_json["component"]
386
+ if not self.check_petal_serial_number(SN):
387
+ dbGtkUtils.complain("Inconsistent Serial number found.",
388
+ "Wrong Serial number extracted from the Production Sheet document.\n{}".format(PSF))
389
+ self.btnPSF.unselect_all()
390
+ return
391
+
392
+ scrolled, gM = create_scrolled_dictdialog(manuf_json, ("component", "testType"))
393
+ self.test_list[self.test_index["manufacture"]] = gM
394
+ dbGtkUtils.replace_in_container(self.manufacture, scrolled)
395
+
396
+ scrolled, gM = create_scrolled_dictdialog(weights_json, ("component", "testType"))
397
+ self.test_list[self.test_index["weights"]] = gM
398
+ dbGtkUtils.replace_in_container(self.weights, scrolled)
399
+
400
+ gD = dbGtkUtils.DictDialog(self.DESY_comp)
401
+ dbGtkUtils.replace_in_container(self.components, gD)
402
+
403
+ # Check if we need to assemble the module
404
+ self.check_assembly(self.DESY_comp)
405
+
406
+ self.check_components()
407
+
408
+ def on_fat_set(self, *args):
409
+ """FAT file selected."""
410
+ FAT = self.btnFAT.get_filename()
411
+ if FAT is None or not Path(FAT).exists():
412
+ dbGtkUtils.complain("Could not find FAT File", FAT, parent=self)
413
+
414
+ try:
415
+ SN = self.get_app_petal_serial_number()
416
+ if SN and not SN.startswith("20USEBC"):
417
+ SN = None
418
+
419
+ j_vi, j_del, j_gnd, j_mtr, batch, self.petal_weight = readAVSdata.readFATfile(self.session, FAT, SN)
420
+ self.test_list[self.test_index["weights"]].set_value("results.WEIGHT_CORE", self.petal_weight)
421
+
422
+ except readAVSdata.AVSDataException as E:
423
+ dbGtkUtils.complain("Wrong FAT file", str(E))
424
+ self.btnFAT.unselect_all()
425
+ return
426
+
427
+ SN = j_vi["component"]
428
+ if not self.check_petal_serial_number(SN):
429
+ dbGtkUtils.complain("Inconsistent Serial number found.",
430
+ "Wrong Serial number extracted from the FAT document.\n{}".format(FAT))
431
+ self.btnFAT.unselect_all()
432
+ return
433
+
434
+ self.update_scroll_window("visual_inspection", j_vi)
435
+ self.update_scroll_window("delamination", j_del)
436
+ self.update_scroll_window("grounding", j_gnd)
437
+ self.update_scroll_window("metrology", j_mtr)
438
+
439
+ self.check_tests(True)
440
+
441
+ def read_avs_files(self, widgets):
442
+ """Read AVS files."""
443
+ PSF = self.btnPSF.get_filename()
444
+ if PSF is not None:
445
+ self.on_psf_set(None)
446
+
447
+ FAT = self.btnFAT.get_filename()
448
+ if FAT is not None:
449
+ self.on_fat_set(None)
450
+
451
+ return
452
+
453
+ def find_petal(self, SN, silent=False):
454
+ """Finds petal with given SN."""
455
+ try:
456
+ self.petal_core = ITkDButils.get_DB_component(self.session, SN)
457
+
458
+ except Exception as E:
459
+ if not silent:
460
+ dbGtkUtils.complain("Could not find Petal Core in DB", str(E))
461
+
462
+ self.petal_core = None
463
+ return
464
+
465
+ if self.petal_core is None:
466
+ return
467
+
468
+ try:
469
+ if self.petal_core["type"]["code"] != "CORE_AVS":
470
+ dbGtkUtils.complain("Wrong component type", "This is not an AVS petal core")
471
+
472
+ if self.petal_core["currentStage"]["code"] != "ASSEMBLY":
473
+ dbGtkUtils.complain("Wrong component stage", "Wrong stage: {}".format(self.petal_core["currentStage"]["code"]))
474
+
475
+ self.write_message("{}\n".format(json.dumps(self.petal_core, indent=3)))
476
+
477
+ except KeyError:
478
+ # Petal is not there
479
+ self.petal_core = None
480
+
481
+ def query_db(self, *args):
482
+ """Called when QueryDB button clicked."""
483
+ SN = self.SN.get_text()
484
+ if len(SN) == 0:
485
+ dbGtkUtils.complain("Empty Serial number",
486
+ "You should enter a valid Serial number for the petal core.",
487
+ parent=self)
488
+ self.petal_core = None
489
+ return
490
+
491
+ # if not checkSerialNumber(SN):
492
+ # dbGtkUtils.complain("Wrong Serial number",
493
+ # "You should enter a valid Serial number for the petal core.",
494
+ # parent=self)
495
+ # return
496
+ self.find_petal(SN)
497
+
498
+ if self.btnFAT.get_filename() is None and self.btnPSF.get_filename() is None:
499
+ # update tests from DB
500
+ for test in self.petal_core["tests"]:
501
+ latest = None
502
+ latest_time = datetime(year=1, month=1, day=1, tzinfo=timezone.utc)
503
+ testType = test["code"]
504
+ for T in test["testRuns"]:
505
+ test_date = dateutil.parser.parse(T["cts"])
506
+ if test_date > latest_time:
507
+ latest_time = test_date
508
+ latest = T["id"]
509
+
510
+ dbT = ITkDButils.get_testrun(self.session, latest)
511
+ testDB = ITkDButils.from_full_test_to_test_data(dbT)
512
+ self.update_scroll_window(self.test_map[testType], testDB)
513
+
514
+ def on_check_components(self, *args):
515
+ """Button clicked."""
516
+ self.check_components()
517
+
518
+ def check_components(self):
519
+ """Check that components are in DB."""
520
+ for cmp, cmp_SN in self.DESY_comp.items():
521
+ if not (isinstance(cmp_SN, str) and cmp_SN.startswith("20U")):
522
+ continue
523
+
524
+ out = ITkDButils.get_DB_component(self.session, cmp_SN)
525
+ if out is None:
526
+ self.write_message("{}: not in DB\n".format(cmp))
527
+ else:
528
+ self.write_message("{}: in {}\n".format(cmp, out["currentLocation"]["code"]))
529
+
530
+
531
+ def check_assembly(self, components):
532
+ """Check if we need to assemble components to core."""
533
+ if self.petal_core is None:
534
+ self.query_db()
535
+ if self.petal_core is None:
536
+ return
537
+
538
+ comp_map = {
539
+ "BT_PETAL_FRONT": "FacingFront",
540
+ "BT_PETAL_BACK": "FacingBack",
541
+ "COOLING_LOOP_PETAL": "CoolingLoop",
542
+ "THERMALFOAMSET_PETAL": "AllcompSet"
543
+ }
544
+ final_stage = {
545
+ "BT_PETAL_FRONT": "COMPLETED",
546
+ "BT_PETAL_BACK": "COMPLETED",
547
+ "COOLING_LOOP_PETAL": "CLINCORE",
548
+ "THERMALFOAMSET_PETAL": "IN_CORE"
549
+ }
550
+ missing = []
551
+ for child in self.petal_core["children"]:
552
+ if child["component"] is None:
553
+ if child["type"] is not None:
554
+ ctype = child["type"]["code"]
555
+ else:
556
+ ctype = child["componentType"]["code"]
557
+
558
+ missing.append(ctype)
559
+
560
+ if len(missing) == 0:
561
+ return
562
+
563
+ error_txt = []
564
+ txt = "Click OK to add\n\t{}".format("\n\t".join(missing))
565
+ if dbGtkUtils.ask_for_confirmation("Missing components", txt, parent=self):
566
+ this_petal = self.SN.get_text()
567
+ for cmp in missing:
568
+ SN = components[comp_map[cmp]]
569
+ if SN[0:5] == "20USE":
570
+ rc = ITkDButils.assemble_component(self.session, this_petal, SN)
571
+ if rc is None:
572
+ error_txt.append("Problem assembling {} into Petal\n".format(cmp))
573
+
574
+ # Check for HonneyComb set
575
+ for P in self.petal_core["properties"]:
576
+ if P["code"] == "HC_ID" and P["value"] is None:
577
+ if dbGtkUtils.is_iterable(components["HoneyCombSet"]):
578
+ val = ' '.join(components["HoneyCombSet"])
579
+ else:
580
+ val = str(components["HoneyCombSet"])
581
+ rc = ITkDButils.set_component_property(self.session,
582
+ this_petal,
583
+ "HC_ID",
584
+ val)
585
+ if rc is None:
586
+ error_txt.append("Problems setting HoneyCombSet ID.\n")
587
+
588
+ break
589
+
590
+ # Check the final stage of the assembled objects
591
+ for child in self.petal_core["children"]:
592
+ if child["component"]:
593
+ cSN = child["component"]["serialNumber"]
594
+ ctype = get_type(child)
595
+ cobj = ITkDButils.get_DB_component(self.session, cSN)
596
+ cstage = cobj["currentStage"]['code']
597
+ if cstage != final_stage[ctype]:
598
+ rc = ITkDButils.set_object_stage(self.session, cSN, final_stage[ctype])
599
+ if rc is None:
600
+ print("Could not set final stage of {}".format(cSN))
601
+
602
+ if len(error_txt)>0:
603
+ dbGtkUtils.complain("Assembly of {} could not be completeed:".format(this_petal),
604
+ "\n".join(error_txt))
605
+
606
+ def upload_current_test(self, *args):
607
+ """Called with upload button clcked."""
608
+ SN = self.SN.get_text()
609
+ if len(SN) == 0:
610
+ dbGtkUtils.complain("Petal SN is empty")
611
+ return
612
+
613
+ def find_children(W):
614
+ try:
615
+ for c in W.get_children():
616
+ if "DictDialog" in c.get_name():
617
+ return c
618
+
619
+ else:
620
+ return find_children(c)
621
+
622
+ except Exception:
623
+ return None
624
+
625
+ return None
626
+
627
+ page = self.notebook.get_nth_page(self.notebook.get_current_page())
628
+ dctD = find_children(page)
629
+ if dctD is None:
630
+ return
631
+
632
+ values = dctD.values
633
+ values["component"] = SN
634
+ print(json.dumps(values, indent=2))
635
+ rc = ITkDButils.upload_test(self.session, values)
636
+ if rc is not None:
637
+ dbGtkUtils.complain("Could not upload test", rc)
638
+
639
+ else:
640
+ dbGtkUtils.ask_for_confirmation("Test uploaded.",
641
+ "{} - {}".format(values["component"], values["testType"]))
642
+
643
+ def upload_avs_files(self, *args):
644
+ """Called when upload AVS files clicked."""
645
+ SN = self.SN.get_text()
646
+ if len(SN) == 0:
647
+ dbGtkUtils.complain("Petal SN is empty")
648
+ return
649
+
650
+ def upload_file(file_path, title, desc):
651
+ if file_path is not None:
652
+ if not Path(file_path).exists():
653
+ dbGtkUtils.complain("Could not find {}".format(title))
654
+
655
+ else:
656
+ try:
657
+ ITkDButils.create_component_attachment(self.session, SN, file_path, description=desc)
658
+
659
+ except Exception as e:
660
+ dbGtkUtils.complain("Could not Upload {}".format(desc), str(e))
661
+
662
+ PSF = self.btnPSF.get_filename()
663
+ upload_file(PSF, "Production File", "AVS Production file")
664
+
665
+ FAT = self.btnFAT.get_filename()
666
+ upload_file(FAT, "FAT file", "AVS FAT file")
667
+
668
+ def on_check_tests(self, *args):
669
+ """Button clicked."""
670
+ self.check_tests(True)
671
+
672
+ def check_tests(self, do_write=False):
673
+ """Check whether all tests are find"""
674
+ nbad = 0
675
+ bad = []
676
+ for test in self.test_list:
677
+ values = test.values
678
+ if not values["passed"]:
679
+ nbad +=1
680
+ bad.append(values["testType"])
681
+
682
+ if nbad:
683
+ dbGtkUtils.set_button_color(self.btn_state, "red", "white")
684
+ self.btn_state.set_label("FAILED")
685
+ else:
686
+ dbGtkUtils.set_button_color(self.btn_state, "green", "white")
687
+ self.btn_state.set_label("PASSED")
688
+
689
+ if do_write:
690
+ if nbad:
691
+ self.write_message("Petal Failed:\n")
692
+ for T in bad:
693
+ self.write_message("\t{}\n".format(T))
694
+ else:
695
+ if len(self.test_list)>0:
696
+ self.write_message("All tests are PASSED\n")
697
+
698
+ return nbad
699
+
700
+ def on_assembly(self, widget):
701
+ """Assembly button clicked."""
702
+ self.check_assembly(self.DESY_comp)
703
+
704
+ def on_upload(self, widget):
705
+ """Upload tests to DB."""
706
+ if self.petal_core is None:
707
+ self.query_db()
708
+ if self.petal_core is None:
709
+ return
710
+
711
+ for test in self.test_list:
712
+ values = test.values
713
+ self.write_message("{}\n".format(values["testType"]))
714
+ res = ITkDButils.upload_test(self.session, values, check_runNumber=True)
715
+ if res is not None:
716
+ dbGtkUtils.complain("Could not upload test {}".format(values["testType"]), res)
717
+
718
+
719
+ class AVSOptions:
720
+ def __init__(self):
721
+ self.PS = None
722
+ self.FAT = None
723
+ self.SN = None
724
+
725
+ def main():
726
+ """The main entry."""
727
+ # Parse command line options
728
+ parser = ArgumentParser()
729
+ parser.add_argument('files', nargs='*', help="Input files")
730
+ parser.add_argument("--SN", dest="SN", type=str, default=None,
731
+ help="Module serial number")
732
+ parser.add_argument("--PS", dest="PS", type=str, default=None,
733
+ help="Produc tion Sheet file")
734
+ parser.add_argument("--FAT", dest="FAT", type=str, default=None,
735
+ help="FAT file")
736
+
737
+ options = parser.parse_args()
738
+
739
+ # ITk_PB authentication
740
+ dlg = ITkDBlogin.ITkDBlogin()
741
+ session = dlg.get_client()
742
+
743
+ # Start the Application
744
+ win = AVSPanel(session, options)
745
+ win.show_all()
746
+ win.set_accept_focus(True)
747
+ win.present()
748
+ try:
749
+ Gtk.main()
750
+ except KeyboardInterrupt:
751
+ print("Arrggggg !!!")
752
+
753
+ print("Bye !!")
754
+ dlg.die()
755
+ sys.exit()
756
+
757
+ if __name__ == "__main__":
758
+ main()