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.
This commit is contained in:
Fabio Manganiello 2024-10-22 02:29:57 +02:00
parent 8feee6ce39
commit 2b7df634fc
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774
3 changed files with 21 additions and 9 deletions

View file

@ -4,6 +4,7 @@ import json
import os import os
import pathlib import pathlib
import pkgutil import pkgutil
from copy import deepcopy
from concurrent.futures import Future, ThreadPoolExecutor from concurrent.futures import Future, ThreadPoolExecutor
from typing import List, Optional from typing import List, Optional
@ -70,6 +71,9 @@ class InspectPlugin(Plugin):
""" """
cache_version_differs = self._cache.version != Cache.cur_version cache_version_differs = self._cache.version != Cache.cur_version
force = force or cache_version_differs 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( with self._cache.lock(), auto_mocks(), override_definitions(), ThreadPoolExecutor(
self._num_workers self._num_workers
@ -101,7 +105,11 @@ class InspectPlugin(Plugin):
while futures: while futures:
futures.pop().result() 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.logger.info('Saving new components cache to %s', self.cache_file)
self._cache.dump(self.cache_file) self._cache.dump(self.cache_file)
self._cache.loaded_at = self._cache.saved_at self._cache.loaded_at = self._cache.saved_at

View file

@ -3,7 +3,6 @@ from enum import Enum
from typing import Any, Optional, Type, Union from typing import Any, Optional, Type, Union
from dateutil.parser import isoparse from dateutil.parser import isoparse
from dateutil.tz import tzutc
from marshmallow import fields from marshmallow import fields
@ -38,7 +37,7 @@ class DateTime(Function): # lgtm [py/missing-call-to-init]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.metadata = { self.metadata = {
'example': datetime.now(tz=tzutc()).isoformat(), 'example': '2020-01-01T00:00:00+00:00',
**(self.metadata or {}), **(self.metadata or {}),
} }
@ -55,7 +54,7 @@ class Date(Function): # lgtm [py/missing-call-to-init]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.metadata = { self.metadata = {
'example': date.today().isoformat(), 'example': '2020-01-01',
**(self.metadata or {}), **(self.metadata or {}),
} }

View file

@ -274,12 +274,15 @@ class Dependencies:
def to_dict(self): def to_dict(self):
return { return {
'before': self.before, 'before': self.before,
'packages': list(self.packages), 'packages': sorted(self.packages),
'pip': self.pip, 'pip': sorted(self.pip),
'after': self.after, 'after': self.after,
'by_pkg_manager': { 'by_pkg_manager': {
pkg_manager.value.executable: list(pkgs) pkg_manager.value.executable: sorted(pkgs)
for pkg_manager, pkgs in self.by_pkg_manager.items() 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( def _init_events(
events: Union[Iterable[str], Mapping[str, Optional[str]]] events: Union[Iterable[str], Mapping[str, Optional[str]]]
) -> Dict[Type, 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 = {} ret = {}
for evt_name, doc in evt_dict.items(): for evt_name, doc in evt_dict.items():