itkdb-gtk 0.0.12__py3-none-any.whl → 0.0.16__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 itkdb-gtk might be problematic. Click here for more details.

itkdb_gtk/__init__.py CHANGED
@@ -1,16 +1,15 @@
1
- from . import dashBoard
2
-
3
- __version__ = "0.0.12"
1
+ __version__ = "0.0.16"
4
2
 
5
3
 
6
4
  def dash_board():
7
5
  """Launches the dash board."""
6
+ from .dashBoard import main
8
7
  dashBoard.main()
9
8
 
10
9
 
11
10
  def getShipments():
12
11
  """getShipments."""
13
- from .getShipments import main
12
+ from .GetShipments import main
14
13
  main()
15
14
 
16
15
 
@@ -20,25 +19,34 @@ def glueWeight():
20
19
  main()
21
20
 
22
21
 
23
- def gndVITests():
22
+ def groundVITests():
24
23
  """GND/VI tests."""
25
- from .gndVITests import main
24
+ from .GroundVITests import main
26
25
  main()
27
26
 
28
27
 
29
28
  def sendShipments():
30
29
  """Send items."""
31
- from .sendShipments import main
30
+ from .SendShipments import main
32
31
  main()
33
32
 
34
-
35
33
  def uploadTest():
36
- """Upload tests."""
37
- from .uploadTest import main
34
+ """Upload a single tests."""
35
+ from .UploadTest import main
38
36
  main()
39
37
 
40
38
 
41
39
  def uploadMultipleTests():
42
40
  """Upload multiple tests."""
43
- from .uploadMultipleTests import main
41
+ from .UploadMultipleTests import main
42
+ main()
43
+
44
+ def uploadModuleIV():
45
+ """Upload IV files of single and double modules"""
46
+ from .UploadModuleIV import main
47
+ main()
48
+
49
+ def wirebondTest():
50
+ """Inputs data and eventually upload wirebod test."""
51
+ from .WireBondGui import main
44
52
  main()
itkdb_gtk/dashBoard.py CHANGED
@@ -3,16 +3,23 @@
3
3
  import sys
4
4
 
5
5
  try:
6
- import dbGtkUtils
7
- import getShipments
8
- import groundingTest
9
- import ITkDBlogin
10
- import sendShipments
11
- import uploadMultipleTests
12
- import GlueWeight
13
-
14
- except Exception:
15
- from itkdb_gtk import dbGtkUtils, getShipments, groundingTest, ITkDBlogin, sendShipments, uploadMultipleTests, GlueWeight
6
+ import itkdb_gtk
7
+
8
+ except ImportError:
9
+ from pathlib import Path
10
+ cwd = Path(sys.argv[0]).parent.parent
11
+ sys.path.append(cwd.as_posix())
12
+
13
+
14
+ from itkdb_gtk import dbGtkUtils
15
+ from itkdb_gtk import GetShipments
16
+ from itkdb_gtk import GroundVITests
17
+ from itkdb_gtk import ITkDBlogin
18
+ from itkdb_gtk import SendShipments
19
+ from itkdb_gtk import UploadMultipleTests
20
+ from itkdb_gtk import GlueWeight
21
+ from itkdb_gtk import UploadModuleIV
22
+ from itkdb_gtk import WireBondGui
16
23
 
17
24
  import gi
18
25
 
@@ -22,7 +29,14 @@ from gi.repository import Gtk
22
29
 
23
30
  class DashWindow(dbGtkUtils.ITkDBWindow):
24
31
  """Dashboard class."""
25
-
32
+ UPLOAD_TEST = 1
33
+ CREATE_SHIPMNT = 2
34
+ RECV_SHIPMNT = 3
35
+ PETAL_GND = 4
36
+ GLUE_WEIGHT = 5
37
+ MOD_IV = 6
38
+ WIRE_BOND = 7
39
+
26
40
  def __init__(self, session):
27
41
  """Initialization."""
28
42
  super().__init__(title="ITkDB Dashboard", session=session)
@@ -59,6 +73,17 @@ class DashWindow(dbGtkUtils.ITkDBWindow):
59
73
  btnWeight.connect("clicked", self.glue_weight)
60
74
  grid.attach(btnWeight, 0, irow, 1, 1)
61
75
 
