diff options
| author | Daniel Schadt <kingdread@gmx.de> | 2023-03-30 21:19:46 +0200 | 
|---|---|---|
| committer | Daniel Schadt <kingdread@gmx.de> | 2023-03-30 21:41:47 +0200 | 
| commit | 60a1585a37bfee43e3d6c7cac002eeee85768c5f (patch) | |
| tree | e9bb6b163e5d6858f18c5b69aa8833b51d470507 | |
| parent | a2aaf098ca5ac897a5e0e1b2302acaf0562f8aad (diff) | |
| download | fietsboek-60a1585a37bfee43e3d6c7cac002eeee85768c5f.tar.gz fietsboek-60a1585a37bfee43e3d6c7cac002eeee85768c5f.tar.bz2 fietsboek-60a1585a37bfee43e3d6c7cac002eeee85768c5f.zip  | |
check if data version matches at startup
This might be helpful to see some errors early.
| -rw-r--r-- | fietsboek/__init__.py | 30 | ||||
| -rw-r--r-- | fietsboek/updater/__init__.py | 46 | 
2 files changed, 75 insertions, 1 deletions
diff --git a/fietsboek/__init__.py b/fietsboek/__init__.py index 41e8a04..ee7d8b7 100644 --- a/fietsboek/__init__.py +++ b/fietsboek/__init__.py @@ -14,6 +14,7 @@ Content  -------  """  import importlib.metadata +import logging  from pathlib import Path  from typing import Callable, Optional @@ -33,9 +34,12 @@ from . import transformers  from .data import DataManager  from .pages import Pages  from .security import SecurityPolicy +from .updater import Updater, UpdateState  __VERSION__ = importlib.metadata.version("fietsboek") +LOGGER = logging.getLogger(__name__) +  def locale_negotiator(request: Request) -> Optional[str]:      """Negotiates the right locale to use. @@ -88,12 +92,36 @@ def maintenance_mode(      return tween -def main(_global_config, **settings): +def check_update_state(config_uri: str): +    """Checks the update state of the data, and logs a warning if there is a +    mismatch. + +    :param config_uri: Path to the configuration file. +    """ +    updater = Updater(config_uri) +    updater.load() +    state = updater.state() + +    if state == UpdateState.OUTDATED: +        LOGGER.warning( +            "The data seems to be outdated - make sure to run the fietsupdate migrations!" +        ) +    elif state == UpdateState.TOO_NEW: +        LOGGER.warning("The data seems to be too new, make sure to update the code accordingly!") +    elif state == UpdateState.UNKNOWN: +        LOGGER.warning("Could not determine version state of the data - check `fietsupdate status`") + + +def main(global_config, **settings):      """This function returns a Pyramid WSGI application."""      # Avoid a circular import by not importing at the top level      # pylint: disable=import-outside-toplevel,cyclic-import      from .views.tileproxy import TileRequester +    # In tests this isn't passed, so guard against it +    if "__file__" in global_config: +        check_update_state(global_config["__file__"]) +      parsed_config = mod_config.parse(settings)      settings["jinja2.newstyle"] = True diff --git a/fietsboek/updater/__init__.py b/fietsboek/updater/__init__.py index fa7f5c6..5faa805 100644 --- a/fietsboek/updater/__init__.py +++ b/fietsboek/updater/__init__.py @@ -1,5 +1,6 @@  """Updating (data migration) logic for fietsboek."""  import datetime +import enum  import importlib.resources  import importlib.util  import logging @@ -50,6 +51,26 @@ class Down(UpdateScript):  """ +class UpdateState(enum.Enum): +    """State of the applied updates. + +    This represents a "summary" of the output that ``fietsupdate status`` +    produces. +    """ + +    OKAY = enum.auto() +    """Everything is good, the data is up to date.""" + +    OUTDATED = enum.auto() +    """The data is outdated, the update process should be run.""" + +    TOO_NEW = enum.auto() +    """The data contains revisions that are not known to Fietsboek yet.""" + +    UNKNOWN = enum.auto() +    """The data version could not be determined.""" + +  class Updater:      """A class that implements the updating logic. @@ -284,6 +305,31 @@ class Updater:              return revision_id in self._transitive_versions()          return revision_id in self._reverse_versions() | set(self.current_versions()) +    def state(self) -> UpdateState: +        """Checks the update state of the instance. + +        This returns a condensed version of what ``fietsupdate status`` +        outputs. + +        :return: The update state of the data. +        """ +        state = UpdateState.OKAY +        current = self.current_versions() +        heads = self.heads() +        if current: +            for i in current: +                if not self.exists(i): +                    state = UpdateState.TOO_NEW +        else: +            return UpdateState.UNKNOWN +        updates = set(heads) - set(current) +        if updates: +            if state != UpdateState.OKAY: +                # We are both too new and too old, so something is pretty wrong +                return UpdateState.UNKNOWN +            return UpdateState.OUTDATED +        return state +  class UpdateScript:      """Represents an update script."""  | 
