@@ -51,8 +51,8 @@ class Event(object):
5151 examining *ok* and do further processing with the *value* it has produced.
5252
5353 Failed events are never silently ignored and will raise an exception upon
54- being processed. If a callback handles an exception, it must set * defused*
55- flag to ``True`` to prevent this.
54+ being processed. If a callback handles an exception, it must set :attr:` defused`
55+ to ``True`` to prevent this.
5656
5757 This class also implements ``__and__()`` (``&``) and ``__or__()`` (``|``).
5858 If you concatenate two events using one of these operators,
@@ -88,13 +88,43 @@ def processed(self):
8888 callbacks have been invoked)."""
8989 return self .callbacks is None
9090
91+ @property
92+ def ok (self ):
93+ """Becomes ``True`` when the event has been triggered successfully.
94+
95+ A "successful" event is one triggered with :meth:`succeed()`.
96+
97+ """
98+ return self ._value is not PENDING and self ._ok
99+
100+ @property
101+ def defused (self ):
102+ """Becomes ``True`` when the failed event's exception is "defused".
103+
104+ When an event fails (i.e. with :meth:`fail()`), the failed event's
105+ `value` is an exception that will be re-raised when the
106+ :class:`~simpy.core.Environment` processes the event (i.e. in
107+ :meth:`~simpy.core.Environment.step()`).
108+
109+ It is also possible for the failed event's exception to be defused by
110+ setting :attr:`defused` to ``True`` from an event callback. Doing so
111+ prevents the event's exception from being re-raised when the event is
112+ processed by the :class:`~simpy.core.Environment`.
113+
114+ """
115+ return not self .ok and hasattr (self , '_defused' )
116+
117+ @defused .setter
118+ def defused (self , value ):
119+ self ._defused = True
120+
91121 @property
92122 def value (self ):
93123 """The value of the event if it is available.
94124
95125 The value is available when the event has been triggered.
96126
97- Raise a :exc:`AttributeError` if the value is not yet available.
127+ Raises :exc:`AttributeError` if the value is not yet available.
98128
99129 """
100130 if self ._value is PENDING :
@@ -109,21 +139,21 @@ def trigger(self, event):
109139 chain reactions.
110140
111141 """
112- self .ok = event .ok
142+ self ._ok = event ._ok
113143 self ._value = event ._value
114144 self .env .schedule (self )
115145
116146 def succeed (self , value = None ):
117147 """Set the event's value, mark it as successful and schedule it for
118148 processing by the environment. Returns the event instance.
119149
120- Raise a :exc:`RuntimeError` if this event has already been triggerd.
150+ Raises :exc:`RuntimeError` if this event has already been triggerd.
121151
122152 """
123153 if self ._value is not PENDING :
124154 raise RuntimeError ('%s has already been triggered' % self )
125155
126- self .ok = True
156+ self ._ok = True
127157 self ._value = value
128158 self .env .schedule (self )
129159 return self
@@ -132,16 +162,16 @@ def fail(self, exception):
132162 """Set *exception* as the events value, mark it as failed and schedule
133163 it for processing by the environment. Returns the event instance.
134164
135- Raise a :exc:`ValueError` if *exception* is not an :exc:`Exception`.
165+ Raises :exc:`ValueError` if *exception* is not an :exc:`Exception`.
136166
137- Raise a :exc:`RuntimeError` if this event has already been triggered.
167+ Raises :exc:`RuntimeError` if this event has already been triggered.
138168
139169 """
140170 if self ._value is not PENDING :
141171 raise RuntimeError ('%s has already been triggered' % self )
142172 if not isinstance (exception , BaseException ):
143173 raise ValueError ('%s is not an exception.' % exception )
144- self .ok = False
174+ self ._ok = False
145175 self ._value = exception
146176 self .env .schedule (self )
147177 return self
@@ -174,7 +204,7 @@ def __init__(self, env, delay, value=None):
174204 self .callbacks = []
175205 self ._value = value
176206 self ._delay = delay
177- self .ok = True
207+ self ._ok = True
178208 env .schedule (self , NORMAL , delay )
179209
180210 def _desc (self ):
@@ -200,7 +230,7 @@ def __init__(self, env, process):
200230 # The initialization events needs to be scheduled as urgent so that it
201231 # will be handled before interrupts. Otherwise a process whose
202232 # generator has not yet been started could be interrupted.
203- self .ok = True
233+ self ._ok = True
204234 env .schedule (self , URGENT )
205235
206236
@@ -217,8 +247,8 @@ def __init__(self, process, cause):
217247 self .env = process .env
218248 self .callbacks = [self ._interrupt ]
219249 self ._value = Interrupt (cause )
220- self .ok = False
221- self .defused = True
250+ self ._ok = False
251+ self ._defused = True
222252
223253 if process ._value is not PENDING :
224254 raise RuntimeError ('%s has terminated and cannot be interrupted.' %
@@ -328,12 +358,12 @@ def _resume(self, event):
328358 while True :
329359 # Get next event from process
330360 try :
331- if event .ok :
361+ if event ._ok :
332362 event = self ._generator .send (event ._value )
333363 else :
334364 # The process has no choice but to handle the failed event
335365 # (or fail itself).
336- event .defused = True
366+ event ._defused = True
337367
338368 # Create an exclusive copy of the exception for this
339369 # process to prevent traceback modifications by other
@@ -347,14 +377,14 @@ def _resume(self, event):
347377 except StopIteration as e :
348378 # Process has terminated.
349379 event = None
350- self .ok = True
380+ self ._ok = True
351381 self ._value = e .args [0 ] if len (e .args ) else None
352382 self .env .schedule (self )
353383 break
354384 except BaseException as e :
355385 # Process has failed.
356386 event = None
357- self .ok = False
387+ self ._ok = False
358388 tb = e .__traceback__ if not PY2 else sys .exc_info ()[2 ]
359389 # Strip the frame of this function from the traceback as it
360390 # does not add any useful information.
@@ -496,7 +526,7 @@ def _populate_value(self, value):
496526
497527 def _build_value (self , event ):
498528 """Build the value of this condition."""
499- if event .ok :
529+ if event ._ok :
500530 self ._value = ConditionValue ()
501531 self ._populate_value (self ._value )
502532
@@ -508,9 +538,9 @@ def _check(self, event):
508538
509539 self ._count += 1
510540
511- if not event .ok :
541+ if not event ._ok :
512542 # Abort if the event has failed.
513- event .defused = True
543+ event ._defused = True
514544 self .fail (event ._value )
515545 elif self ._evaluate (self ._events , self ._count ):
516546 # The condition has been met. The _collect_values callback will
0 commit comments