76
+ btnModIV = Gtk.Button(label="Module IV")
77
+ btnModIV.connect("clicked", self.module_IV)
78
+ grid.attach(btnModIV, 1, irow, 1, 1)
79
+
80
+ irow +=1
81
+ btnWireBond = Gtk.Button(label="Wire Bond")
82
+ btnWireBond.connect("clicked", self.wire_bond)
83
+ grid.attach(btnWireBond, 0, irow, 1, 1)
84
+
85
+
86
+
62
87
  irow += 1
63
88
  grid.attach(Gtk.Label(), 0, irow, 1, 1)
64
89
 
@@ -83,51 +108,51 @@ class DashWindow(dbGtkUtils.ITkDBWindow):
83
108
 
84
109
  def upload_test(self, *args):
85
110
  """Launch upload test."""
86
- bitn = 1
111
+ bitn = DashWindow.UPLOAD_TEST
87
112
  bt = 1 << bitn
88
113
  if self.mask & bt:
89
114
  return
90
115
 
91
116
  self.mask |= bt
92
- W = uploadMultipleTests.UploadMultipleTests(self.session)
117
+ W = UploadMultipleTests.UploadMultipleTests(self.session)
93
118
  W.connect("destroy", self.app_closed, bitn)
94
119
 
95
120
  def create_shipment(self, *args):
96
121
  """Launch sendShipment."""
97
- bitn = 2
122
+ bitn = DashWindow.CREATE_SHIPMNT
98
123
  bt = 1 << bitn
99
124
  if self.mask & bt:
100
125
  return
101
126
 
102
127
  self.mask |= bt
103
- W = sendShipments.SendShipments(self.session)
128
+ W = SendShipments.SendShipments(self.session)
104
129
  W.connect("destroy", self.app_closed, bitn)
105
130
 
106
131
  def receive_shipment(self, *args):
107
132
  """Launch getShipments."""
108
- bitn = 3
133
+ bitn = DashWindow.RECV_SHIPMNT
109
134
  bt = 1 << bitn
110
135
  if self.mask & bt:
111
136
  return
112
137
 
113
138
  self.mask |= bt
114
- W = getShipments.ReceiveShipments(self.session)
139
+ W = GetShipments.ReceiveShipments(self.session)
115
140
  W.connect("destroy", self.app_closed, bitn)
116
141
 
117
142
  def petal_gnd(self, *args):
118
143
  """Petal GND/VI test."""
119
- bitn = 4
144
+ bitn = DashWindow.PETAL_GND
120
145
  bt = 1 << bitn
121
146
  if self.mask & bt:
122
147
  return
123
148
 
124
149
  self.mask |= bt
125
- W = groundingTest.GroundingTest(self.session)
150
+ W = GroundVITests.GroundingTest(self.session)
126
151
  W.connect("destroy", self.app_closed, bitn)
127
152
 
128
153
  def glue_weight(self, *args):
129
154
  """Glue Weight test."""
130
- bitn = 5
155
+ bitn = DashWindow.GLUE_WEIGHT
131
156
  bt = 1 << bitn
132
157
  if self.mask & bt:
133
158
  return
@@ -136,11 +161,33 @@ class DashWindow(dbGtkUtils.ITkDBWindow):
136
161
  W = GlueWeight.GlueWeight(self.session)
137
162
  W.connect("destroy", self.app_closed, bitn)
138
163
 
164
+ def module_IV(self, *args):
165
+ """Module IV tests."""
166
+ bitn = DashWindow.MOD_IV
167
+ bt = 1 << bitn
168
+ if self.mask & bt:
169
+ return
170
+
171
+ self.mask |= bt
172
+ W = UploadModuleIV.IVwindow(self.session)
173
+ W.connect("destroy", self.app_closed, bitn)
174
+
175
+ def wire_bond(self, *args):
176
+ """Module IV tests."""
177
+ bitn = DashWindow.WIRE_BOND
178
+ bt = 1 << bitn
179
+ if self.mask & bt:
180
+ return
181
+
182
+ self.mask |= bt
183
+ W = WireBondGui.WireBond(session=self.session, title="Wirebond")
184
+ W.connect("destroy", self.app_closed, bitn)
185
+
139
186
  def app_closed(self, *args):
140
187
  """Application window closed. Clear mask."""
141
188
  bt = 1 << args[1]
142
189
  self.mask &= ~bt
143
- print(bt, self.mask)
190
+ # print(bt, self.mask)
144
191
 
145
192
 
146
193
  def main():
