From 2b7df634fcda2d0772c4fefd9088d9e9d9ef9d76 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 22 Oct 2024 02:29:57 +0200 Subject: [PATCH] A better way to ensure that the components cache won't be rewritten unless changed. - Compare the serialized versions of the cache before and after, minus the saved/loaded timestamps, rather than marking the cache as dirty after a set. - `Date` and `DateTime` schema fields should have static default values, or those values will change on every run. - Always sort all the sets before serializing them. --- platypush/plugins/inspect/__init__.py | 10 +++++++++- platypush/schemas/__init__.py | 5 ++--- platypush/utils/manifest.py | 15 ++++++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/platypush/plugins/inspect/__init__.py b/platypush/plugins/inspect/__init__.py index 3319ec46a6..6532ef0dfb 100644 --- a/platypush/plugins/inspect/__init__.py +++ b/platypush/plugins/inspect/__init__.py @@ -4,6 +4,7 @@ import json import os import pathlib import pkgutil +from copy import deepcopy from concurrent.futures import Future, ThreadPoolExecutor from typing import List, Optional @@ -70,6 +71,9 @@ class InspectPlugin(Plugin): """ cache_version_differs = self._cache.version != Cache.cur_version force = force or cache_version_differs + old_cache = deepcopy(self._cache.to_dict()) + old_cache.pop('loaded_at', None) + old_cache.pop('saved_at', None) with self._cache.lock(), auto_mocks(), override_definitions(), ThreadPoolExecutor( self._num_workers @@ -101,7 +105,11 @@ class InspectPlugin(Plugin): while futures: futures.pop().result() - if self._cache.has_changes: + new_cache = self._cache.to_dict() + new_cache.pop('loaded_at', None) + new_cache.pop('saved_at', None) + + if old_cache != new_cache or cache_version_differs: self.logger.info('Saving new components cache to %s', self.cache_file) self._cache.dump(self.cache_file) self._cache.loaded_at = self._cache.saved_at diff --git a/platypush/schemas/__init__.py b/platypush/schemas/__init__.py index c81d01540f..fd8ddc4da8 100644 --- a/platypush/schemas/__init__.py +++ b/platypush/schemas/__init__.py @@ -3,7 +3,6 @@ from enum import Enum from typing import Any, Optional, Type, Union from dateutil.parser import isoparse -from dateutil.tz import tzutc from marshmallow import fields @@ -38,7 +37,7 @@ class DateTime(Function): # lgtm [py/missing-call-to-init] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.metadata = { - 'example': datetime.now(tz=tzutc()).isoformat(), + 'example': '2020-01-01T00:00:00+00:00', **(self.metadata or {}), } @@ -55,7 +54,7 @@ class Date(Function): # lgtm [py/missing-call-to-init] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.metadata = { - 'example': date.today().isoformat(), + 'example': '2020-01-01', **(self.metadata or {}), } diff --git a/platypush/utils/manifest.py b/platypush/utils/manifest.py index 07788deb78..1d0ff533cc 100644 --- a/platypush/utils/manifest.py +++ b/platypush/utils/manifest.py @@ -274,12 +274,15 @@ class Dependencies: def to_dict(self): return { 'before': self.before, - 'packages': list(self.packages), - 'pip': self.pip, + 'packages': sorted(self.packages), + 'pip': sorted(self.pip), 'after': self.after, 'by_pkg_manager': { - pkg_manager.value.executable: list(pkgs) - for pkg_manager, pkgs in self.by_pkg_manager.items() + pkg_manager.value.executable: sorted(pkgs) + for pkg_manager, pkgs in sorted( + self.by_pkg_manager.items(), + key=lambda item: item[0].value.executable, + ) }, } @@ -560,7 +563,9 @@ class Manifest(ABC): def _init_events( events: Union[Iterable[str], Mapping[str, Optional[str]]] ) -> Dict[Type, str]: - evt_dict = events if isinstance(events, Mapping) else {e: None for e in events} + evt_dict = ( + events if isinstance(events, Mapping) else dict.fromkeys(events, None) + ) ret = {} for evt_name, doc in evt_dict.items():