itkdb-gtk 0.0.3__py3-none-any.whl → 0.20.1__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.
Files changed (37) hide show
  1. itkdb_gtk/{sendShipments.py → CreateShipments.py} +74 -78
  2. itkdb_gtk/{getShipments.py → GetShipments.py} +99 -106
  3. itkdb_gtk/GlueWeight.py +45 -66
  4. itkdb_gtk/ITkDB.desktop +8 -0
  5. itkdb_gtk/ITkDB.svg +380 -0
  6. itkdb_gtk/ITkDBlogin.py +10 -6
  7. itkdb_gtk/ITkDButils.py +295 -57
  8. itkdb_gtk/PanelVisualInspection.py +590 -0
  9. itkdb_gtk/QRScanner.py +120 -0
  10. itkdb_gtk/SensorUtils.py +492 -0
  11. itkdb_gtk/ShowAttachments.py +267 -0
  12. itkdb_gtk/ShowComments.py +94 -0
  13. itkdb_gtk/ShowDefects.py +103 -0
  14. itkdb_gtk/UploadModuleIV.py +566 -0
  15. itkdb_gtk/UploadMultipleTests.py +746 -0
  16. itkdb_gtk/UploadTest.py +509 -0
  17. itkdb_gtk/VisualInspection.py +297 -0
  18. itkdb_gtk/WireBondGui.py +1304 -0
  19. itkdb_gtk/__init__.py +38 -12
  20. itkdb_gtk/dashBoard.py +292 -33
  21. itkdb_gtk/dbGtkUtils.py +356 -75
  22. itkdb_gtk/findComponent.py +242 -0
  23. itkdb_gtk/findVTRx.py +36 -0
  24. itkdb_gtk/readGoogleSheet.py +1 -2
  25. itkdb_gtk/untrash_component.py +35 -0
  26. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/METADATA +21 -12
  27. itkdb_gtk-0.20.1.dist-info/RECORD +30 -0
  28. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/WHEEL +1 -1
  29. itkdb_gtk-0.20.1.dist-info/entry_points.txt +12 -0
  30. itkdb_gtk/checkComponent.py +0 -131
  31. itkdb_gtk/groundingTest.py +0 -225
  32. itkdb_gtk/readAVSdata.py +0 -565
  33. itkdb_gtk/uploadPetalInformation.py +0 -604
  34. itkdb_gtk/uploadTest.py +0 -384
  35. itkdb_gtk-0.0.3.dist-info/RECORD +0 -19
  36. itkdb_gtk-0.0.3.dist-info/entry_points.txt +0 -7
  37. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,509 @@
