@@ -35,11 +35,38 @@ def __repr__(self):
35
35
36
36
37
37
class Globals :
38
+ """
39
+ A dictionary wrapper used for :attr:`puzzlepiece.puzzle.Puzzle.globals`. It behaves like
40
+ a dictionary, allowing :class:`puzzlepiece.piece.Piece` objects to share device APIs
41
+ with each other.
42
+
43
+ Additionally, :func:`~puzzlepiece.puzzle.Globals.require` and
44
+ :func:`~puzzlepiece.puzzle.Globals.release` can be used to keep track of the Pieces
45
+ using a given variable, so that the API can be loaded once and then unloaded once
46
+ all the Pieces are done with it.
47
+ """
38
48
def __init__ (self ):
39
49
self ._dict = {}
40
50
self ._counts = {}
41
51
42
52
def require (self , name ):
53
+ """
54
+ Register that a Piece is using the variable with a given name. This will increase
55
+ an internal counter to indicate the Piece having a hold on the variable.
56
+
57
+ Returns `False` if this is the first time a variable is being registered (and thus
58
+ setup is needed) or `True` if the variable has been registered already.
59
+
60
+ For example, this can be used within :func:`~puzzlepiece.piece.Piece.setup`::
61
+
62
+ def setup(self):
63
+ if not self.puzzle.globals.require('sdk'):
64
+ # Load the SDK if not done already by a different Piece
65
+ self.puzzle.globals['sdk'] = self.load_sdk()
66
+
67
+ :param name: a dictionary key for the required variable
68
+ :rtype: bool
69
+ """
43
70
if name not in self ._dict :
44
71
self ._dict [name ] = None
45
72
self ._counts [name ] = 1
@@ -49,6 +76,25 @@ def require(self, name):
49
76
return True
50
77
51
78
def release (self , name ):
79
+ """
80
+ Indicate that a Piece is done using the variable with a given name.
81
+ This will decrease an internal counter to indicate the Piece is releasing
82
+ its hold on the variable.
83
+
84
+ Returns `False` if the counter is non-zero (so different Pieces are still using
85
+ this variable) or `True` if all Pieces are done with the variable (in that case
86
+ the SDK can be safely shut down for example).
87
+
88
+ For example, this can be used within :func:`~puzzlepiece.piece.Piece.handle_close`::
89
+
90
+ def handle_close(self):
91
+ if self.puzzle.globals.release('sdk'):
92
+ # Unload the SDK if all Pieces are done with it
93
+ self.puzzle.globals['sdk'].stop()
94
+
95
+ :param name: a dictionary key for the variable being released
96
+ :rtype: bool
97
+ """
52
98
if name not in self ._dict :
53
99
raise KeyError (f"No global variable with id '{ name } ' to release" )
54
100
if name not in self ._counts :
@@ -408,8 +454,9 @@ def closeEvent(self, event):
408
454
"""
409
455
self ._shutdown_threads .emit ()
410
456
411
- for piece_name in self .pieces :
412
- self .pieces [piece_name ].handle_close (event )
457
+ if not self .debug :
458
+ for piece_name in self .pieces :
459
+ self .pieces [piece_name ].handle_close (event )
413
460
super ().closeEvent (event )
414
461
415
462
0 commit comments