Mercurial > piecrust2
view piecrust/data/base.py @ 1188:a7c43131d871
bake: Fix file write flushing problem with Python 3.8+
Writing the cache files fails in Python 3.8 because it looks like flushing
behaviour has changed. We need to explicitly flush. And even then, in very
rare occurrences, it looks like it can still run into racing conditions,
so we do a very hacky and ugly "retry" loop when fetching cached data :(
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 15 Jun 2021 22:36:23 -0700 |
parents | 501bd4ab7e06 |
children |
line wrap: on
line source
import time import collections.abc class MergedMapping(collections.abc.Mapping): """ Provides a dictionary-like object that's really the aggregation of multiple dictionary-like objects. """ def __init__(self, dicts, path=''): self._dicts = dicts self._path = path def __getattr__(self, name): try: return self[name] except KeyError: raise AttributeError("No such attribute: %s" % self._subp(name)) def __getitem__(self, name): values = [] for d in self._dicts: try: val = getattr(d, name) values.append(val) continue except AttributeError: pass try: val = d[name] values.append(val) continue except KeyError: pass if len(values) == 0: raise KeyError("No such item: %s" % self._subp(name)) if len(values) == 1: return values[0] for val in values: if not isinstance(val, (dict, collections.abc.Mapping)): raise Exception( "Template data for '%s' contains an incompatible mix " "of data: %s" % ( self._subp(name), ', '.join([str(type(v)) for v in values]))) return MergedMapping(values, self._subp(name)) def __iter__(self): keys = set() for d in self._dicts: keys |= set(d.keys()) return iter(keys) def __len__(self): keys = set() for d in self._dicts: keys |= set(d.keys()) return len(keys) def _subp(self, name): return '%s/%s' % (self._path, name) def _prependMapping(self, d): self._dicts.insert(0, d) def _appendMapping(self, d): self._dicts.append(d)