Repository: cocotb/cocotb

Issue:
Make `Trigger.prime` and `Trigger.unprime` private
Users shouldn't be touching them, only the scheduler. There is currently a warning they shouldn't be used by users, let's just make them private.


Discussion:

Resolving patch:
diff --git a/cocotb/scheduler.py b/cocotb/scheduler.py
--- a/cocotb/scheduler.py
+++ b/cocotb/scheduler.py
@@ -303,12 +303,12 @@ def _check_termination(self):
                 self._write_coro_inst = None
 
             for t in self._trigger2coros:
-                t.unprime()
+                t._unprime()
 
             if self._timer1.primed:
-                self._timer1.unprime()
+                self._timer1._unprime()
 
-            self._timer1.prime(self._test_completed)
+            self._timer1._prime(self._test_completed)
             self._trigger2coros = _py_compat.insertion_ordered_dict()
             self._terminate = False
             self._write_calls = OrderedDict()
@@ -329,7 +329,7 @@ def _test_completed(self, trigger=None):
         with ctx:
             self._mode = Scheduler._MODE_NORMAL
             if trigger is not None:
-                trigger.unprime()
+                trigger._unprime()
 
             # extract the current test, and clear it
             test = self._test
@@ -394,7 +394,7 @@ def _event_loop(self, trigger):
             # When a trigger fires it is unprimed internally
             if _debug:
                 self.log.debug("Trigger fired: %s" % str(trigger))
-            # trigger.unprime()
+            # trigger._unprime()
 
             if self._mode == Scheduler._MODE_TERM:
                 if _debug:
@@ -464,7 +464,7 @@ def _event_loop(self, trigger):
                     )
 
                 # This trigger isn't needed any more
-                trigger.unprime()
+                trigger._unprime()
 
                 for coro in self._scheduling:
                     if coro._outcome is not None:
@@ -539,7 +539,7 @@ def _unschedule(self, coro):
             if coro in self._trigger2coros.setdefault(trigger, []):
                 self._trigger2coros[trigger].remove(coro)
             if not self._trigger2coros[trigger]:
-                trigger.unprime()
+                trigger._unprime()
                 del self._trigger2coros[trigger]
 
         assert self._test is not None
@@ -612,7 +612,7 @@ def _resume_coro_upon(self, coro, trigger):
                 )
 
             try:
-                trigger.prime(self._react)
+                trigger._prime(self._react)
             except Exception as e:
                 # discard the trigger we associated, it will never fire
                 self._trigger2coros.pop(trigger)
@@ -621,7 +621,7 @@ def _resume_coro_upon(self, coro, trigger):
                 self._resume_coro_upon(
                     coro,
                     NullTrigger(
-                        name="Trigger.prime() Error", outcome=outcomes.Error(e)
+                        name="Trigger._prime() Error", outcome=outcomes.Error(e)
                     ),
                 )
 
@@ -994,7 +994,7 @@ def _cleanup(self):
             trigger = self._pending_triggers.pop(0)
             if _debug:
                 self.log.debug("Unpriming %r", trigger)
-            trigger.unprime()
+            trigger._unprime()
         assert not self._pending_triggers
 
         # Kill any queued coroutines.
diff --git a/cocotb/triggers.py b/cocotb/triggers.py
--- a/cocotb/triggers.py
+++ b/cocotb/triggers.py
@@ -87,7 +87,7 @@ def log(self):
         return SimLog("cocotb.%s" % (type(self).__qualname__), id(self))
 
     @abc.abstractmethod
-    def prime(self, callback):
+    def _prime(self, callback):
         """Set a callback to be invoked when the trigger fires.
 
         The callback will be invoked with a single argument, `self`.
@@ -101,11 +101,11 @@ def prime(self, callback):
         """
         self.primed = True
 
