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
itkdb_gtk/ITkDBlogin.py CHANGED
@@ -92,6 +92,7 @@ class ITkDBlogin(Gtk.Dialog):
92
92
 
93
93
  if gtk_runs:
94
94
  self.create_window()
95
+ self.present()
95
96
  self.run()
96
97
 
97
98
  else:
@@ -216,7 +217,7 @@ class ITkDBlogin(Gtk.Dialog):
216
217
  #
217
218
  self.has_window = True
218
219
  self.add_buttons(
219
- Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK
220
+ Gtk.STOCK_OK, Gtk.ResponseType.OK, Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL
220
221
  )
221
222
  # self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
222
223
 
@@ -238,10 +239,10 @@ class ITkDBlogin(Gtk.Dialog):
238
239
  self.ac1.set_visibility(False)
239
240
  self.ac2.set_visibility(False)
240
241
 
241
- grid.attach(Gtk.Label(label="Acces Code 1"), 0, irow, 1, 1)
242
+ grid.attach(Gtk.Label(label="Access Code 1"), 0, irow, 1, 1)
242
243
  grid.attach(self.ac1, 1, irow, 1, 1)
243
244
  irow = irow + 1
244
- grid.attach(Gtk.Label(label="Acces Code 1"), 0, irow, 1, 1)
245
+ grid.attach(Gtk.Label(label="Access Code 2"), 0, irow, 1, 1)
245
246
  grid.attach(self.ac2, 1, irow, 1, 1)
246
247
 
247
248
  btn = self.get_widget_for_response(Gtk.ResponseType.OK)
@@ -253,7 +254,6 @@ class ITkDBlogin(Gtk.Dialog):
253
254
  """Opens an error dialog.
254
255
 
255
256
  Args:
256
- ----
257
257
  main_title: Main text in window
258
258
  second_text: Second text
259
259
 
@@ -306,12 +306,12 @@ class ITkDBlogin(Gtk.Dialog):
306
306
  # token_file.write(json.dumps(self.token))
307
307
  self.hide()
308
308
 
309
- def get_client(self):
309
+ def get_client(self, use_eos=True):
310
310
  """Return the client."""
311
311
  if not self.is_connected():
312
312
  return None
313
313
 
314
- return itkdb.Client(user=self.user)
314
+ return itkdb.Client(user=self.user, use_eos=use_eos)
315
315
 
316
316
  def __del__(self):
317
317
  """Delete."""
@@ -336,6 +336,10 @@ if __name__ == "__main__":
336
336
  # print(l)
337
337
 
338
338
  print("Hello {}".format(dlg.name))
339
+
340
+ rc = client.get("getUser", json={"userIdentity": dlg.user.identity})
341
+ print(rc)
342
+
339
343
  if gtk_runs:
340
344
  try:
341
345
  while True:
itkdb_gtk/ITkDButils.py CHANGED
@@ -1,22 +1,39 @@
1
1
  """Utilities for the inteaction with the ITkDB."""
2
- import mimetypes
3
2
  from collections.abc import Iterable
4
3
  from datetime import datetime
5
4
  from pathlib import Path
5
+ import getpass
6
6
 
7
7
  import dateutil.parser
8
+ import itkdb
8
9
 
9
10
  # The response of the DB
10
11
  db_response = ""
12
+ attachment_urls = {}
13
+ uploaded_test_runs = []
11
14
 
12
15
 
13
16
  # define an Attachment object.
14
17
  class Attachment(object):
15
18
  """Encapsulates Attachment information."""
16
19
 
17
- def __init__(self, path=None, title=None, desc=None):
20
+ def __init__(self, path=None, url=None, title=None, desc=None):
18
21
  """Initialization."""
19
- self.path = path
22
+ if path is not None:
23
+ self.path = Path(path).expanduser().resolve()
24
+ self.type = "file"
25
+ else:
26
+ self.path = None
27
+
28
+ if url is not None:
29
+ self.url = url
30
+ self.type = "link"
31
+ else:
32
+ self.url = None
33
+
34
+ if self.path and self.url:
35
+ raise ValueError("Invalid Attachment. Has both file and link.")
36
+
20
37
  self.title = title
21
38
  self.desc = desc
22
39
 
@@ -38,7 +55,6 @@ def get_db_response():
38
55
  It is stores in a global variable. Trust the function if call
39
56
  right after your interaction with the DB.
40
57
  """
