def generate(self, conf, env, data): """In this step, we filter drafted entries (they should not be included into the Sitemap) and test each url pattern for success and write the corresponding changefreq and priority to the Sitemap.""" drafted = set([joinurl(conf['output_dir'], e.permalink, 'index.html') for e in data.get('drafts', [])]) path = joinurl(conf['output_dir'], self.path) sm = Map() if exists(path) and not self.modified: event.skip(path) raise StopIteration for fname in self.files: if fname in drafted: continue url = join(conf['www_root'], fname.replace(conf['output_dir'], '')) for view in self.views: if any(ifilter(lambda pat: pat.match(url), self.patterns[view])): priority, changefreq = self.scores.get(view.name, (0.5, 'weekly')) sm.add(rchop(url, 'index.html'), getmtime(fname), changefreq, priority) break sm.finish() yield sm, 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): """Creates nicely paged listing of your posts. First page is the index.hml used to have this nice url: http://yourblog.com/ with a recent list of your (e.g. summarized) Posts. Other pages are enumerated to /page/n+1 """ ipp = self.items_per_page tt = self.env.jinja2.get_template('main.html') entrylist = [entry for entry in request['entrylist'] if not entry.draft] paginator = paginate(entrylist, ipp, orphans=self.conf['default_orphans']) for (next, curr, prev), entries, has_changed in paginator: # curr = current page, next = newer pages, prev = older pages if next is not None: next = self.path.rstrip('/') if next == 1 \ else expand(self.pagination, {'num': next}) curr = self.path if curr == 1 else expand(self.pagination, {'num': curr}) prev = None if prev is None else expand(self.pagination, {'num': prev}) path = joinurl(self.conf['output_dir'], curr, 'index.html') if exists(path) and not has_changed and not tt.has_changed: event.skip(path) continue html = tt.render(conf=self.conf, env=union(self.env, entrylist=entries, type='index', prev=prev, curr=curr, next=next, items_per_page=ipp, num_entries=len(entrylist))) 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.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): tt = self.env.jinja2.get_template('main.html') 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 for path, entry in pathes.iteritems(): if exists(path) and not entry.has_changed and not tt.has_changed: event.skip(path) continue html = tt.render(env=union(self.env, entrylist=[entry], type='entry'), conf=self.conf, entry=entry) yield html, path
def generate(self, request): """In this step, we filter drafted entries (they should not be included into the Sitemap) and test each url pattern for success and write the corresponding changefreq and priority to the Sitemap.""" drafted = set([joinurl(self.conf['output_dir'], e.permalink, 'index.html') for e in request['entrylist'] + request['pages'] if e.draft]) path = joinurl(self.conf['output_dir'], self.path) sm = Map() if exists(path) and not self.has_changed: event.skip(path) raise StopIteration for fname in self.files: if fname in drafted: continue url = join(self.conf['www_root'], fname.replace(self.conf['output_dir'], '')) for view in self.views: if self.patterns[view].match(url): priority, changefreq = self.scores.get(view, (0.5, 'weekly')) sm.add(rchop(url, 'index.html'), getmtime(fname), changefreq, priority) break yield sm.read(), path
def generate(self, conf, env, data, **kwargs): if self.pagination is None: self.items_per_page = 2**32 self.pagination = self.path ipp = self.items_per_page tt = env.engine.fromfile(env, self.template) route = expand(self.path, kwargs) entrylist = data['entrylist'] paginator = paginate(entrylist, ipp, route, conf.default_orphans) for (next, curr, prev), entrylist, modified in paginator: next = None if next is None \ else link(u'Next', expand(self.path, kwargs)) if next == 1 \ else link(u'Next', expand(self.pagination, union({'num': next}, kwargs))) curr = link(curr, expand(self.path, kwargs)) if curr == 1 \ else link(curr, expand(self.pagination, union({'num': curr}, kwargs))) prev = None if prev is None \ else link(u'Previous', expand(self.pagination, union({'num': prev}, kwargs))) path = joinurl(conf['output_dir'], curr.href) if isfile(path) and not (modified or tt.modified or env.modified or conf.modified): event.skip(self.__class__.__name__.lower(), path) continue html = self.render(conf, env, union(locals(), kwargs)) yield html, path
def generate(self, conf, env, data): """In this step, we filter drafted entries (they should not be included into the Sitemap) and write the pre-defined priorities to the map.""" path = joinurl(conf['output_dir'], self.path) sm = Map() if exists(path) and not self.modified and not conf.modified: event.skip('sitemap', path) raise StopIteration for ns, fname in self.files: if ns == 'draft': continue permalink = '/' + fname.replace(conf['output_dir'], '') url = conf['www_root'] + permalink priority, changefreq = self.scores.get(ns, (0.5, 'weekly')) if self.imgext: images = [x for x in self.mapping.get(permalink, []) if splitext(x)[1].lower() in self.imgext] sm.add(rchop(url, 'index.html'), getmtime(fname), changefreq, priority, images) else: sm.add(rchop(url, 'index.html'), getmtime(fname), changefreq, priority) sm.finish() yield sm, path
def generate(self, request): ipp = self.items_per_page tt = self.env.engine.fromfile(self.template) entrylist = [entry for entry in request['entrylist'] if not entry.draft] paginator = paginate(entrylist, ipp, orphans=self.conf['default_orphans']) route = self.path for (next, curr, prev), entries, has_changed in paginator: # curr = current page, next = newer pages, prev = older pages next = None if next is None \ else link(u'« Next', self.path.rstrip('/')) if next == 1 \ else link(u'« Next', expand(self.pagination, {'num': next})) curr = link(curr, self.path) if curr == 1 \ else link(expand(self.pagination, {'num': curr})) prev = None if prev is None \ else link(u'Previous »', expand(self.pagination, {'num': prev})) path = joinurl(self.conf['output_dir'], curr.href, 'index.html') if exists(path) and not has_changed and not tt.has_changed: event.skip(path) continue html = tt.render(conf=self.conf, env=union(self.env, entrylist=entries, type='index', prev=prev, curr=curr, next=next, items_per_page=ipp, num_entries=len(entrylist), route=route)) yield html, path
def generate(self, request): """In this step, we filter drafted entries (they should not be included into the Sitemap) and test each url pattern for success and write the corresponding changefreq and priority to the Sitemap.""" drafted = set([ joinurl(self.conf['output_dir'], e.permalink, 'index.html') for e in request['entrylist'] + request['pages'] if e.draft ]) path = joinurl(self.conf['output_dir'], self.path) sm = Map() if exists(path) and not self.has_changed: event.skip(path) raise StopIteration for fname in self.files: if fname in drafted: continue url = join(self.conf['www_root'], fname.replace(self.conf['output_dir'], '')) for view in self.views: if self.patterns[view].match(url): priority, changefreq = self.scores.get( view, (0.5, 'weekly')) sm.add(rchop(url, 'index.html'), getmtime(fname), changefreq, priority) break yield sm.read(), path
def generate(self, conf, env, data): ipp = self.items_per_page tt = env.engine.fromfile(self.template) entrylist = data['entrylist'] paginator = paginate(entrylist, ipp, self.path, conf.default_orphans) route = self.path for (next, curr, prev), entries, modified in paginator: # curr = current page, next = newer pages, prev = older pages next = None if next is None \ else link(u'« Next', self.path.rstrip('/')) if next == 1 \ else link(u'« Next', expand(self.pagination, {'num': next})) curr = link(curr, self.path) if curr == 1 \ else link(expand(self.pagination, {'num': curr})) prev = None if prev is None \ else link(u'Previous »', expand(self.pagination, {'num': prev})) path = joinurl(conf['output_dir'], curr.href, 'index.html') if isfile(path) and not (modified or tt.modified or env.modified or conf.modified): event.skip(path) continue html = tt.render(conf=conf, env=union(env, entrylist=entries, type='index', prev=prev, curr=curr, next=next, items_per_page=ipp, num_entries=len(entrylist), route=route)) 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 generate(self, request): """Creates paged listing by tag.""" ipp = self.items_per_page tt = self.env.engine.fromfile(self.template) for tag in self.tags: entrylist = [entry for entry in self.tags[tag]] paginator = paginate(entrylist, ipp, salt=tag, orphans=self.conf["default_orphans"]) route = expand(self.path, {"name": tag}).rstrip("/") for (next, curr, prev), entries, has_changed in paginator: # e.g.: curr = /page/3, next = /page/2, prev = /page/4 next = ( None if next is None else link(u"« Next", expand(self.path, {"name": tag}).rstrip("/")) if next == 1 else link(u"« Next", expand(self.pagination, {"name": tag, "num": next})) ) curr = ( link(curr, expand(self.path, {"name": tag})) if curr == 1 else link(expand(self.pagination, {"num": curr, "name": tag})) ) prev = ( None if prev is None else link(u"Previous »", expand(self.pagination, {"name": tag, "num": prev})) ) path = joinurl(self.conf["output_dir"], curr, "index.html") if exists(path) and not has_changed and not tt.has_changed: event.skip(path) continue html = tt.render( conf=self.conf, env=union( self.env, entrylist=entries, type="tag", prev=prev, curr=curr, next=next, tag=tag, items_per_page=ipp, num_entries=len(entrylist), route=route, ), ) yield html, path
def init(env, options): """Subcommand: init -- create the base structure of an Acrylamid blog or restore individual files and folders. If the destination directory is empty, it will create a new blog. If the destination directory is not empty it won't overwrite anything unless you supply -f, --force to re-initialize the whole theme. If you need to restore a single file, run $ cd blog && acrylamid init theme/main.html """ if not options.engine: try: import jinja2 options.engine = "jinja2" except ImportError: options.engine = "mako" theme, files = rollout(options.theme, options.engine) # if destination is part of theme, restore it! for src, dest in resolve(options, theme, files): if dest.endswith(options.dest): if ( not isfile(options.dest) or options.overwrite or raw_input("re-initialize %s ? [yn]: " % options.dest) == "y" ): write(src, options.dest) log.info("re-initialized " + options.dest) return if isfile(options.dest): raise AcrylamidException("%s already exists!" % options.dest) if isdir(options.dest) and len(os.listdir(options.dest)) > 0 and not options.overwrite: if raw_input("Destination directory not empty! Continue? [yn]: ") != "y": sys.exit(1) for src, dest in resolve(options, theme, files): if not isdir(dirname(dest)): os.makedirs(dirname(dest)) if options.overwrite or not exists(dest): write(src, dest) event.create(dest) else: event.skip(dest) log.info("Created your fresh new blog at %r. Enjoy!", options.dest)
def generate(self, conf, env, data): tt = env.engine.fromfile(env, self.template) keyfunc = lambda k: () if '/:year' in self.path: keyfunc = lambda k: (k.year, ) if '/:month' in self.path: keyfunc = lambda k: (k.year, k.imonth) if '/:day' in self.path: keyfunc = lambda k: (k.year, k.imonth, k.iday) for next, curr, prev in neighborhood( groupby(data['entrylist'], keyfunc)): salt, group = '-'.join(str(i) for i in curr[0]), list(curr[1]) modified = memoize('archive-' + salt, hash(*group)) or any( e.modified for e in group) if prev: prev = link(u'/'.join('%02i' % i for i in prev[0]), expand(self.path, prev[1][0])) if next: next = link(u'/'.join('%02i' % i for i in next[0]), expand(self.path, next[1][0])) route = expand(self.path, group[0]) path = joinurl(conf['output_dir'], route) # an object storing year, zero-padded month and day as attributes (may be None) key = type( 'Archive', (object, ), dict( zip(('year', 'month', 'day'), map(lambda x: '%02i' % x if x else None, keyfunc(group[0])))))() if isfile(path) and not (modified or tt.modified or env.modified or conf.modified): event.skip('archive', path) continue html = tt.render(conf=conf, env=union(env, entrylist=group, type='archive', prev=prev, curr=link(route), next=next, num_entries=len(group), route=route, archive=key)) yield html, path
def generate(self, request): """Creates paged listing by tag.""" ipp = self.items_per_page tt = self.env.engine.fromfile(self.template) entrylist = [ entry for entry in request['entrylist'] if not entry.draft ] for tag in self.tags: entrylist = [entry for entry in self.tags[tag]] paginator = paginate(entrylist, ipp, salt=tag, orphans=self.conf['default_orphans']) route = expand(self.path, {'name': tag}).rstrip('/') for (next, curr, prev), entries, has_changed in paginator: # e.g.: curr = /page/3, next = /page/2, prev = /page/4 next = None if next is None \ else link(u'« Next', expand(self.path, {'name': tag}).rstrip('/')) if next == 1 \ else link(u'« Next', expand(self.pagination, {'name': tag, 'num': next})) curr = link(curr, expand(self.path, {'name': tag})) if curr == 1 \ else link(expand(self.pagination, {'num': curr, 'name': tag})) prev = None if prev is None \ else link(u'Previous »', expand(self.pagination, {'name': tag, 'num': prev})) path = joinurl(self.conf['output_dir'], curr, 'index.html') if exists(path) and not has_changed and not tt.has_changed: event.skip(path) continue html = tt.render(conf=self.conf, env=union(self.env, entrylist=entries, type='tag', prev=prev, curr=curr, next=next, tag=tag, items_per_page=ipp, num_entries=len(entrylist), route=route)) yield html, path
def generate(self, conf, env, data): pathes, entrylist = set(), data[self.type] unmodified = not env.modified and not conf.modified for i, entry in enumerate(entrylist): if entry.hasproperty('permalink'): path = joinurl(conf['output_dir'], entry.permalink) else: path = joinurl(conf['output_dir'], expand(self.path, entry)) if isfile(path) and path in pathes: try: os.remove(path) finally: other = [e.filename for e in entrylist if e is not entry and e.permalink == entry.permalink][0] log.error("title collision %s caused by %s and %s", entry.permalink, entry.filename, other) raise SystemExit pathes.add(path) next, prev = self.next(entrylist, i), self.prev(entrylist, i) # per-entry template tt = env.engine.fromfile(env, entry.props.get('layout', self.template)) if all([isfile(path), unmodified, not tt.modified, not entry.modified, not modified(*references(entry))]): event.skip(self.name, path) else: html = tt.render(conf=conf, entry=entry, env=union(env, entrylist=[entry], type=self.__class__.__name__.lower(), prev=prev, next=next, route=expand(self.path, entry))) yield html, path # check if any resources need to be moved if entry.hasproperty('copy'): for res_src in entry.resources: res_dest = join(dirname(path), basename(res_src)) # Note, presence of res_src check in FileReader.getresources if isfile(res_dest) and getmtime(res_dest) > getmtime(res_src): event.skip(self.name, res_dest) continue try: fp = io.open(res_src, 'rb') # use mkfile rather than yield so different ns can be specified (and filtered by sitemap) mkfile(fp, res_dest, ns='resource', force=env.options.force, dryrun=env.options.dryrun) except IOError as e: log.warn("Failed to copy resource '%s' whilst processing '%s' (%s)" % (res_src, entry.filename, e.strerror))
def generate(self, conf, env, data): for lang in env.langs: ipp = self.items_per_page tt = env.engine.fromfile(self.template) entrylist = [] for entry in data['entrylist']: try: e = entry_for_lang(data, lang, entry) entrylist.append(e) except TranslationNotFound: pass#entrylist.append(entry) paginator = paginate(entrylist, ipp, self.path, conf.default_orphans) route = '/blog/' for (next, curr, prev), entries, modified in paginator: # curr = current page, next = newer pages, prev = older pages if next is None: pass elif next == 1: next = link(u'« Next', expand(self.path.rstrip('/'), {'lang':lang})) else: next = link(u'« Next', expand(self.pagination, {'num': next,'lang': lang})) if next: next.href = strip_default_lang(next.href, self.conf) curr = link(curr, self.path) if curr == 1 \ else link(expand(self.pagination, {'num': curr,'lang': lang})) curr.href = strip_default_lang(curr.href, self.conf) prev = None if prev is None \ else link(u'Previous »', expand(self.pagination, {'num': prev,'lang': lang})) if prev: prev.href = strip_default_lang(prev.href, self.conf) path = joinurl(conf['output_dir'], expand(curr.href, {'lang': lang}), 'index.html') path = strip_default_lang(path, self.conf) env['lang'] = lang env['active_route'] = route if isfile(path) and not (modified or tt.modified or env.modified or conf.modified): event.skip(path) continue html = tt.render(conf=conf, env=union(env, entrylist=entries, type='index', prev=prev, curr=curr, next=next, items_per_page=ipp, num_entries=len(entrylist), route=route)) yield html, path
def generate(self, conf, env, data): for lang in env.langs: entrylist = [] for entry in data[self.type]: try: e = entry_for_lang(data, lang, entry) entrylist.append(e) except TranslationNotFound: entrylist.append(entry) unmodified = not env.modified and not conf.modified for i, entry in enumerate(entrylist): route = strip_default_lang(expand(self.path, entry), self.conf) if entry.hasproperty('permalink'): path = joinurl(conf['output_dir'], entry.permalink) elif lang == self.conf.lang_code: path = joinurl(self.conf['output_dir'], route, '/') entry.permalink = route else: path = joinurl(self.conf['output_dir'], expand(self.path, entry)) entry.permalink = route if path.endswith('/'): path = joinurl(path, 'index.html') next, prev = self.next(entrylist, i), self.prev(entrylist, i) env['lang'] = lang env['active_route'] = route # per-entry template tt = env.engine.fromfile(entry.props.get('layout', self.template)) if all([isfile(path), unmodified, not tt.modified, not entry.modified, not modified(*references(entry))]): event.skip(self.name, path) continue html = tt.render(conf=conf, entry=entry, env=union(env, entrylist=[entry], type=self.__class__.__name__.lower(), prev=prev, next=next, route=expand( self.path, entry))) yield html, path
def write(self, src, dest, force=False, dryrun=False): dest = dest.replace(splitext(src)[-1], self.target) if not force and isfile(dest) and getmtime(dest) > getmtime(src): return event.skip(ns, dest) if isinstance(self.cmd, basestring): self.cmd = [self.cmd, ] tt = time.time() fd, path = mkstemp(dir=core.cache.cache_dir) # make destination group/world-readable as other files from Acrylamid os.chmod(path, os.stat(path).st_mode | stat.S_IRGRP | stat.S_IROTH) try: res = helpers.system(self.cmd + [src]) except (OSError, AcrylamidException) as e: if isfile(dest): os.unlink(dest) log.exception('%s: %s' % (e.__class__.__name__, e.args[0])) else: with os.fdopen(fd, 'w') as fp: fp.write(res) with io.open(path, 'rb') as fp: mkfile(fp, dest, time.time()-tt, ns, force, dryrun) finally: os.unlink(path)
def write(self, src, dest, force=False, dryrun=False): dest = dest.replace(self.ext, self.target) if not force and isfile(dest) and getmtime(dest) > getmtime(src): return event.skip(dest) if isinstance(self.cmd, basestring): self.cmd = [self.cmd, ] tt = time.time() fd, path = mkstemp(dir=core.cache.cache_dir) try: res = helpers.system(self.cmd + [src]) except (OSError, AcrylamidException) as e: if isfile(dest): os.unlink(dest) log.warn('%s: %s' % (e.__class__.__name__, e.args[0])) else: with os.fdopen(fd, 'w') as fp: fp.write(res) with io.open(path, 'rb') as fp: mkfile(fp, dest, ctime=time.time()-tt, force=force, dryrun=dryrun) finally: os.unlink(path)
def write(self, src, dest, force=False, dryrun=False): if not force and isfile(dest) and getmtime(dest) > getmtime(src): return event.skip(dest) with io.open(src, 'rb') as fp: mkfile(fp, dest, force=force, dryrun=dryrun, mode="b")
def generate(self, conf, env, data): entrylist = data['entrylist'] entrylist = list(entrylist)[0:self.num_entries] tt = env.engine.fromfile('%s.xml' % self.type) path = joinurl(conf['output_dir'], self.route) modified = any(entry.modified for entry in entrylist) if isfile(path) and not (conf.modified or env.modified or tt.modified or modified): event.skip(self.name, path) raise StopIteration updated = entrylist[0].date if entrylist else datetime.utcnow() html = tt.render(conf=conf, env=union(env, route=self.route, updated=updated, entrylist=entrylist)) yield html, path
def generate(self, request): tt = self.env.engine.fromfile(self.template) pathes = set() nondrafts, drafts = [], [] for entry in request[self.type]: if not entry.draft: nondrafts.append(entry) else: drafts.append(entry) for isdraft, entrylist in enumerate([nondrafts, drafts]): has_changed = self.has_changed(entrylist, 'draft' if isdraft else 'entry') for i, entry in enumerate(entrylist): if entry.hasproperty('permalink'): path = joinurl(self.conf['output_dir'], entry.permalink) else: path = joinurl(self.conf['output_dir'], expand(self.path, entry)) if path.endswith('/'): path = joinurl(path, 'index.html') if isfile(path) and path in pathes: try: os.remove(path) finally: f = lambda e: e is not entry and e.permalink == entry.permalink raise AcrylamidException("title collision %r in %r with %r." % (entry.permalink, entry.filename, filter(f, entrylist)[0].filename)) pathes.add(path) next = self.next(entrylist, i) if not isdraft else None prev = self.prev(entrylist, i) if not isdraft else None if isfile(path) and not any([has_changed, entry.has_changed, tt.has_changed]): event.skip(path) continue route = expand(self.path, entry) html = tt.render(conf=self.conf, entry=entry, env=union(self.env, entrylist=[entry], type=self.__class__.__name__.lower(), prev=prev, next=next, route=route)) yield html, path
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 generate(self, conf, env, data): entrylist = data['entrylist'] tt = env.engine.fromfile(env, self.template) path = joinurl(conf['output_dir'], self.path, 'index.html') if exists(path) and not (conf.modified or env.modified or tt.modified): event.skip('article', path) raise StopIteration articles = {} for entry in entrylist: articles.setdefault((entry.year, entry.imonth), []).append(entry) html = tt.render(conf=conf, articles=articles, env=union(env, num_entries=len(entrylist), route=self.path)) yield html, path
def generate(self, request): path = joinurl(self.conf['output_dir'], self.path) sm = Map() if exists(path) and not self.has_changed: event.skip(path) raise StopIteration for fname in self.files: url = join(self.conf['www_root'], fname.replace(self.conf['output_dir'], '')) if self.regex.match(url): sm.add(url.rstrip('index.html'), getmtime(fname), priority=1.0) else: sm.add(url.rstrip('index.html'), getmtime(fname), changefreq='weekly') yield sm.read(), path
def generate(self, request): ipp = self.items_per_page tt = self.env.engine.fromfile(self.template) entrylist = [ entry for entry in request['entrylist'] if not entry.draft ] paginator = paginate(entrylist, ipp, orphans=self.conf['default_orphans']) route = self.path for (next, curr, prev), entries, has_changed in paginator: # curr = current page, next = newer pages, prev = older pages next = None if next is None \ else link(u'« Next', self.path.rstrip('/')) if next == 1 \ else link(u'« Next', expand(self.pagination, {'num': next})) curr = link(curr, self.path) if curr == 1 \ else link(expand(self.pagination, {'num': curr})) prev = None if prev is None \ else link(u'Previous »', expand(self.pagination, {'num': prev})) path = joinurl(self.conf['output_dir'], curr.href, 'index.html') if exists(path) and not has_changed and not tt.has_changed: event.skip(path) continue html = tt.render(conf=self.conf, env=union(self.env, entrylist=entries, type='index', prev=prev, curr=curr, next=next, items_per_page=ipp, num_entries=len(entrylist), route=route)) 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') if exists(path) and not filter(lambda e: e.has_changed, entrylist): if 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 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') if exists(path) and not filter(lambda e: e.has_changed, entrylist): if not tt.has_changed: event.skip(path) raise StopIteration updated = entrylist[0].date if entrylist else datetime.now() html = tt.render(conf=self.conf, env=union(self.env, path=self.path, updated=updated, entrylist=entrylist)) yield html, path
def generate(self, request): tt = self.env.engine.fromfile(self.template) entrylist = request[self.type] pathes = set() has_changed = self.has_changed(entrylist) for i, entry in enumerate(entrylist): if entry.hasproperty('permalink'): path = joinurl(self.conf['output_dir'], entry.permalink) else: path = joinurl(self.conf['output_dir'], expand(self.path, entry)) if path.endswith('/'): path = joinurl(path, 'index.html') if isfile(path) and path in pathes: try: os.remove(path) finally: f = lambda e: e is not entry and e.permalink == entry.permalink raise AcrylamidException("title collision %r in %r with %r." % (entry.permalink, entry.filename, filter(f, entrylist)[0].filename)) next, prev = self.next(entrylist, i), self.prev(entrylist, i) # detect collisions pathes.add(path) if isfile(path) and not any([has_changed, entry.has_changed, tt.has_changed]): event.skip(path) continue route = expand(self.path, entry) html = tt.render(conf=self.conf, entry=entry, env=union(self.env, entrylist=[entry], type=self.__class__.__name__.lower(), prev=prev, next=next, route=route)) yield html, path
def generate(self, request): entrylist = filter(lambda e: not e.draft, request['entrylist'])[:self.num_entries] tt = self.env.jinja2.get_template('%s.xml' % self.__class__.__name__.lower()) path = joinurl(self.conf['output_dir'], self.path) if not filter(lambda e: path.endswith(e), ['.xml', '.html']): path = joinurl(path, 'index.html') if exists(path) and not filter(lambda e: e.has_changed, entrylist): if not tt.has_changed: event.skip(path) raise StopIteration updated=entrylist[0].date if entrylist else datetime.now() html = tt.render(conf=self.conf, env=union(self.env, updated=updated, entrylist=entrylist)) yield html, path
def generate(self, request): """Creates paged listing by tag.""" ipp = self.items_per_page tt = self.env.jinja2.get_template('main.html') entrylist = [entry for entry in request['entrylist'] if not entry.draft] for tag in self.tags: entrylist = [entry for entry in self.tags[tag]] paginator = paginate(entrylist, ipp, salt=tag, orphans=self.conf['default_orphans']) for (next, curr, prev), entries, has_changed in paginator: # e.g.: curr = /page/3, next = /page/2, prev = /page/4 if next == 1: next = expand(self.path, {'name': tag}).rstrip('/') elif next > 1: next = expand(self.pagination, {'name': tag, 'num': next}) if curr == 1: curr = expand(self.path, {'name': tag}) elif curr > 1: curr = expand(self.pagination, {'num': curr, 'name': tag}) if prev is not None: prev = expand(self.pagination, {'name': tag, 'num': prev}) path = joinurl(self.conf['output_dir'], curr, 'index.html') if exists(path) and not has_changed and not tt.has_changed: event.skip(path) continue html = tt.render(conf=self.conf, env=union(self.env, entrylist=entries, type='tag', prev=prev, curr=curr, next=next, items_per_page=ipp, num_entries=len(entrylist))) yield html, path
def generate(self, request): tt = self.env.engine.fromfile(self.template) entrylist = request[self.type] pathes = set() has_changed = self.has_changed(entrylist) for i, entry in enumerate(entrylist): if entry.hasproperty('permalink'): path = joinurl(self.conf['output_dir'], entry.permalink) else: path = joinurl(self.conf['output_dir'], expand(self.path, entry)) if path.endswith('/'): path = joinurl(path, 'index.html') if isfile(path) and path in pathes: try: os.remove(path) finally: f = lambda e: e is not entry and e.permalink == entry.permalink raise AcrylamidException("title collision %r in %r with %r." % (entry.permalink, entry.filename, filter(f, entrylist)[0].filename)) next, prev = self.next(entrylist, i), self.prev(entrylist, i) # detect collisions pathes.add(path) if isfile(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=self.__class__.__name__.lower(), prev=prev, next=next)) yield html, path
def needs_rebuild(self, bundle, env): if super(TimestampUpdater, self).needs_rebuild(bundle, env): return True try: dest = getmtime(bundle.resolve_output(env)) except OSError: return self.new.add(bundle) or True src = [s[1] for s in bundle.resolve_contents(env)] deps = bundle.resolve_depends(env) for item in src + deps: self.used.add(item) if any(getmtime(deps) > dest for deps in src + deps): return True event.skip('assets', bundle.resolve_output(env)) return False
def generate(self, conf, env, data): tt = env.engine.fromfile(env, self.template) keyfunc = lambda k: ( ) if '/:year' in self.path: keyfunc = lambda k: (k.year, ) if '/:month' in self.path: keyfunc = lambda k: (k.year, k.imonth) if '/:day' in self.path: keyfunc = lambda k: (k.year, k.imonth, k.iday) for next, curr, prev in neighborhood(groupby(data['entrylist'], keyfunc)): salt, group = '-'.join(str(i) for i in curr[0]), list(curr[1]) modified = memoize('archive-' + salt, hash(*group)) or any(e.modified for e in group) if prev: prev = link(u'/'.join('%02i' % i for i in prev[0]), expand(self.path, prev[1][0])) if next: next = link(u'/'.join('%02i' % i for i in next[0]), expand(self.path, next[1][0])) route = expand(self.path, group[0]) path = joinurl(conf['output_dir'], route) # an object storing year, zero-padded month and day as attributes (may be None) key = type('Archive', (object, ), dict(zip(('year', 'month', 'day'), map(lambda x: '%02i' % x if x else None, keyfunc(group[0])) )))() if isfile(path) and not (modified or tt.modified or env.modified or conf.modified): event.skip('archive', path) continue html = tt.render(conf=conf, env=union(env, entrylist=group, type='archive', prev=prev, curr=link(route), next=next, num_entries=len(group), route=route, archive=key)) yield html, path
def generate(self, request): """Creates paged listing by tag.""" ipp = self.items_per_page tt = self.env.engine.fromfile(self.template) entrylist = [entry for entry in request['entrylist'] if not entry.draft] for tag in self.tags: entrylist = [entry for entry in self.tags[tag]] paginator = paginate(entrylist, ipp, salt=tag, orphans=self.conf['default_orphans']) route = expand(self.path, {'name': tag}).rstrip('/') for (next, curr, prev), entries, has_changed in paginator: # e.g.: curr = /page/3, next = /page/2, prev = /page/4 next = None if next is None \ else link(u'« Next', expand(self.path, {'name': tag}).rstrip('/')) if next == 1 \ else link(u'« Next', expand(self.pagination, {'name': tag, 'num': next})) curr = link(curr, expand(self.path, {'name': tag})) if curr == 1 \ else link(expand(self.pagination, {'num': curr, 'name': tag})) prev = None if prev is None \ else link(u'Previous »', expand(self.pagination, {'name': tag, 'num': prev})) path = joinurl(self.conf['output_dir'], curr, 'index.html') if exists(path) and not has_changed and not tt.has_changed: event.skip(path) continue html = tt.render(conf=self.conf, env=union(self.env, entrylist=entries, type='tag', prev=prev, curr=curr, next=next, tag=tag, items_per_page=ipp, num_entries=len(entrylist), route=route)) yield html, path
def generate(self, conf, env, data): pathes, entrylist = set(), data[self.type] unmodified = not env.modified and not conf.modified for i, entry in enumerate(entrylist): if entry.hasproperty('permalink'): path = joinurl(conf['output_dir'], entry.permalink) else: path = joinurl(conf['output_dir'], expand(self.path, entry)) if isfile(path) and path in pathes: try: os.remove(path) finally: other = [ e.filename for e in entrylist if e is not entry and e.permalink == entry.permalink ][0] log.error("title collision %s caused by %s and %s", entry.permalink, entry.filename, other) raise SystemExit pathes.add(path) next, prev = self.next(entrylist, i), self.prev(entrylist, i) # per-entry template tt = env.engine.fromfile(env, entry.props.get('layout', self.template)) if all([ isfile(path), unmodified, not tt.modified, not entry.modified, not modified(*references(entry)) ]): event.skip(self.name, path) else: html = tt.render(conf=conf, entry=entry, env=union( env, entrylist=[entry], type=self.__class__.__name__.lower(), prev=prev, next=next, route=expand(self.path, entry))) yield html, path # check if any resources need to be moved if entry.hasproperty('copy'): for res_src in entry.resources: res_dest = join(dirname(path), basename(res_src)) # Note, presence of res_src check in FileReader.getresources if isfile(res_dest ) and getmtime(res_dest) > getmtime(res_src): event.skip(self.name, res_dest) continue try: fp = io.open(res_src, 'rb') # use mkfile rather than yield so different ns can be specified (and filtered by sitemap) mkfile(fp, res_dest, ns='resource', force=env.options.force, dryrun=env.options.dryrun) except IOError as e: log.warn( "Failed to copy resource '%s' whilst processing '%s' (%s)" % (res_src, entry.filename, e.strerror))
def write(self, src, dest, force=False, dryrun=False): if not force and not self.modified(src, dest): return event.skip(ns, dest) mkfile(self.generate(src, dest), dest, ns=ns, force=force, dryrun=dryrun)