-    def unprime(self):
+    def _unprime(self):
         """Remove the callback, and perform cleanup if necessary.
 
         After being un-primed, a Trigger may be re-primed again in the future.
-        Calling `unprime` multiple times is allowed, subsequent calls should be
+        Calling `_unprime` multiple times is allowed, subsequent calls should be
         a no-op.
 
         Sub-classes may override this, but should end by calling the base class
@@ -119,7 +119,7 @@ def unprime(self):
 
     def __del__(self):
         # Ensure if a trigger drops out of scope we remove any pending callbacks
-        self.unprime()
+        self._unprime()
 
     @property
     def _outcome(self):
@@ -159,12 +159,12 @@ def __init__(self):
         # else:
         self.cbhdl = None
 
-    def unprime(self):
+    def _unprime(self):
         """Disable a primed trigger, can be re-primed."""
         if self.cbhdl is not None:
             self.cbhdl.deregister()
         self.cbhdl = None
-        Trigger.unprime(self)
+        Trigger._unprime(self)
 
 
 class Timer(GPITrigger):
@@ -255,7 +255,7 @@ def __init__(
             round_mode = type(self).round_mode
         self.sim_steps = get_sim_steps(time, units, round_mode=round_mode)
 
-    def prime(self, callback):
+    def _prime(self, callback):
         """Register for a timed callback."""
         if self.cbhdl is None:
             self.cbhdl = simulator.register_timed_callback(
@@ -263,7 +263,7 @@ def prime(self, callback):
             )
             if self.cbhdl is None:
                 raise TriggerException("Unable set up %s Trigger" % (str(self)))
-        GPITrigger.prime(self, callback)
+        GPITrigger._prime(self, callback)
 
     def __repr__(self):
         return "<{} of {:1.2f}ps at {}>".format(
@@ -297,12 +297,12 @@ def __singleton_key__(cls):
     def __init__(self):
         GPITrigger.__init__(self)
 
-    def prime(self, callback):
+    def _prime(self, callback):
         if self.cbhdl is None:
             self.cbhdl = simulator.register_readonly_callback(callback, self)
             if self.cbhdl is None:
                 raise TriggerException("Unable set up %s Trigger" % (str(self)))
-        GPITrigger.prime(self, callback)
+        GPITrigger._prime(self, callback)
 
     def __repr__(self):
         return "{}()".format(type(self).__qualname__)
@@ -320,12 +320,12 @@ def __singleton_key__(cls):
     def __init__(self):
         GPITrigger.__init__(self)
 
-    def prime(self, callback):
+    def _prime(self, callback):
         if self.cbhdl is None:
             self.cbhdl = simulator.register_rwsynch_callback(callback, self)
             if self.cbhdl is None:
                 raise TriggerException("Unable set up %s Trigger" % (str(self)))
-        GPITrigger.prime(self, callback)
+        GPITrigger._prime(self, callback)
 
     def __repr__(self):
         return "{}()".format(type(self).__qualname__)
@@ -343,12 +343,12 @@ def __singleton_key__(cls):
     def __init__(self):
         GPITrigger.__init__(self)
 
-    def prime(self, callback):
+    def _prime(self, callback):
         if self.cbhdl is None:
             self.cbhdl = simulator.register_nextstep_callback(callback, self)
             if self.cbhdl is None:
                 raise TriggerException("Unable set up %s Trigger" % (str(self)))
-        GPITrigger.prime(self, callback)
+        GPITrigger._prime(self, callback)
 
     def __repr__(self):
         return "{}()".format(type(self).__qualname__)
@@ -373,7 +373,7 @@ def __init__(self, signal):
         super().__init__()
         self.signal = signal
 
-    def prime(self, callback):
+    def _prime(self, callback):
         """Register notification of a value change via a callback"""
         if self.cbhdl is None:
             self.cbhdl = simulator.register_value_change_callback(
@@ -381,7 +381,7 @@ def prime(self, callback):
             )
             if self.cbhdl is None:
                 raise TriggerException("Unable set up %s Trigger" % (str(self)))
-        super().prime(callback)
+        super()._prime(callback)
 
     def __repr__(self):
         return "{}({!r})".format(type(self).__qualname__, self.signal)
@@ -421,10 +421,10 @@ def __init__(self, parent):
         PythonTrigger.__init__(self)
         self.parent = parent
 
-    def prime(self, callback):
+    def _prime(self, callback):
         self._callback = callback
         self.parent._prime_trigger(self, callback)
-        Trigger.prime(self, callback)
+        Trigger._prime(self, callback)
 
     def __call__(self):
         self._callback(self)
@@ -508,11 +508,11 @@ def __init__(self, parent):
         self.fired = False
         self.data = None
 
-    def prime(self, callback):
+    def _prime(self, callback):
         if self._callback is not None:
             raise RuntimeError("This Trigger may only be awaited once")
         self._callback = callback
-        Trigger.prime(self, callback)
+        Trigger._prime(self, callback)
         if self.fired:
             self._callback(self)
 
@@ -551,10 +551,10 @@ def __init__(self, parent):
         PythonTrigger.__init__(self)
         self.parent = parent
 
-    def prime(self, callback):
+    def _prime(self, callback):
         self._callback = callback
         self.parent._prime_trigger(self, callback)
-        Trigger.prime(self, callback)
+        Trigger._prime(self, callback)
 
     def __call__(self):
         self._callback(self)
@@ -662,7 +662,7 @@ def _outcome(self):
             return self.__outcome
         return super()._outcome
 
-    def prime(self, callback):
+    def _prime(self, callback):
         callback(self)
 
     def __repr__(self):
@@ -724,11 +724,11 @@ def retval(self):
         """
         return self._coroutine.result()
 
-    def prime(self, callback):
+    def _prime(self, callback):
         if self._coroutine.done():
             callback(self)
         else:
-            super().prime(callback)
+            super()._prime(callback)
 
     def __repr__(self):
         return "{}({!s})".format(type(self).__qualname__, self._coroutine)


Test patch:
diff --git a/tests/test_cases/test_cocotb/test_scheduler.py b/tests/test_cases/test_cocotb/test_scheduler.py
--- a/tests/test_cases/test_cocotb/test_scheduler.py
+++ b/tests/test_cases/test_cocotb/test_scheduler.py
@@ -162,7 +162,7 @@ async def test_trigger_with_failing_prime(dut):
     """Test that a trigger failing to prime throws"""
 
     class ABadTrigger(Trigger):
-        def prime(self, callback):
+        def _prime(self, callback):
             raise RuntimeError("oops")
 
     await Timer(1, "ns")
@@ -542,7 +542,7 @@ async def coro():
 
     t = Timer(1, "step")
     # pre-prime with wrapper function instead of letting scheduler prime it normally
-    t.prime(react_wrapper)
+    t._prime(react_wrapper)
     await t
     # react_wrapper is now on the stack
     cocotb.start_soon(coro())  # coro() should run before returning to the simulator
@@ -672,7 +672,7 @@ async def coro():
 
     t = Timer(1, "step")
     # pre-prime with wrapper function instead of letting scheduler prime it normally
-    t.prime(react_wrapper)
+    t._prime(react_wrapper)
     await t
     # react_wrapper is now on the stack
     assert sim_resumed is False