itkdb_gtk/dbGtkUtils.py CHANGED
@@ -7,33 +7,72 @@ from datetime import datetime
7
7
 
8
8
  import dateutil.parser
9
9
  import gi
10
+ import numpy as np
11
+
10
12
 
11
13
  gi.require_version("Gtk", "3.0")
12
- from gi.repository import Gtk, Gio, GLib
14
+ from gi.repository import Gtk, GObject, Gio, GLib
13
15
 
16
+ def parse_date(txt):
17
+ """Parse a date."""
18
+ try:
19
+ return dateutil.parser.parse(txt, fuzzy=False)
14
20
 
15
- def set_combo_iter(combo, txt, col=0):
16
- """Set scombo active iter to that containing txt in column col."""
17
- model = combo.get_model()
18
- iter = model.get_iter_first()
19
- while iter:
20
- val = model.get_value(iter, col)
21
- if val == txt:
22
- combo.set_active_iter(iter)
23
- break
21
+ except Exception:
22
+ return None
23
+ def parse_date_as_string(txt):
24
+ """Parse data and return DB compatible string."""
25
+ D = parse_date(txt)
26
+ if D is None:
27
+ return D
24
28
 
25
- iter = model.iter_next(iter)
29
+ out = D.isoformat(timespec='milliseconds')
30
+ if out[-1] not in ['zZ']:
31
+ out += 'Z'
32
+
33
+ return out
34
+
35
+ def is_a_date(txt):
36
+ """check tha the input string is a date."""
37
+ try:
38
+ dateutil.parser.parse(txt, fuzzy=False)
39
+ return True
26
40
 
41
+ except Exception:
42
+ return False
43
+
44
+ def new_small_text_entry():
45
+ """Returs a new, smaller Gtk.Entry."""
46
+ entry = Gtk.Entry()
47
+ provider = Gtk.CssProvider()
48
+ style_context = entry.get_style_context()
49
+ font_size = 2.25*style_context.get_property("font-size", 0)
50
+ css = "entry {{ min-height: {}px; }}".format(font_size)
51
+ provider.load_from_data(css.encode())
52
+ style_context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_SETTINGS)
53
+ return entry
27
54
 
28
55
  def set_entry_style(container):
29
56
  """Set max entry."""
30
57
  provider = Gtk.CssProvider()
31
- print(container.get_name())
32
58
  style_context = container.get_style_context()
33
59
  font_size = 2.25*style_context.get_property("font-size", 0)
34
60
  css = "{} {{ min-height: {}px; }}".format(container.get_name(), font_size)
35
61
  provider.load_from_data(css.encode())
36
62
  style_context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_SETTINGS)
63
+ return container
64
+
65
+ def set_combo_iter(combo, txt, col=0):
66
+ """Set scombo active iter to that containing txt in column col."""
67
+ model = combo.get_model()
68
+ iter = model.get_iter_first()
69
+ while iter:
70
+ val = model.get_value(iter, col)
71
+ if val == txt:
72
+ combo.set_active_iter(iter)
73
+ break
74
+
75
+ iter = model.iter_next(iter)
37
76
 
38
77
 
39
78
  def is_iterable(obj):
@@ -55,6 +94,12 @@ class MyEncoder(json.JSONEncoder):
55
94
  if isinstance(o, datetime):
56
95
  text = o.astimezone().isoformat()
57
96
  return text
97
+ elif isinstance(o, np.integer):
98
+ return int(o)
99
+ elif isinstance(o, np.floating):
100
+ return float(o)
101
+ elif isinstance(o, np.ndarray):
102
+ return o.tolist()
58
103
  else:
59
104
  return super().default(o)
60
105
 
@@ -138,11 +183,16 @@ def ask_for_confirmation(main_title, second_text, parent=None):
138
183
  return (out == Gtk.ResponseType.OK)
139
184
 
140
185
 
141
- class TextEntry(object):
186
+ class TextEntry(GObject.GObject):
142
187
  """Create a Gtk text entry/view object."""
188
+ __gsignals__ = {
189
+ "text_changed": (GObject.SIGNAL_RUN_FIRST, None, (str,))
190
+ }
143
191
 
144
- def __init__(self, n_lines=1):
192
+ def __init__(self, n_lines=1, small=False):
145
193
  """Init."""
194
+ GObject.GObject.__init__(self)
195
+ self.tmp_txt = ""
146
196
  self.nlines = n_lines
147
197
  if self.nlines > 1:
