Time replacement not tracked in event

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.