+def was_file_written_today(filename: str) -> bool:
+ """Convenience wrapper around :meth:`was_file_written_within_n_seconds`.
+
+ Args:
+ filename: filename to check
+
+ Returns:
+ True if filename was written today.
+
+ >>> import os
+ >>> filename = f'/tmp/testing_persistent_py_{os.getpid()}'
+ >>> os.system(f'touch {filename}')
+ 0
+ >>> was_file_written_today(filename)
+ True
+ >>> os.system(f'touch -d 1974-04-15T01:02:03.99 {filename}')
+ 0
+ >>> was_file_written_today(filename)
+ False
+ >>> os.system(f'/bin/rm -f {filename}')
+ 0
+ >>> was_file_written_today(filename)
+ False
+ """
+
+ if not file_utils.does_file_exist(filename):
+ return False
+
+ mtime = file_utils.get_file_mtime_as_datetime(filename)
+ assert mtime is not None
+ now = datetime.datetime.now()
+ return mtime.month == now.month and mtime.day == now.day and mtime.year == now.year
+
+
+def was_file_written_within_n_seconds(
+ filename: str,
+ limit_seconds: int,
+) -> bool:
+ """Helper for determining persisted state staleness.
+
+ Args:
+ filename: the filename to check
+ limit_seconds: how fresh, in seconds, it must be
+
+ Returns:
+ True if filename was written within the past limit_seconds
+ or False otherwise (or on error).
+
+ >>> import os
+ >>> filename = f'/tmp/testing_persistent_py_{os.getpid()}'
+ >>> os.system(f'touch {filename}')
+ 0
+ >>> was_file_written_within_n_seconds(filename, 60)
+ True
+ >>> import time
+ >>> time.sleep(2.0)
+ >>> was_file_written_within_n_seconds(filename, 2)
+ False
+ >>> os.system(f'/bin/rm -f {filename}')
+ 0
+ >>> was_file_written_within_n_seconds(filename, 60)
+ False
+ """
+
+ if not file_utils.does_file_exist(filename):
+ return False
+
+ mtime = file_utils.get_file_mtime_as_datetime(filename)
+ assert mtime is not None
+ now = datetime.datetime.now()
+ return (now - mtime).total_seconds() <= limit_seconds
+
+
+class PersistAtShutdown(enum.Enum):
+ """
+ An enum to describe the conditions under which state is persisted
+ to disk. This is passed as an argument to the decorator below and
+ is used to indicate when to call :meth:`save` on a :class:`Persistent`
+ subclass.
+
+ * NEVER: never call :meth:`save`
+ * IF_NOT_LOADED: call :meth:`save` as long as we did not successfully
+ :meth:`load` its state.
+ * ALWAYS: always call :meth:`save`
+ """
+
+ NEVER = (0,)
+ IF_NOT_LOADED = (1,)
+ ALWAYS = (2,)
+
+
+class persistent_autoloaded_singleton(object):
+ """A decorator that can be applied to a :class:`Persistent` subclass
+ (i.e. a class with :meth:`save` and :meth:`load` methods. The
+ decorator will intercept attempts to instantiate the class via
+ it's c'tor and, instead, invoke the class' :meth:`load` to give it a
+ chance to read state from somewhere persistent (disk, db,
+ whatever). Subsequent calls to construt instances of the wrapped
+ class will return a single, global instance (i.e. the wrapped
+ class is a singleton).
+
+ If :meth:`load` fails (returns None), the c'tor is invoked with the
+ original args as a fallback.
+
+ Based upon the value of the optional argument
+ :code:`persist_at_shutdown` argument, (NEVER, IF_NOT_LOADED,
+ ALWAYS), the :meth:`save` method of the class will be invoked just
+ before program shutdown to give the class a chance to save its
+ state somewhere.
+
+ .. note::
+ The implementations of :meth:`save` and :meth:`load` and where the
+ class persists its state are details left to the :class:`Persistent`
+ implementation. Essentially this decorator just handles the
+ plumbing of calling your save/load and appropriate times and
+ creates a transparent global singleton whose state can be
+ persisted between runs.
+
+ """
+
+ def __init__(
+ self,
+ *,
+ persist_at_shutdown: PersistAtShutdown = PersistAtShutdown.IF_NOT_LOADED,
+ ):
+ self.persist_at_shutdown = persist_at_shutdown