• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2024 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4""" An AbstractContextManager to wait the modifications to finish during exit.
5"""
6
7import os
8import time
9from contextlib import AbstractContextManager
10
11
12class ModificationWaiter(AbstractContextManager):
13    """ Exits if there is no modifications for a certain time period, or the
14    timeout has been reached. """
15
16    def __init__(self, path: str) -> None:
17        self._path = path
18        # Waits at most 60 seconds.
19        self._timeout = 60
20        # Exits early if no modification happened during last 5 seconds.
21        self._quiet_time = 5
22
23    def __enter__(self) -> None:
24        # Do nothing, the logic happens in __exit__
25        return
26
27    def __exit__(self, exc_type, exc_value, traceback) -> bool:
28        # Always consider the last modification happening now to avoid an
29        # unexpected early return.
30        last_mod_time = time.time()
31        start_time = last_mod_time
32        while True:
33            cur_time = time.time()
34            if cur_time - start_time >= self._timeout:
35                break
36            cur_mod_time = os.path.getmtime(self._path)
37            if cur_mod_time > last_mod_time:
38                last_mod_time = cur_mod_time
39            elif cur_time - last_mod_time >= self._quiet_time:
40                break
41            time.sleep(1)
42
43        # Do not suppress exceptions.
44        return False
45