def AddImportCallbackBySuffix(path, callback):
  """Register import hook.

  This function overrides the default import process. Then whenever a module
  whose suffix matches path is imported, the callback will be invoked.

  A module may be imported multiple times. Import event only means that the
  Python code contained an "import" statement. The actual loading and
  initialization of a new module normally happens only once, at which time
  the callback will be invoked. This function does not validates the existence
  of such a module and it's the responsibility of the caller.

  TODO(erezh): handle module reload.

  Args:
    path: python module file path. It may be missing the directories for the
          outer packages, and therefore, requires suffix comparison to match
          against loaded modules. If it contains all outer packages, it may
          contain the sys.path as well.
          It might contain an incorrect file extension (e.g., py vs. pyc).
    callback: callable to invoke upon module load.

  Returns:
    Function object to invoke to remove the installed callback.
  """

  def RemoveCallback():
    # This is a read-if-del operation on _import_callbacks. Lock to prevent
    # callbacks from being inserted just before the key is deleted. Thus, it
    # must be locked also when inserting a new entry below. On the other hand
    # read only access, in the import hook, does not require a lock.
    with _import_callbacks_lock:
      callbacks = _import_callbacks.get(path)
      if callbacks:
        callbacks.remove(callback)
        if not callbacks:
          del _import_callbacks[path]

  with _import_callbacks_lock:
    _import_callbacks.setdefault(path, set()).add(callback)
  _InstallImportHookBySuffix()

  return RemoveCallback
Register import hook.

  This function overrides the default import process. Then whenever a module
  whose suffix matches path is imported, the callback will be invoked.

  A module may be imported multiple times. Import event only means that the
  Python code contained an "import" statement. The actual loading and
  initialization of a new module normally happens only once, at which time
  the callback will be invoked. This function does not validates the existence
  of such a module and it's the responsibility of the caller.

  TODO(erezh): handle module reload.

  Args:
    path: python module file path. It may be missing the directories for the
          outer packages, and therefore, requires suffix comparison to match
          against loaded modules. If it contains all outer packages, it may
          contain the sys.path as well.
          It might contain an incorrect file extension (e.g., py vs. pyc).
    callback: callable to invoke upon module load.

  Returns:
    Function object to invoke to remove the installed callback.