148
198
  self.widget = Gtk.Frame()
@@ -156,9 +206,31 @@ class TextEntry(object):
156
206
  scrolled.add(self.entry)
157
207
 
158
208
  else:
159
- self.widget = Gtk.Entry()
209
+ if small:
210
+ self.widget = new_small_text_entry()
211
+ else:
212
+ self.widget = Gtk.Entry()
213
+
214
+ self.widget.connect("focus-in-event", self.on_enter)
215
+ self.widget.connect("focus-out-event", self.on_leave)
216
+
160
217
  self.entry = self.widget
161
218
 
219
+ def do_my_signal(self, *args):
220
+ """Signal handler."""
221
+ pass
222
+
223
+ def on_enter(self, *args):
224
+ """On enter."""
225
+ self.tmp_txt = self.widget.get_text().strip()
226
+ return False
227
+
228
+ def on_leave(self, *args):
229
+ """On leave."""
230
+ val = self.widget.get_text().strip()
231
+ if val != self.tmp_txt:
232
+ self.emit("text_changed", val)
233
+
162
234
  def get_text(self):
163
235
  """Return the text."""
164
236
  if self.nlines > 1:
@@ -170,6 +242,13 @@ class TextEntry(object):
170
242
  else:
171
243
  return self.entry.get_text()
172
244
 
245
+ def set_text(self, text):
246
+ """Sets text."""
247
+ if self.nlines > 1:
248
+ self.entry.get_buffer().set_text(text)
249
+ else:
250
+ self.entry.set_text(text)
251
+
173
252
 
174
253
  def get_a_value(main_title, second_text=None, is_tv=False, parent=None):
175
254
  """Open a dialog to get a value.
@@ -216,7 +295,7 @@ def get_a_value(main_title, second_text=None, is_tv=False, parent=None):
216
295
  return out
217
296
 
218
297
 
219
- def get_a_list_of_values(main_title, labels, second_text=None, parent=None):
298
+ def get_a_list_of_values(main_title, labels, defaults=None, second_text=None, parent=None):
220
299
  """Get a list of values.
221
300
 
222
301
  Args:
@@ -224,6 +303,7 @@ def get_a_list_of_values(main_title, labels, second_text=None, parent=None):
224
303
  main_title: Main title for window
225
304
  labels: List of labes to get the values. If the label ends with /v
226
305
  then a TextView will be shown instead of a TextEntry.
306
+ defaults (optional): default values-
227
307
  second_text (optional): Second title for window-. Defaults to None.
228
308
 
229
309
  Returns
@@ -252,7 +332,7 @@ def get_a_list_of_values(main_title, labels, second_text=None, parent=None):
252
332
  is_text_view = []
253
333
  vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
254
334
  area.pack_start(vbox, False, True, 0)
255
- for txt in labels:
335
+ for i, txt in enumerate(labels):
256
336
  use_tv = False
257
337
  if txt.endswith("/v"):
258
338
  is_text_view.append(True)
@@ -266,6 +346,11 @@ def get_a_list_of_values(main_title, labels, second_text=None, parent=None):
266
346
  vbox.pack_start(lbl, False, False, 0)
267
347
 
268
348
  entry = TextEntry(3 if use_tv else -1)
349
+ try:
350
+ entry.set_text(defaults[i])
351
+ except Exception:
352
+ pass
353
+
269
354
  vbox.pack_start(entry.widget, False, False, 0)
270
355
  entries.append(entry)
271
356
 
@@ -301,11 +386,70 @@ def add_button_to_container(box, label, tooltip=None, callback=None):
301
386
 
302
387
  box.pack_start(btn, True, False, 0)
303
388
 