41
- global db_response
42
58
  return db_response
43
59
 
44
60
 
@@ -46,7 +62,6 @@ def get_db_date(timestamp=None):
46
62
  """Convert a date string into the expected DB format.
47
63
 
48
64
  Args:
49
- ----
50
65
  timestamp: A date in string format
51
66
 
52
67
  """
@@ -67,23 +82,61 @@ def get_db_date(timestamp=None):
67
82
  try:
68
83
  this_date = dateutil.parser.parse(timestamp)
69
84
  out = date2string(this_date)
70
- except Exception:
85
+
86
+ except (OverflowError, dateutil.parser.ParserError):
71
87
  out = ""
72
88
 
73
89
  return out
74
90
 
75
91
 
76
- def registerPetalCore(client, SN, alias, HC_id=None):
92
+
93
+ def get_petal_core_batches(session):
94
+ """Get list of Petal core batches"""
95
+ payload = {
96
+ "filterMap": {
97
+ "project": "S",
98
+ "batchType": ["PETAL_CORE_BATCH_TYPE"],
99
+ }
100
+ }
101
+ batch_list = session.get("listBatches", json=payload)
102
+ rc = {}
103
+ for B in batch_list:
104
+ rc[B["number"] ]= B["id"]
105
+
106
+ return rc
107
+
108
+ def set_petal_core_batch(session, petal_core):
109
+ """Set the batch of the petal core."""
110
+ if isinstance(petal_core["type"], str):
111
+ tp = petal_core["type"]
112
+ else:
113
+ tp = petal_core["type"]["code"]
114
+
115
+ if tp != "CORE_AVS":
116
+ return
117
+
118
+ batch_list = get_petal_core_batches(session)
119
+ aliasID = petal_core["alternativeIdentifier"]
120
+ if "PPB" in aliasID:
121
+ batch_code = "PETAL_CORE_PREPROD"
122
+ elif "PPC" in aliasID:
123
+ batch_code = "PETAL_CORE_PROD"
124
+ else:
125
+ batch_code = "PETAL_CORE_PROTO"
126
+
127
+ rc = session.post("addBatchComponent", json={"id":batch_list[batch_code], "component": petal_core["id"]})
128
+ return rc
129
+
130
+
131
+ def registerPetalCore(client, SN, alias, HC_id=None, petal_core=None):
77
132
  """Register a Petal Core in the DB.
78
133
 
79
134
  Args:
80
- ----
81
135
  SN: Serial Number
82
136
  alias: The alias of the Petal
83
137
  HC_id: Comma separated list of HC identifiers.
84
138
 
85
- Returns
86
- -------
139
+ Returns:
87
140
  _type_: _description_
88
141
 
89
142
  """
@@ -95,14 +148,39 @@ def registerPetalCore(client, SN, alias, HC_id=None):
95
148
  "componentType": "CORE_PETAL",
96
149
  "type": "CORE_AVS",
97
150
  "serialNumber": SN,
98
- "properties": {'DESY_ID': alias}
151
+ "properties": {'PRODUCTION_ID': alias}
99
152
  }
100
153
  if HC_id is not None:
101
154
  dto["properties"]["HC_ID"] = HC_id
102
155
 
103
- db_response = client.post('registerComponent', json=dto)
156
+ the_component = None
157
+
104
158
  try:
