Hi,
I try to manipulate the start_dt property of an event:
newEvent.start_dt = newEvent.start_dt.replace(hour = EVENT_START_DT.hour,
minute = EVENT_START_DT.minute,
second = EVENT_START_DT.second,
microsecond = EVENT_START_DT.microsecond)
Unfortunately, this implementation results in a runtime error:
RuntimeError: Time change of <Event(189, 2020-04-01 15:44:02.001639+00:00, 2020-04-02 23:44:02.001639+00:00): “DemoEvent”> was not tracked
Does anyone have a clue how to track the time manipulation ?
Best regards,
Philipp
Hey,
in order to make it work I think you should run your code wrapped in a context manager called track_time_changes
. For example:
from indico.modules.events.util import track_time_changes
with track_time_changes():
your code
Tip: When getting an error like this, searching for the origin in the code often helps. For example, searching for “was not tracked” points to the register_event_time_change
function, whose docstring actually mentions what @kolodzie wrote above:
"""Register a time-related change for an event
This is an internal helper function used in the model to record
changes of the start time or end time. The changes are exposed
through the `track_time_changes` contextmanager function.
"""
and track_time_changes
is documented like this:
@contextmanager
def track_time_changes(auto_extend=False, user=None):
"""Track time changes of event objects.
This provides a list of changes while the context manager was
active and also triggers `times_changed` signals.
If the code running inside the ``with`` block of this context
manager raises an exception, no signals will be triggered.
:param auto_extend: Whether entry parents will get their boundaries
automatically extended or not. Passing ``'start'`` will
extend only start datetime, ``'end'`` to extend only
end datetime.
:param user: The `User` that will trigger time changes.
"""
Thank you for you help. The code works now.
But one question is left:
I know from other flask apps, that if you want to modify the database entry of a model you create an instance of that model first and pass it to the database via:
db.session.add(my_Model_Instance)
db.session.commit()
Is the helper function track_time_changes
similar in functionality to these lines of code ?
No, adding to the session is only needed when an object is completely new (ie not in the DB yet and not linked to any object already in the DB). Same in Indico. The commit is done automatically by the RH class, unless you disable this using self.commit = False
.
But the point of track_time_changes
is something completely different: It takes care of correctly handling automatically extending the event’s duration when changing something inside its timetable in a way that would exceed the boundaries of the event. It also triggers the signal plugins can use to be notified about any time changes.
Having the transaction fail unless it’s explicitly “whitelisted” inside a track_time_changes
also makes sure that you don’t accidentally end up unknowingly changing event times somewhere else.
I see. Thank you very much.