389
+ return btn
390
+
391
+
392
+ class MessagePanel(object):
393
+ """Encapsulates a TExtView object to show messages."""
394
+
395
+ def __init__(self, size=100):
396
+ """Initializarion."""
397
+ self.frame = None
398
+ self.text_view = Gtk.TextView()
399
+ self.textbuffer = self.text_view.get_buffer()
400
+
401
+ self.__create_message_panel(size)
402
+
403
+
404
+ def __create_message_panel(self, size):
405
+ """Creates a message panel within a frame.
406
+
407
+ Args:
408
+ size: size of the panel
409
+
410
+ Returns
411
+ Gtk.TextBuffer, Gtk.Frame
412
+ """
413
+ frame = Gtk.Frame()
414
+ frame.set_shadow_type(Gtk.ShadowType.IN)
415
+
416
+ box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
417
+ box.set_size_request(-1, size)
418
+ frame.add(box)
419
+
420
+ # The title for the tet view
421
+ box.pack_start(Gtk.Label(label="Messages"), False, True, 0)
422
+
423
+ # A scroll window with the text view
424
+ scrolled = Gtk.ScrolledWindow()
425
+ scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
426
+ scrolled.add(self.text_view)
427
+ box.pack_start(scrolled, True, True, 0)
428
+ self.frame = frame
429
+
430
+ def scroll_to_end(self):
431
+ """Scrolls text view to end."""
432
+ end = self.textbuffer.get_end_iter()
433
+ self.text_view.scroll_to_iter(end, 0, False, 0, 0)
434
+
435
+ def write_message(self, text):
436
+ """Writes text to Text Viewer."""
437
+ nlines = self.textbuffer.get_line_count()
438
+ if nlines > 100:
439
+ start = self.textbuffer.get_iter_at_line(0)
440
+ end = self.textbuffer.get_iter_at_line(75)
441
+ self.textbuffer.delete(start, end)
442
+
443
+ end = self.textbuffer.get_end_iter()
444
+ msg = "[{}] {}".format(time.strftime("%d/%m/%y %T"), text)
445
+ self.textbuffer.insert(end, msg)
446
+ GLib.idle_add(self.scroll_to_end)
447
+
304
448
 
305
449
  class ITkDBWindow(Gtk.Window):
306
450
  """Base class for GUI main windows."""
307
451
 
308
- def __init__(self, title="", session=None, show_search=None, gtk_runs=True):
452
+ def __init__(self, title="", session=None, show_search=None, gtk_runs=True, panel_size=100):
309
453
  """Initialization.
310
454
 
311
455
  Args:
@@ -321,12 +465,13 @@ class ITkDBWindow(Gtk.Window):
321
465
  self.session = session
322
466
  self.inst2code = {}
323
467
  self.code2inst = {}
468
+ self.message_panel = None
324
469
 
325
470
  if gtk_runs:
326
471
  super().__init__(title=title)
327
- self.prepare_window(show_search)
472
+ self.prepare_window(show_search, panel_size)
328
473
 
329
- def prepare_window(self, show_search):
474
+ def prepare_window(self, show_search, panel_size):
330
475
  """Inititalizes GUI."""
331
476
  # Prepare HeaderBar
332
477
  self.hb = Gtk.HeaderBar()
@@ -351,11 +496,13 @@ class ITkDBWindow(Gtk.Window):
351
496
 
352
497
  # Create main content box
353
498
  self.mainBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
499
+ self.mainBox.set_property("margin-left", 6)
500
+ self.mainBox.set_property("margin-right", 6)
501
+
354
502
  self.add(self.mainBox)
355
503
 
356
504
  # The text view and buffer
357
- self.text_view = Gtk.TextView()
358
- self.textbuffer = self.text_view.get_buffer()
505
+ self.message_panel = MessagePanel(size=panel_size)
359
506
 
360
507
  # The button box
361
508
  btnBox = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL)
@@ -378,7 +525,8 @@ class ITkDBWindow(Gtk.Window):
378
525
  def new_login(self, obj, msg):
379
526
  """A new user logged in."""
380
527
  if msg == "<OK>":
381
- self.session = self.session.user_gui.get_client()
528
+ if hasattr(self.session, "user_gui"):
529
+ self.session = self.session.user_gui.get_client()
382
530
  self.userLabel.get_child().set_text(self.session.user.name)
383
531
 
384
532
  else:
@@ -450,29 +598,15 @@ class ITkDBWindow(Gtk.Window):
450
598
 
451
599
  return frame
452
600
 
453
- def scroll_to_end(self):
454
- """Scrolls text view to end."""
455
- end = self.textbuffer.get_end_iter()
456
- self.text_view.scroll_to_iter(end, 0, False, 0, 0)
457
-
458
601
  def write_message(self, text):
459
602
  """Writes text to Text Viewer."""
460
- nlines = self.textbuffer.get_line_count()
461
- if nlines > 100:
462
- start = self.textbuffer.get_iter_at_line(0)
463
- end = self.textbuffer.get_iter_at_line(75)
464
- self.textbuffer.delete(start, end)
465
-
466
- end = self.textbuffer.get_end_iter()
467
- msg = "[{}] {}".format(time.strftime("%d/%m/%y %T"), text)
468
- self.textbuffer.insert(end, msg)
469
- GLib.idle_add(self.scroll_to_end)
603
+ self.message_panel.write_message(text)
470
604
 
471
605
 
472
606
  class DictDialog(Gtk.Grid):
473
607
  """Creates a dialog to show and edit variables in a JSon dict."""
474
608
 
475
- def __init__(self, values, hidden_keys={}):
609
+ def __init__(self, values, hidden_keys=None):
476
610
  """Create the Gtk.Grid.