105
- return db_response['component']
159
+ if petal_core is None:
160
+ db_response = client.post('registerComponent', json=dto)
161
+ petal_core = db_response['component']
162
+
163
+ else:
164
+ # WE set the alternative ID and the HC_ID
165
+ the_component = SN
166
+ if petal_core["alternativeIdentifier"] is None:
167
+ dto = {
168
+ "component": SN,
169
+ "code": "PRODUCTION_ID",
170
+ "value": alias
171
+ }
172
+ db_response = client.post("setComponentProperty", json=dto)
173
+
174
+ if HC_id is not None:
175
+ dto = {
176
+ "component": SN,
177
+ "code": "HC_ID",
178
+ "value": HC_id
179
+ }
180
+ db_response = client.post("setComponentProperty", json=dto)
181
+
182
+ set_petal_core_batch(client, petal_core)
183
+ return petal_core
106
184
 
107
185
  except KeyError:
108
186
  return None
@@ -112,7 +190,6 @@ def create_component_attachment(client, SN, file_path, title=None, description="
112
190
  """Create an attachment to the given component.
113
191
 
114
192
  Args:
115
- ----
116
193
  client: The DB client
117
194
  SN: The SN of the component.
118
195
  file_path: The pat to th efile to be attached.
@@ -124,7 +201,7 @@ def create_component_attachment(client, SN, file_path, title=None, description="
124
201
  global db_response
125
202
  db_response = None
126
203
  path = Path(file_path).expanduser().resolve()
127
- filetype = mimetypes.guess_type(path)
204
+ filetype = itkdb.utils.get_mimetype(path, None)
128
205
  if title is None:
129
206
  title = path.name
130
207
 
@@ -159,14 +236,13 @@ def create_component_attachment(client, SN, file_path, title=None, description="
159
236
  return db_response
160
237
 
161
238
 
162
- def set_component_property(client, SN, property, value):
239
+ def set_component_property(client, SN, the_property, value):
163
240
  """Set the value of an object property.
164
241
 
165
242
  Args:
166
- ----
167
243
  client: The DB client
168
244
  SN: The object SN
169
- property: The property name
245
+ the_property: The property name
170
246
  value: The property value
171
247
 
172
248
  """
@@ -174,7 +250,7 @@ def set_component_property(client, SN, property, value):
174
250
  try:
175
251
  db_response = client.post('setComponentProperty',
176
252
  json={'component': SN,
177
- 'code': property,
253
+ 'code': the_property,
178
254
  'value': value})
179
255
  return db_response
180
256
 
@@ -188,7 +264,6 @@ def assemble_component(client, parent, child):
188
264
  """Assemble child into parent.
189
265
 
190
266
  Args:
191
- ----
192
267
  client: The DB client
193
268
  parent: The parent object or container.
194
269
  child: The child to be assembled.
@@ -206,63 +281,192 @@ def assemble_component(client, parent, child):
206
281
  return None
207
282
 
208
283
 
284
+ def set_object_stage(client, SN, stage):
285
+ """Set stage of object
286
+
287
+ Args:
288
+ client: DB session
289
+ SN: Serial number
290
+ stage: Stage
291
+
292
+ """
293
+ global db_response
294
+ try:
295
+ db_response = client.post("setComponentStage",
296
+ json={"component": SN, "stage": stage})
297
+ return db_response
298
+
299
+ except Exception as e:
300
+ print("Problems changing stage of {} into {}:\n\t{}".format(
301
+ SN, stage, str(e)))
302
+ return None
303
+
304
+
209
305
  def get_DB_component(client, SN):
210
306
  """Get ta component by its serial number."""
211
307
  global db_response
212
- db_response = client.get('getComponent', json={'component': SN})
213
- return db_response
214
308
 
309
+ try:
310
+ db_response = client.get("getComponent", json={"component": SN})
311
+ return db_response
312
+
313
+ except Exception as e:
314
+ db_response = str(e)
315
+
316
+ try:
317
+ out = client.get('getComponent', json={'component': SN, "alternativeIdentifier":True})
318
+ db_response = out
319
+ return out
320
+
321
+ except Exception as e:
322
+ db_response = str(e)
323
+ return None
215
324
 
216
- def upload_test(client, data, attachments=None):
325
+ def upload_test(client, data, attachments=None, check_runNumber=False):
217
326
  """Upload a test to the DB.
218
327
 
219
328
  Args:
220
- ----
221
329
  client: The DB client
222
- data (dict): A distionary with all the elements of thee test.
223
- attachments (Attachments): one or more (in a list) Attachments to the test
330
+ data (dict): A dictionary with all the elements of thee test.
331
+ attachments ([Attachment]): one or more (in a list) Attachment to the test
224
332
 
225
333
  Return:
226
- ------
227
334
  resp: The response of the DB session.
228
335
 
229
336
  """
230
337
  global db_response
338
+ global attachment_urls
339
+ global uploaded_test_runs
340
+
341
+ uploaded_test_runs = []
342
+ attachment_urls = {}
343
+ db_response = None
344
+
345
+ # Check the given run_number. If already existing, give another one which
346
+ # will try to be consecutive.
347
+ if check_runNumber:
348
+ # Get all the runNumbers in this test
349
+ test_list = client.get("listTestRunsByComponent",
350
+ json={
351
+ "filterMap":{
352
+ "serialNumber": data["component"],
353
+ "state": "ready",
354
+ "testType":[data["testType"]]
355
+ }
356
+ }
357
+ )
358
+ runN= {}
359
+ for T in test_list:
360
+ runN[T["runNumber"]] = 1
361
+
362
+ if data["runNumber"] in runN:
363
+ # if the given runNumber is there, try to create a new one.
364
+ #print("runNumber {} already in {} of {}".format(data["runNumber"], data["testType"], data["component"]))
365
+ try:
366
+ irun = int(data["runNumber"])
367
+ for i in range(irun+1, 100):
368
+ newRn = "{}".format(i)
369
+ if newRn not in runN:
370
+ data["runNumber"] = newRn
371
+ break
372
+
373
+ except ValueError:
374
+ for i in range(100):
375
+ newRn = "{}_{}".format(data["runNumber"], i+1)
376
+ if newRn not in runN:
377
+ data["runNumber"] = newRn
378
+ break
379
+
380
+ # Try to upload the test
231
381
  try:
232
382
  db_response = client.post("uploadTestRunResults", json=data)
383
+ testRun = db_response["testRun"]["id"]
384
+ uploaded_test_runs.append(testRun)
385
+
386
+ except Exception as e:
387
+ msg = "Could not upload the test:\n{}".format(str(e))
388
+ return msg
389
+
390
+ try:
391
+ # Handle attachments.
392
+ attachment_urls = {}
233
393
  if attachments is not None:
234
394
  if not isinstance(attachments, Iterable):
235
395
  attachments = (attachments)
236
396
 
237
397
  for att in attachments:
238
- path = Path(att.path).expanduser().resolve()
239
- if not path.exists():
240
- print("File {} does not exist".format(path))
241
- continue
242
-
243
- data = {"testRun": db_response["testRun"]["id"],
398
+ data = {"testRun": testRun,
244
399
  "title": att.title if att.title is not None else path.name,
245
400
  "description": att.desc if att.desc is not None else path.name,
246
- "type": "file",
401
+ "type": att.type,
247
402
  }
248
- filetype = mimetypes.guess_type(path.name)
249
- attachment = {'data': (path.name, open(path.as_posix(), 'rb'), filetype[0])}
403
+ if att.type == "file":
404
+ path = Path(att.path).expanduser().resolve()
405
+ if not path.exists():
406
+ print("File {} does not exist".format(path))
407
+ continue
408
+
409
+ data["url"] = path.as_uri()
410
+ filetype = itkdb.utils.get_mimetype(path.as_posix(), None)
411
+ attachment = {'data': (path.as_posix(), open(path.as_posix(), 'rb'), filetype)}
412
+ else:
413
+ data["url"] = att.url
414
+ filetype = itkdb.utils.get_mimetype(att.url, None)
415
+ attachment = {'data':(att.url, None, "text/x-uri") }
416
+
250
417
  db_response = client.post('createTestRunAttachment',
251
418
  data=data,
252
419
  files=attachment)
420
+ try:
421
+ url = db_response['url'].replace("https://eosatlas.cern.ch","https://cernbox.cern.ch/files/spaces")
422
+ attachment_urls[path.name] = url
423
+
424
+ except KeyError:
425
+ pass
426
+
253
427
 
254
428
  return None
255
429
 
256
430
  except Exception as e:
257
- return(str(e))
431
+ return "Could not upload attachment:\n{}".format(str(e))
432
+
258
433
 
434
+ def set_test_run_parameter(session, test_run, parameter, value):
435
+ """Modify testRun Parameter
259
436
 
260
- def create_shipment(session, sender, recipient, items, name=None, send=False, type="domestic",
261
- attachment=None, comments=None):
437
+ Args:
438
+ session: The ITkDB session
439
+ test_run: ID of test run
440
+ parameter: parameter code
441
+ value: The new value
442
+ """
443
+ global db_response
444
+ try:
445
+ db_response = session.post("setTestRunParameter",
446
+ json={"testRun": test_run, "code": parameter, "value": value})
447
+ return None
448
+
449
+ except Exception as E:
450
+ return (str(E))
451
+
452
+ def create_test_run_comment(session, test_run, comments):
453
+ """Adds a new comment in testRun."""
454
+ global db_response
455
+ if not isinstance(comments, Iterable):
456
+ comments = (comments)
457
+
458
+ try:
459
+ db_response = session.post("createTestRunComment", json={"testRun": test_run, "comments": comments})
460
+ return None
461
+
462
+ except Exception as E:
463
+ return (str(E))
464
+
465
+ def create_shipment(session, sender, recipient, items, name=None, send=False,
466
+ shipment_type="domestic", attachment=None, comments=None):
262
467
  """Create a chipment.
263
468
 
264
469
  Args:
265
- ----
266
470
  session : The itkdb session
267
471
  sender : The sender ID
268
472
  recipient : The recipient ID
@@ -270,7 +474,7 @@ def create_shipment(session, sender, recipient, items, name=None, send=False, ty
270
474
  name: the name of the shipment.
271
475
  send: If true, the status of the shipment is updated to inTransit
272
476
  type (optional): Type of shipment. Defaults to "domestic".
273
- attachment (optional): Attachment object.
477
+ attachment (optional, :class:`Attachment`): :class:`Attachment` object.
274
478
  comments (optional): comments for the shipment
275
479
 
276
480
  """
@@ -278,7 +482,7 @@ def create_shipment(session, sender, recipient, items, name=None, send=False, ty
278
482
  if name is None:
279
483
  name = "From {} to {}".format(sender, recipient)
280
484
 
281
- if type not in ["domestic", "intraContinental", "continental"]:
485
+ if shipment_type not in ["domestic", "intraContinental", "continental"]:
282
486
  db_response = "Wrong shipment type."
283
487
  return None
284
488
 
@@ -297,7 +501,7 @@ def create_shipment(session, sender, recipient, items, name=None, send=False, ty
297
501
  "name": name,
298
502
  "sender": sender,
299
503
  "recipient": recipient,
300
- "type": type,
504
+ "type": shipment_type,
301
505
  "shipmentItems": items,
302
506
  }
303
507
 
@@ -388,16 +592,19 @@ def from_full_test_to_test_data(full_test):
388
592
  for P in full_test["properties"]:
389
593
  test["properties"][P["code"]] = P['value']
390
594
 
391
- for P in full_test["results"]:
392
- test["results"][P["code"]] = P['value']
595
+ if full_test["results"]:
596
+ for P in full_test["results"]:
597
+ test["results"][P["code"]] = P['value']
393
598
 
394
- for C in full_test["comments"]:
395
- test["comments"].append(C["comment"])
599
+ if full_test["comments"]:
600
+ for C in full_test["comments"]:
601
+ test["comments"].append(C["comment"])
396
602
 
397
- for D in full_test["defects"]:
398
- test["defects"].append({"name": D["name"],
399
- "description": D["description"],
400
- "properties": D["properties"]})
603
+ if full_test["defects"]:
604
+ for D in full_test["defects"]:
605
+ test["defects"].append({"name": D["name"],
606
+ "description": D["description"],
607
+ "properties": D["properties"]})
401
608
 
402
609
  return test
403
610
 
@@ -406,7 +613,6 @@ def get_testrun(session, test_id, out_type="object"):
406
613
  """Retrieve information about a given test.
407
614
 
408
615
  Args:
409
- ----
410
616
  session : The itkdb session
411
617
  test_id : The ID of the test.
412
618
  out_type (optional): Type of output (full or object). Defaults to "object".
@@ -421,11 +627,10 @@ def get_testrun(session, test_id, out_type="object"):
421
627
  return None
422
628
 
423
629
 
424
- def get_test_skeleton(session, component, test_code, userdef={}, uservalues={}):
630
+ def get_test_skeleton(session, component, test_code, userdef=None, uservalues=None):
425
631
  """Get the skeleton of the given test.
426
632
 
427
633
  Args:
428
- ----
429
634
  session: The DB session
430
635
  component: The component which is tested
431
636
  test_code: The test code
@@ -434,6 +639,13 @@ def get_test_skeleton(session, component, test_code, userdef={}, uservalues={}):
434
639
 
435
640
  """
436
641
  global db_response
642
+
643
+ if userdef is None:
644
+ userdef = {}
645
+
646
+ if uservalues is None:
647
+ uservalues = {}
648
+
437
649
  defvalues = {
438
650
  "string": "",
439
651
  "integer": -9999,
@@ -479,9 +691,9 @@ def get_test_skeleton(session, component, test_code, userdef={}, uservalues={}):
479
691
  }
480
692
 
481
693
  # Set default values
482
- for key in skltn.keys():
694
+ for key, val in skltn.items():
483
695
  if key in userdef:
484
- if isinstance(skltn[key], dict):
696
+ if isinstance(val, dict):
485
697
  continue
486
698
 
487
699
  skltn[key] = userdef[key]
@@ -494,7 +706,7 @@ def get_test_skeleton(session, component, test_code, userdef={}, uservalues={}):
494
706
  if vtype in uservalues:
495
707
  val = uservalues[vtype]
496
708
  else:
497
- print("default for data type ", vtype, " not found")
709
+ # print("default for data type ", vtype, " not found")
498
710
  val = None
499
711
 
500
712
  else:
@@ -519,3 +731,29 @@ def get_test_skeleton(session, component, test_code, userdef={}, uservalues={}):
519
731
  skltn['results'][key] = get_default(par)
520
732
 
521
733
  return skltn
734
+
735
+ def create_client():
736
+ """Create a Client."""
737
+ client = itkdb.Client()
738
+ client.user._access_code1 = getpass.getpass("Access 1: ")
739
+ client.user._access_code2 = getpass.getpass("Access 2: ")
740
+ client.user.authenticate()
741
+ print("Hello {} !".format(client.user.name))
742
+ return client
743
+
744
+ def get_db_user(client):
745
+ """REturn PDB information of current user.
746
+
747
+ Args:
748
+ client (itkdb.Client): The DB client.
749
+
750
+ """
751
+ global db_response
752
+ if client is None:
753
+ return None
754
+
755
+ try:
756
+ db_response = client.get("getUser", json={"userIdentity": client.user.identity})
757
+ return db_response
758
+ except Exception:
759
+ return None