Spaces:
Building
Building
# Copyright 2024 The etils Authors. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
"""IPython utils.""" | |
from typing import Callable, Hashable | |
import IPython | |
def register_once( | |
event_name: str, | |
callback: Callable[..., None], | |
info: Hashable, | |
) -> None: | |
"""Register the IPython event once (replace the previous event if exists). | |
Alias for `InteractiveShell.events.register` but replaces previous event | |
if it exists. | |
This avoids duplicated events after ecolab reload or running cell twice. | |
Args: | |
event_name: Forwarded to `ip.events.register` | |
callback: Forwarded to `ip.events.register` | |
info: If an event with the same info already exists, it is replaced. | |
""" | |
ip = IPython.get_ipython() | |
# Even if hash is non-deterministic, we only need to check registration within | |
# the same run. | |
info = hash(info) | |
# Remove the previous callback (if any) | |
for old_callback in ip.events.callbacks[event_name]: | |
if getattr(old_callback, '__ecolab_event__', None) == info: | |
ip.events.unregister(event_name, old_callback) | |
break | |
# Mark the function (so it can be cleared when reloaded) | |
callback.__ecolab_event__ = info | |
ip.events.register(event_name, callback) | |