def has_changed(self): """Check wether the entry has changed using the following conditions: - cache file does not exist -> has changed - cache file does not contain required filter intermediate -> has changed - entry's file is newer than the cache's one -> has changed - otherwise -> not changed""" # with new-style classes we can't delete/overwrite @property-ied methods, # so we try to return a fixed value otherwise continue try: return self._has_changed except AttributeError: pass path = join(cache.cache_dir, self.md5) deps = [] for fxs in self.filters.iter(self.context): # extend filter dependencies deps.extend(fxs) if not cache.has_key(path, md5(*deps)): return True else: return self.lastmodified > cache.getmtime(path)
def generate(self, request): entrylist = sorted((e for e in request['entrylist'] if not e.draft), key=lambda k: k.date, reverse=True) tt = self.env.engine.fromfile(self.template) path = joinurl(self.conf['output_dir'], self.path, 'index.html') hv = md5(*entrylist, attr=lambda o: o.md5) rv = memoize('articles-hash') if rv == hv: has_changed = False else: # save new value for next run memoize('articles-hash', hv) has_changed = True if exists(path) and not has_changed and not tt.has_changed: event.skip(path) raise StopIteration articles = {} for entry in entrylist: articles.setdefault((entry.year, entry.imonth), []).append(entry) route = self.path html = tt.render(conf=self.conf, articles=articles, env=union(self.env, num_entries=len(entrylist), route=route)) yield html, path
def generate(self, request): entrylist = sorted((e for e in request['entrylist'] if not e.draft), key=lambda k: k.date, reverse=True) tt = self.env.tt.fromfile(self.template) path = joinurl(self.conf['output_dir'], self.path, 'index.html') hv = md5(*entrylist, attr=lambda o: o.md5) rv = memoize('articles-hash') if rv == hv: has_changed = False else: # save new value for next run memoize('articles-hash', hv) has_changed = True if exists(path) and not has_changed and not tt.has_changed: event.skip(path) raise StopIteration articles = {} for entry in entrylist: articles.setdefault((entry.year, entry.month), []).append(entry) html = tt.render(conf=self.conf, articles=articles, env=union(self.env, num_entries=len(entrylist))) yield html, path
def generate(self, request): entrylist = filter(lambda e: not e.draft, request['entrylist']) entrylist = list(entrylist)[0:self.num_entries] tt = self.env.engine.fromfile('%s.xml' % self.type) path = joinurl(self.conf['output_dir'], self.path) if not path.endswith(('.xml', '.html')): path = joinurl(path, 'index.html') # detect removed entries hv = md5(*entrylist, attr=lambda e: e.permalink) if memoize(path) != hv: memoize(path, hv) has_changed = True else: has_changed = False if (exists(path) and not filter(lambda e: e.has_changed, entrylist) and not has_changed and not tt.has_changed): event.skip(path) raise StopIteration updated = entrylist[0].date if entrylist else datetime.utcnow() html = tt.render(conf=self.conf, env=union(self.env, route=self.path, updated=updated, entrylist=entrylist)) yield html, path
def has_changed(self, entrylist): # detect changes in prev and next hv = md5(*entrylist, attr=lambda e: e.permalink) if memoize('entry-permalinks') != hv: memoize('entry-permalinks', hv) return True return False
def generate(self, request): tt = self.env.tt.fromfile(self.template) entrylist = request['entrylist'] pathes = dict() for entry in entrylist: if entry.permalink != expand(self.path, entry): p = joinurl(self.conf['output_dir'], entry.permalink) else: p = joinurl(self.conf['output_dir'], expand(self.path, entry)) if p.endswith('/'): p = joinurl(p, 'index.html') if p in pathes: raise AcrylamidException("title collision %r in %r" % (entry.permalink, entry.filename)) pathes[p] = entry has_changed = False hv = md5(*entrylist, attr=lambda e: e.permalink) if memoize('entry-permalinks') != hv: memoize('entry-permalinks', hv) has_changed = True pathes = sorted(pathes.iteritems(), key=lambda k: k[1].date, reverse=True) for i, (path, entry) in enumerate(pathes): next = None if i == 0 else link(entrylist[i-1].title, entrylist[i-1].permalink.rstrip('/'), entrylist[i-1]) prev = None if i == len(pathes) - 1 else link(entrylist[i+1].title, entrylist[i+1].permalink.rstrip('/'), entrylist[i+1]) if exists(path) and not any([has_changed, entry.has_changed, tt.has_changed]): event.skip(path) continue html = tt.render(conf=self.conf, entry=entry, env=union(self.env, entrylist=[entry], type='entry', prev=prev, next=next)) yield html, path
def content(self): """Returns the processed content. This one of the core functions of acrylamid: it compiles incrementally the filter chain using a tree representation and saves final output or intermediates to cache, so we can rapidly re-compile the whole content. The cache is rather dumb: Acrylamid can not determine wether it differs only in a single character. Thus, to minimize the overhead the cache object is zlib-compressed.""" # previous value pv = None # this is our cache filename path = join(cache.cache_dir, self.md5) # growing dependencies of the filter chain deps = [] for fxs in self.filters.iter(context=self.context): # extend dependencies deps.extend(fxs) # key where we save this filter chain key = md5(*deps) try: rv = cache.get(path, key, mtime=self.lastmodified) if rv is None: res = self.source if pv is None else pv for f in fxs: res = f.transform(res, self, *f.args) pv = cache.set(path, key, res) self.has_changed = True else: pv = rv except (IndexError, AttributeError): # jinja2 will ignore these Exceptions, better to catch them before traceback.print_exc(file=sys.stdout) return pv
def md5(self): return md5(self.filename, self.title, self.date)