477
611
 
478
612
  Args:
@@ -484,12 +618,18 @@ class DictDialog(Gtk.Grid):
484
618
  super().__init__(column_spacing=5, row_spacing=1)
485
619
 
486
620
  self.set_border_width(10)
621
+ self.factory = deepcopy(values)
487
622
  self.values = deepcopy(values)
488
623
  self.keys = {}
489
624
  self.containers = {}
490
- self.hidden_keys = hidden_keys
625
+ self.hidden_keys = hidden_keys if hidden_keys else {}
491
626
  self.show_values()
492
627
 
628
+ def factory_reset(self):
629
+ """Set values to original values."""
630
+ self.values = deepcopy(self.factory)
631
+ self.refresh()
632
+
493
633
  def on_enter(self, entry, *args):
494
634
  """Get the value when we first enter into the Entry."""
495
635
  self.keys[args[2]] = entry.get_text()
@@ -519,6 +659,15 @@ class DictDialog(Gtk.Grid):
519
659
  elif isinstance(itm[last_key], datetime):
520
660
  itm[last_key] = dateutil.parser.parse(txt)
521
661
 
662
+ elif is_a_date(itm[last_key]):
663
+ D = dateutil.parser.parse(txt)
664
+ out = D.isoformat(timespec='milliseconds')
665
+ if out[-1] not in ['zZ']:
666
+ out += 'Z'
667
+
668
+ itm[last_key] = out
669
+ self.containers[name].set_text(out)
670
+
522
671
  else:
523
672
  tp = type(itm[last_key])
524
673
  itm[last_key] = tp(txt)
itkdb_gtk/readAVSdata.py CHANGED
@@ -5,10 +5,14 @@ from argparse import ArgumentParser
5
5
  from pathlib import Path
6
6
 
7
7
  try:
8
- import ITkDBlogin
9
- import ITkDButils
10
- except ModuleNotFoundError:
11
- from itkdb_gtk import ITkDBlogin, ITkDButils
8
+ import itkdb_gtk
9
+
10
+ except ImportError:
11
+ from pathlib import Path
12
+ cwd = Path(sys.argv[0]).parent.parent
13
+ sys.path.append(cwd.as_posix())
14
+
15
+ from itkdb_gtk import ITkDBlogin, ITkDButils
12
16
 
13
17
  import dateutil.parser
14
18
  import openpyxl as XL
@@ -13,7 +13,7 @@ SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
13
13
 
14
14
 
15
15
  # Get spreadsheet ID from share link
16
- re_sheet_id = re.compile(r"https://docs.google.com/spreadsheets/d/(?P<ID>\w+)", re.DOTALL)
16
+ re_sheet_id = re.compile(r"https://docs.google.com/spreadsheets/d/(?P<ID>[\w-]+)", re.DOTALL)
17
17
 
18
18
 
19
19
  def get_spreadsheet_service():
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env python3
2
+ """Un trash a trashed component."""
3
+
4
+
5
+ def untrash_component(client, SN, reason="Accidentally trashed"):
6
+ """Un trash given component.
7
+
8
+ Args:
9
+ SN (str): Serial number of component to recover.
10
+ reason (str): message for the DB
11
+ Return:
12
+ dict: PDB response.
13
+
14
+ """
15
+ DTO = {
16
+ 'component': SN,
17
+ 'trashed': False,
18
+ 'reason': reason
19
+ }
20
+
21
+ response = client.post('setComponentTrashed', json=DTO)
22
+ return response
23
+
24
+
25
+ if __name__ == "__main__":
26
+ import sys
27
+ from itkdb_gtk import ITkDBlogin
28
+ dlg = ITkDBlogin.ITkDBlogin()
29
+ client = dlg.get_client()
30
+
31
+ try:
32
+ response = untrash_component(client, sys.argv[1])
33
+
34
+ except Exception as E:
35
+ print(str(E))