1
+ #!/usr/bin/env python3
2
+ """GUI to upload tests."""
3
+ import argparse
4
+ import json
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ try:
9
+ import itkdb_gtk
10
+
11
+ except ImportError:
12
+ cwd = Path(__file__).parent.parent
13
+ sys.path.append(cwd.as_posix())
14
+
15
+ from itkdb_gtk import dbGtkUtils, ITkDBlogin, ITkDButils
16
+ from itkdb_gtk.ShowComments import ShowComments
17
+ from itkdb_gtk.ShowAttachments import ShowAttachments
18
+ from itkdb_gtk.ShowDefects import ShowDefects
19
+
20
+ import gi
21
+ gi.require_version("Gtk", "3.0")
22
+ from gi.repository import Gtk, Gio
23
+
24
+ # Check if Gtk can be open
25
+ gtk_runs, gtk_args = Gtk.init_check()
26
+
27
+
28
+ def create_json_data_editor(data):
29
+ """Create a dialog to show the JSon file."""
30
+ dlg = Gtk.Dialog(title="Test Data")
31
+ dlg.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
32
+ Gtk.STOCK_OK, Gtk.ResponseType.OK)
33
+
34
+ dlg.set_property("height-request", 500)
35
+ box = dlg.get_content_area()
36
+ value = dbGtkUtils.DictDialog(data)
37
+ scrolled = Gtk.ScrolledWindow()
38
+ scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
39
+ scrolled.add(value)
40
+ box.pack_start(scrolled, True, True, 10)
41
+
42
+ dlg.show_all()
43
+ return value, dlg
44
+
45
+
46
+ def check_data(data):
47
+ """Checks validity of JSon data.
48
+
49
+ Args:
50
+ data (): The json data
51
+
52
+ Returns:
53
+ boolean: True if valid, False otherwise.
54
+
55
+ """
56
+ errors = []
57
+ missing = []
58
+ if "component" not in data:
59
+ errors.append("Need reference to component, hex string")
60
+ missing.append("component")
61
+
62
+ if "testType" not in data:
63
+ errors.append("Need to know test type, short code")
64
+ missing.append("testType")
65
+
66
+ if "institution" not in data:
67
+ errors.append("Need to know institution, short code")
68
+ missing.append("institution")
69
+
70
+ if "results" not in data:
71
+ errors.append("Need some test results")
72
+ missing.append("results")
73
+
74
+ return errors, missing
75
+
76
+
77
+ class UploadTest(dbGtkUtils.ITkDBWindow):
78
+ """Collects information to upload a test and its attachments."""
79
+
80
+ def __init__(self, session, payload=None, attachment=None, help_link=None):
81
+ """Initialization.
82
+
83
+ Args:
84
+ session: ITkDB session
85
+ payload: path of test file
86
+ attachment: an Attachment object or list of attachments.
87
+
88
+ """
89
+ self.payload = payload
90
+ self.data = None
91
+ self.folder = None
92
+ self.attachments = []
93
+ self.comments = []
94
+ self.defects = []
95
+ self.currentStage = None
96
+ if attachment is not None:
97
+ if isinstance(attachment, ITkDButils.Attachment):
98
+ if attachment.path is not None:
99
+ self.attachments.append(attachment)
100
+ else:
101
+ try:
102
+ for att in attachment:
103
+ self.attachments.append(att)
104
+
105
+ except TypeError:
106
+ print("Wrong attachment: {}".format(attachment))
107
+
108
+ global gtk_runs
109
+ if gtk_runs:
110
+ super().__init__(session=session, title="Upload Test", gtk_runs=gtk_runs, help_link=help_link)
111
+ self.init_window()
112
+
113
+ def init_window(self):
114
+ """Creates the Gtk window."""
115
+ # Initial tweaks
116
+ self.set_border_width(10)
117
+
118
+ # Prepare HeaderBar
119
+ self.hb.props.title = "Upload Tests"
120
+
121
+ # Active button in header
122
+ button = Gtk.Button()
123
+ icon = Gio.ThemedIcon(name="document-send-symbolic")
124
+ image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
125
+ button.add(image)
126
+ button.set_tooltip_text("Click to upload test")
127
+ button.connect("clicked", self.upload_test_gui)
128
+ self.hb.pack_end(button)
129
+
130
+ # Data panel
131
+ grid = Gtk.Grid(column_spacing=5, row_spacing=1)
132
+ self.mainBox.pack_start(grid, True, False, 0)
133
+
134
+ # The test file widgets
135
+ lbl = Gtk.Label(label="Test file")
136
+ lbl.set_xalign(0)
137
+ grid.attach(lbl, 0, 0, 1, 1)
138
+
139
+ self.testF = Gtk.FileChooserButton()
140
+ self.testF.set_tooltip_text("Click to select JSon test file.")
141
+
142
+ grid.attach(self.testF, 1, 0, 1, 1)
143
+ self.testF.connect("file-set", self.on_test_file)
144
+
145
+ # This is to show/edit the test file data
146
+ btn = Gtk.Button()
147
+ icon = Gio.ThemedIcon(name="view-paged-symbolic")
148
+ image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
149
+ btn.add(image)
150
+ btn.set_tooltip_text("Click to view/edit test data.")
151
+ btn.connect("clicked", self.show_data)
152
+ grid.attach(btn, 2, 0, 1, 1)
153
+
154
+ # Object Data
155
+ lbl = Gtk.Label(label="Serial Number")
156
+ lbl.set_xalign(0)
157
+ grid.attach(lbl, 0, 1, 1, 1)
158
+
159
+ self.entrySN = Gtk.Entry()
160
+ grid.attach(self.entrySN, 1, 1, 1, 1)
161
+
162
+ # Test type
163
+ lbl = Gtk.Label(label="Test Type")
164
+ lbl.set_xalign(0)
165
+ grid.attach(lbl, 0, 2, 1, 1)
166
+
167
+ self.entryTest = Gtk.Entry()
168
+ grid.attach(self.entryTest, 1, 2, 1, 1)
169
+
170
+ # Object Stage
171
+ lbl = Gtk.Label(label="Object Stage")
172
+ lbl.set_xalign(0)
173
+ grid.attach(lbl, 0, 3, 1, 1)
174
+
175
+ self.objStage = Gtk.ComboBoxText.new()
176
+ self.objStage.connect("changed", self.on_new_stage)
177
+ grid.attach(self.objStage, 1, 3, 1, 1)
178
+
179
+ self.isRetroactive = Gtk.ToggleButton.new_with_label("RetroActive")
180
+ grid.attach(self.isRetroactive, 2, 3, 1, 1)
181
+
182
+
183
+ # The "Add attachment" button.
184
+ box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
185
+ self.mainBox.pack_start(box, False, False, 0)
186
+ self.btn_attch = dbGtkUtils.add_button_to_container(box, "Attachments",
187
+ "Click to edit attachments.",
188
+ self.edit_attachments)
189
+
190
+ self.btn_comments = dbGtkUtils.add_button_to_container(box, "Comments",
191
+ "Click to edit comments.",
192
+ self.edit_comments)
193
+
194
+ self.btn_defects = dbGtkUtils.add_button_to_container(box, "Defects",
195
+ "Click to edit defects.",
196
+ self.edit_defects)
197
+
198
+ dbGtkUtils.add_button_to_container(box, "Upload Test",
199
+ "Click to upload test.",
200
+ self.upload_test_gui)
201
+
202
+ # The text view
203
+ self.mainBox.pack_start(self.message_panel.frame, True, True, 0)
204
+
205
+ self.show_all()
206
+
207
+ if self.payload:
208
+ try:
209
+ the_path = Path(self.payload).expanduser().resolve()
210
+ if the_path.exists():
211
+ ifile = Path(self.payload).expanduser().resolve().as_posix()
212
+ self.testF.set_filename(ifile)
213
+ self.on_test_file(self.testF)
214
+ self.write_message("Loaded {}\n".format(the_path.name))
215
+
216
+ else:
217
+ print("Input file does not exists: {}".format(self.payload))
218
+
219
+ except TypeError:
220
+ self.load_payload(self.payload)
221
+ self.write_message("Loaded memory payload.\n")
222
+ self.testF.set_sensitive(False)
223
+
224
+ if len(self.attachments) > 0:
225
+ self.btn_attch.set_label("Attachments ({})".format(len(self.attachments)))
226
+
227
+ if len(self.comments) > 0:
228
+ self.btn_comments.set_label("Comments ({})".format(len(self.comments)))
229
+
230
+ if len(self.defects) > 0:
231
+ self.btn_defects.set_label("Defects ({})".format(len(self.defects)))
232
+
233
+
234
+ def get_test_institute(self):
235
+ """Select an institue."""
236
+ dlg = Gtk.Dialog(title="Select Institution.", flags=0)
237
+ dlg.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
238
+ Gtk.STOCK_OK, Gtk.ResponseType.OK)
239
+ area = dlg.get_content_area()
240
+ box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
241
+ area.add(box)
242
+
243
+ box.pack_start(Gtk.Label(label="Select an Institute"), False, True, 0)
244
+
245
+ combo = self.create_institute_combo()
246
+ box.pack_start(combo, False, True, 5)
247
+
248
+ dlg.show_all()
249
+ rc = dlg.run()
250
+
251
+ out = None
252
+ if rc == Gtk.ResponseType.OK:
253
+ out = self.get_institute_from_combo(combo)
254
+
255
+ dlg.hide()
256
+ dlg.destroy()
257
+ return out
258
+
259
+ def load_payload(self, data):
260
+ """Payload is given as a dict."""
261
+ self.data = data
262
+ errors, missing = check_data(self.data)
263
+ self.complete_missing(missing, errors)
264
+ self.set_stages()
265
+
266
+ def on_new_stage(self, *args):
267
+ """New stage selected."""
268
+ stg = self.objStage.get_active_text()
269
+ changed = (stg != self.currentStage)
270
+ self.isRetroactive.set_active(changed)
271
+ self.data["isRetroactive"] = changed
272
+ if changed:
273
+ self.data["stage"] = stg
274
+ else:
275
+ if "stage" in self.data:
276
+ del self.data["stage"]
277
+
278
+ def set_stages(self):
279
+ """Prepare the stages combo."""
280
+ # Check the object stage
281
+ SN = self.data["component"]
282
+ try:
283
+ obj = ITkDButils.get_DB_component(self.session, SN)
284
+ self.currentStage = obj["currentStage"]["code"]
285
+
286
+ self.objStage.remove_all()
287
+ indx = 0
288
+ for i, stg in enumerate(obj["stages"]):
289
+ S = stg["code"]
290
+ self.objStage.append_text(S)
291
+ if S == self.currentStage:
292
+ indx = i
293
+
294
+ self.objStage.set_active(indx)
295
+
296
+ except Exception:
297
+ self.write_message("Something went wrong with the stages\n")
298
+
299
+
300
+ def on_test_file(self, fdlg):
301
+ """Test file browser clicked."""
302
+ fnam = fdlg.get_filename()
303
+ self.folder = Path(fnam).parent
304
+
305
+ # The file exists by definition
306
+ try:
307
+ self.data = json.loads(open(fnam, encoding="UTF-8").read())
308
+ errors, missing = check_data(self.data)
309
+ self.complete_missing(missing, errors)
310
+ self.set_stages()
311
+
312
+ except Exception as E:
313
+ self.data = None
314
+ self.write_message("Cannot load file {}\n".format(fnam))
315
+ self.write_message("{}\n".format(str(E)))
316
+
317
+ def complete_missing(self, missing, errors):
318
+ """Completes missing parts."""
319
+ if len(missing):
320
+ self.write_message("Some keys are missing in the JSon file.\n")
321
+ self.write_message("{}\n".format("\n".join(['\t'+line for line in missing])))
322
+
323
+ if "institution" in missing and len(missing) == 1:
324
+ site = self.get_test_institute()
325
+ if site:
326
+ self.data["institution"] = site
327
+ self.write_message("Setting Institution to {}\n".format(self.data["institution"]))
328
+
329
+ else:
330
+ dbGtkUtils.complain("Invalid JSON data\n{}".format('\n'.join(errors)))
331
+
332
+ self.find_attachments()
333
+ self.find_comments()
334
+ self.find_defects()
335
+
336
+ self.entrySN.set_text(self.data["component"] if self.data["component"] else "")
337
+ self.entryTest.set_text(self.data["testType"])
338
+ self.comments = self.data.get("comments", [])
339
+ self.defects = self.data.get("defects", [])
340
+
341
+
342
+ def show_data(self, *args):
343
+ """Show data button clicked."""
344
+ if self.data is None:
345
+ return
346
+
347
+ value, dlg = create_json_data_editor(self.data)
348
+ rc = dlg.run()
349
+ if rc == Gtk.ResponseType.OK:
350
+ self.data = value.values
351
+
352
+ dlg.hide()
353
+ dlg.destroy()
354
+
355
+ def find_attachments(self):
356
+ """Find Attachments in payload."""
357
+ # We used to clean the attachmetns, but this would remove the ones given
358
+ # in the contructor.
359
+ # self.attachments = []
360
+ if "attachments" in self.data:
361
+ for A in self.data["attachments"]:
362
+ if not Path(A["path"]).exists():
363
+ if self.folder:
364
+ the_path = self.folder.joinpath(A["path"])
365
+ else:
366
+ continue
367
+ else:
368
+ the_path = Path(A["path"]).expanduser().resolve()
369
+
370
+ self.attachments.append(ITkDButils.Attachment(path=the_path, title=A["title"], desc=A["description"]))
371
+
372
+ if len(self.attachments) > 0:
373
+ self.btn_attch.set_label("Attachments ({})".format(len(self.attachments)))
374
+
375
+ def edit_attachments(self, *args):
376
+ """Edit test attachmetns."""
377
+ SA = ShowAttachments("Test Attachments", self.session, self.attachments, parent=self)
378
+ response = SA.run()
379
+ if response == Gtk.ResponseType.OK:
380
+ self.attachments = SA.attachments
381
+
382
+ SA.hide()
383
+ SA.destroy()
384
+
385
+ if len(self.attachments) > 0:
386
+ self.btn_attch.set_label("Attachments ({})".format(len(self.attachments)))
387
+
388
+ def find_comments(self):
389
+ """Find comments in payload"""
390
+ self.comments = []
391
+ if "comments" in self.data:
392
+ for C in self.data["comments"]:
393
+ self.comments.append(C)
394
+
395
+ if len(self.comments) > 0:
396
+ self.btn_comments.set_label("Comments ({})".format(len(self.comments)))
397
+
398
+ def edit_comments(self, *args):
399
+ """Edit test comments."""
400
+ SC = ShowComments("Test Comments", self.comments, self)
401
+ rc = SC.run()
402
+ if rc == Gtk.ResponseType.OK:
403
+ self.comments = SC.comments
404
+
405
+ SC.hide()
406
+ SC.destroy()
407
+
408
+ if len(self.comments) > 0:
409
+ self.btn_comments.set_label("Comments ({})".format(len(self.comments)))
410
+
411
+
412
+ def find_defects(self):
413
+ """Find defects in payload."""
414
+ self.defects = []
415
+ if "defects" in self.data:
416
+ for D in self.data["defects"]:
417
+ self.defects.append(D)
418
+
419
+ if len(self.defects) > 0:
420
+ self.btn_defects.set_label("Defects ({})".format(len(self.defects)))
421
+
422
+ def edit_defects(self, *args):
423
+ """Edit test defects."""
424
+ SD = ShowDefects("Test Defects", self.defects, self)
425
+ rc = SD.run()
426
+ if rc == Gtk.ResponseType.OK:
427
+ self.defects = SD.defects
428
+
429
+ SD.hide()
430
+ SD.destroy()
431
+
432
+ if len(self.defects) > 0:
433
+ self.btn_defects.set_label("Defects ({})".format(len(self.defects)))
434
+
435
+ def upload_test_gui(self, *args):
436
+ """Uploads test and attachments."""
437
+ self.upload_test()
438
+
439
+ def upload_test(self):
440
+ """Uploads test and attachments."""
441
+ if self.data is None:
442
+ self.write_message("No data available to upload\n")
443
+ return
444
+
445
+ self.data["comments"] = self.comments
446
+ self.data["defects"] = self.defects
447
+
448
+ rc = ITkDButils.upload_test(self.session, self.data, self.attachments, check_runNumber=True)
449
+ if rc:
450
+ ipos = rc.find("The following details may help:")
451
+ msg = rc[ipos:]
452
+ dbGtkUtils.complain("Failed uploading test", msg)
453
+
454
+ else:
455
+ self.write_message("Upload successfull\n")
456
+ dbGtkUtils.ask_for_confirmation("Upload successfull", "")
457
+
458
+
459
+ def main():
460
+ """Main entry."""
461
+ HELP_LINK="https://itkdb-gtk.docs.cern.ch/uploadSingleTest.html"
462
+ parser = argparse.ArgumentParser()
463
+
464
+ parser.add_argument("--test-file", help="Name of json file with test data")
465
+ parser.add_argument("--component-id", help="Override component code")
466
+ parser.add_argument("--raw_data", help="Raw data file", default=None)
467
+ parser.add_argument("--attachment", help="Attachment to upload with the test", default=None)
468
+ parser.add_argument("--attach_title", default=None, type=str, help="The attachment description")
469
+ parser.add_argument("--attach_desc", default="", type=str, help="The attachment description")
470
+ parser.add_argument("--verbose", action="store_true", help="Print what's being sent and received")
471
+
472
+ args = parser.parse_args()
473
+
474
+ # DB login
475
+ dlg = ITkDBlogin.ITkDBlogin()
476
+ client = dlg.get_client()
477
+ if client is None:
478
+ print("Could not connect to DB with provided credentials.")
479
+ dlg.die()
480
+ sys.exit()
481
+
482
+ client.user_gui = dlg
483
+
484
+ # Start GUI
485
+ UpT = UploadTest(client,
486
+ payload=args.test_file,
487
+ help_link=HELP_LINK,
488
+ attachment=ITkDButils.Attachment(path=args.attachment,
489
+ title=args.attach_title,
490
+ desc=args.attach_desc))
491
+
492
+ if gtk_runs:
493
+ UpT.present()
494
+ UpT.connect("destroy", Gtk.main_quit)
495
+ try:
496
+ Gtk.main()
497
+
498
+ except KeyboardInterrupt:
499
+ print("Arrrgggg!!!")
500
+
501
+ else:
502
+ # Think
503
+ pass
504
+
505
+ dlg.die()
506
+
507
+
508
+ if __name__ == "__main__":
509
+ main()