def summarize(): summarize = get_filters()['summarize'](conf, env, 'summarize') examples = [('Hello World', 'Hello World'), # a real world example ('<p>Hello World, you have to click this link because</p>', '<p>Hello World, you have to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>'), ('<p>Hel­lo Wor­ld, you have to click this link because</p>', # now with HTML entities '<p>Hel­lo Wor­ld, you have to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>'), ('Hello<br />', 'Hello<br />'), ('<p>Hello World, you have<br /> to <br /> click<br /> this<br /> link...</p>', '<p>Hello World, you have<br /> to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>'), ('Hello World, you have to click this link because', 'Hello World, you have to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span>')] for text, result in examples: assert summarize.transform(text, Entry(), '5') == result conf['summarize_mode'] = 0 summarize = get_filters()['summarize'](conf, env, 'summarize') assert summarize.transform(( '<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod ' 'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam</p>' '\n' '<p>Here it breaks ...</p>'), Entry(), '20') == ( '<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod ' 'tempor incididunt ut labore et dolore magna aliqua. Ut ' '<span>…<a href="/foo/" class="continue">continue</a>.</span></p>')
def headoffset(): h1 = get_filters()['h1'](conf, env, 'h1') examples = [ ('<h1>Hello</h1>', '<h2>Hello</h2>'), ('<h2>World</h2>', '<h3>World</h3>'), ('<h1 class="foo bar">spam</h1>', '<h2 class="foo bar">spam</h2>'), ('<h1 class="foo" id="baz">spam</h1>', '<h2 class="foo" id="baz">spam</h2>'), ] for test, result in examples: assert h1.transform(test, None) == result h5 = get_filters()['h5'](conf, env, 'h5') assert h5.transform('<h3>eggs</h3>', '<h6>eggs</h6>')
def test_hyphenate(self): hyph = get_filters()['Hyphenate'](conf, env, 'Hyphenate') hyph.transform('Airplane', Entry('en')) == 'Airplane' hyph.transform('supercalifragilisticexpialidocious', Entry('en')) == \ '­'.join(['su', 'per', 'cal', 'ifrag', 'ilis', 'tic', 'ex', 'pi', 'ali', 'do', 'cious']) hyph = get_filters()['Hyphenate'](conf, env, 'Hyphenate') assert hyph.transform('Flugzeug', Entry('de'), '8') == 'Flugzeug' assert hyph.transform('Flugzeug', Entry('de'), '7') == 'Flug­zeug' # test unsupported assert hyph.transform('Flugzeug', Entry('foo'), '8') == 'Flugzeug'
def test_hyphenation(self): hyph = get_filters()['Hyphenate']('Hyphenate') self.assertEqual(hyph.transform('Airplane', Entry('en')), 'Airplane') self.assertEqual(hyph.transform('supercalifragilisticexpialidocious', Entry('en')), '­'.join(['su', 'per', 'cal', 'ifrag', 'ilis', 'tic', 'ex', 'pi', 'ali', 'do', 'cious'])) hyph = get_filters()['Hyphenate']('Hyphenate') self.assertEqual(hyph.transform('Flugzeug', Entry('de'), '8'), 'Flugzeug') self.assertEqual(hyph.transform('Flugzeug', Entry('de'), '7'), 'Flug­zeug') # test unsupported self.assertEqual(hyph.transform('Flugzeug', Entry('foo'), '8'), 'Flugzeug')
def mako(): mako = get_filters()['Mako'](conf, env, 'Mako') e = Entry('de') e.filename = '1' assert mako.transform('${entry.lang}', Entry('de')) == 'de' assert mako.transform("${ 'which which' | system }", e) == '/usr/bin/which'
def intro(): intro = get_filters()['intro'](conf, env, 'intro') examples = [('Hello World', ''), ('<p>First</p>', '<p>First</p><span>…<a href="/foo/" class="continue">continue</a>.</span>'), ('<p>First</p><p>Second</p>', '<p>First</p><span>…<a href="/foo/" class="continue">continue</a>.</span>')] for text, result in examples: assert intro.transform(text, Entry(), '1') == result
def strip(): strip = get_filters()['strip'](conf, env, 'strip') examples = [('<em>Foo</em>', 'Foo'), ('<a href="#">Bar</a>', 'Bar'), ('<video src="#" />', '')] for text, result in examples: assert strip.transform(text, Entry()) == result assert strip.transform('<pre>...</pre>', Entry(), 'pre') == '' assert strip.transform('<pre><</pre>', Entry(), 'pre') == ''
def strip(): strip = get_filters()['strip'](conf, env, 'strip') examples = [ ('<em>Foo</em>', 'Foo'), ('<a href="#">Bar</a>', 'Bar'), ('<video src="#" />', '')] for text, result in examples: assert strip.transform(text, Entry()) == result assert strip.transform('<pre>...</pre>', Entry(), 'pre') == '' assert strip.transform('<pre><</pre>', Entry(), 'pre') == ''
def acronyms(): acronyms = get_filters()['Acronyms'](conf, env, 'Acronyms') abbr = lambda abbr, expl: '<abbr title="%s">%s</abbr>' % (expl, abbr) examples = [('CGI', abbr('CGI', 'Common Gateway Interface')), ('IMDB', abbr('IMDB', 'Internet Movie Database')), ('IMDb', abbr('IMDb', 'Internet Movie Database')), ('PHP5', abbr('PHP5', 'Programmers Hate PHP ;-)')), ('TEST', 'TEST')] for test, result in examples: assert acronyms.transform(test, None) == result
def acronyms(): acronyms = get_filters()['Acronyms'](conf, env, 'Acronyms') abbr = lambda abbr, expl: '<abbr title="%s">%s</abbr>' % (expl, abbr) examples = [ ('CGI', abbr('CGI', 'Common Gateway Interface')), ('IMDB', abbr('IMDB', 'Internet Movie Database')), ('IMDb', abbr('IMDb', 'Internet Movie Database')), ('PHP5', abbr('PHP5', 'Programmers Hate PHP ;-)')), ('TEST', 'TEST') ] for test, result in examples: assert acronyms.transform(test, None) == result
def liquid(): liquid = get_filters()['liquid'](conf, env, 'liquid') # liquid block recognition text = '\n'.join([ "{% tag %}", "", "Foo Bar.", "", "{% endtag %}" ]) rv = liquid.block("tag").match(text) assert rv.group(1) == "" assert rv.group(2) == "\nFoo Bar.\n" # multiple, not nested blocks text = '\n'.join([ "{% block %}", "", "Foo Bar.", "", "{% endblock %}", "", "{% block %}", "", "Baz.", "", "{% endblock %}" ]) rv = tuple(liquid.block("block").finditer(text)) assert len(rv) == 2 x, y = rv assert x.group(2).strip() == "Foo Bar." assert y.group(2).strip() == "Baz." # self-closing block text = '{% block a few args %}' rv = liquid.block("block").match(text) assert rv is not None assert rv.group(1) == 'a few args' assert rv.group(2) is None # blockquote examples = [ ('{% blockquote Author, Source http://example.org/ Title %}\nFoo Bar\n{% endblockquote %}', '<blockquote><p>Foo Bar</p><footer><strong>Author, Source</strong> <cite><a href="http://example.org/">Title</a></cite></footer></blockquote>'), ] for text, result in examples: assert liquid.transform(text, Entry()) == result
def test_works(self): summarize = get_filters()['summarize'](conf, env, 'summarize') examples = [('Hello World', 'Hello World'), # a real world example ('<p>Hello World, you have to click this link because</p>', '<p>Hello World, you have to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>'), ('<p>Hel­lo Wor­ld, you have to click this link because</p>', # now with HTML entities '<p>Hel­lo Wor­ld, you have to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>'), ('Hello<br />', 'Hello<br />'), ('<p>Hello World, you have<br /> to <br /> click<br /> this<br /> link...</p>', '<p>Hello World, you have<br /> to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>')] for text, result in examples: assert summarize.transform(text, Entry(), '5') == result
def test_works(self): summarize = get_filters()['summarize'](conf, env, 'summarize') examples = [('Hello World', 'Hello World'), # a real world example ('<p>Hello World, you have to click this link because</p>', '<p>Hello World, you have to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>'), ('<p>Hel­lo Wor­ld, you have to click this link because</p>', # now with HTML entities '<p>Hel­lo Wor­ld, you have to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>'), ('Hello<br />', 'Hello<br />'), ('<p>Hello World, you have<br /> to <br /> click<br /> this<br /> link...</p>', '<p>Hello World, you have<br /> to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span></p>'), ('Hello World, you have to click this link because', 'Hello World, you have to <span>…<a href="/foo/" '+ \ 'class="continue">continue</a>.</span>')] for text, result in examples: assert summarize.transform(text, Entry(), '5') == result
def compile(conf, env, force=False, **options): """The compilation process. Current API: #. when we require context #. when we called an event New API: #. before we start with view Initialization #. after we initialized views #. before we require context #. after we required context #. before we template #. before we write a file #. when we called an event #. when we finish """ # time measurement ctime = time.time() # populate env and corrects some conf things request = initialize(conf, env) # load pages/entries and store them in env entrylist, pages = readers.load(conf) env.globals['entrylist'] = entrylist env.globals['pages'] = pages # XXX translations should be moved out of core env.globals['translations'] = translations = [] if force: # acrylamid compile -f cache.clear() # here we store all found filter and their aliases ns = defaultdict(set) # get available filter list, something like with obj.get-function # list = [<class head_offset.Headoffset at 0x1014882c0>, <class html.HTML at 0x101488328>,...] aflist = filters.get_filters() # ... and get all configured views _views = views.get_views() # filters found in all entries, views and conf.py found = sum((x.filters for x in entrylist+pages+_views), []) + request['conf']['filters'] for val in found: # first we for `no` and get the function name and arguments f = val[2:] if val.startswith('no') else val fname, fargs = f.split('+')[:1][0], f.split('+')[1:] try: # initialize the filter with its function name and arguments fx = aflist[fname](conf, env, val, *fargs) if val.startswith('no'): fx = filters.disable(fx) except ValueError: try: fx = aflist[val.split('+')[:1][0]](conf, env, val, *fargs) except ValueError: raise AcrylamidException('no such filter: %s' % val) ns[fx].add(val) for entry in entrylist + pages: for v in _views: # a list that sorts out conflicting and duplicated filters flst = filters.FilterList() # filters found in this specific entry plus views and conf.py found = entry.filters + v.filters + request['conf']['filters'] for fn in found: fx, _ = next((k for k in ns.iteritems() if fn in k[1])) if fx not in flst: flst.append(fx) # sort them ascending because we will pop within filters.add entry.filters.add(sorted(flst, key=lambda k: (-k.priority, k.name)), context=v.__class__.__name__) # lets offer a last break to populate tags or so # XXX this API component needs a review for v in _views: env = v.context(env, {'entrylist': entrylist, 'pages': pages, 'translations': translations}) # now teh real thing! for v in _views: # XXX the entry should automatically determine its caller (using # some sys magic to recursively check wether the calling class is # derieved from `View`.) for entry in entrylist + pages + translations: entry.context = v.__class__.__name__ request['pages'], request['translations'] = pages, translations request['entrylist'] = filter(v.condition, entrylist) tt = time.time() for html, path in v.generate(request): helpers.mkfile(html, path, time.time()-tt, **options) tt = time.time() # remove abandoned cache files cache.shutdown() # print a short summary log.info('%i new, %i updated, %i skipped [%.2fs]', event.count('create'), event.count('update'), event.count('identical') + event.count('skip'), time.time() - ctime)
def test_jinja2(self): jinja2 = get_filters()['Jinja2']('Jinja2') self.assertEqual(jinja2.transform('{{ entry.lang }}', Entry('de')), 'de') self.assertEqual(jinja2.transform("{{ 'which which' | system }}", None), '/usr/bin/which')
def compile(conf, env): """The compilation process.""" hooks.initialize(conf, env) hooks.run(conf, env, 'pre') if env.options.force: cache.clear(conf.get('cache_dir')) # time measurement ctime = time.time() # populate env and corrects some conf things data = initialize(conf, env) # load pages/entries and store them in env rv = dict( zip(['entrylist', 'pages', 'translations', 'drafts'], map(HashableList, readers.load(conf)))) entrylist, pages = rv['entrylist'], rv['pages'] translations, drafts = rv['translations'], rv['drafts'] # load references refs.load(entrylist, pages, translations, drafts) data.update(rv) env.globals.update(rv) # here we store all found filter and their aliases ns = defaultdict(set) # [<class head_offset.Headoffset at 0x1014882c0>, <class html.HTML at 0x101488328>,...] aflist = filters.get_filters() # ... and get all configured views _views = views.get_views() # filters found in all entries, views and conf.py (skip translations, has no items) found = sum((x.filters for x in chain(entrylist, pages, drafts, _views, [conf])), []) for val in found: # first we for `no` and get the function name and arguments f = val[2:] if val.startswith('no') else val fname, fargs = f.split('+')[:1][0], f.split('+')[1:] try: # initialize the filter with its function name and arguments fx = aflist[fname](conf, env, val, *fargs) if val.startswith('no'): fx = filters.disable(fx) except ValueError: try: fx = aflist[val.split('+')[:1][0]](conf, env, val, *fargs) except ValueError: raise AcrylamidException('no such filter: %s' % val) ns[fx].add(val) # include actual used filters to trigger modified state env.filters = HashableList(iterkeys(ns)) for entry in chain(entrylist, pages, drafts): for v in _views: # a list that sorts out conflicting and duplicated filters flst = filters.FilterList() # filters found in this specific entry plus views and conf.py found = entry.filters + v.filters + data['conf']['filters'] for fn in found: fx, _ = next((k for k in iteritems(ns) if fn in k[1])) if fx not in flst: flst.append(fx) # sort them ascending because we will pop within filters.add entry.filters.add(sorted(flst, key=lambda k: (-k.priority, k.name)), context=v) # lets offer a last break to populate tags and such for v in _views: env = v.context(conf, env, data) # now teh real thing! for v in _views: for entry in chain(entrylist, pages, translations, drafts): entry.context = v for var in 'entrylist', 'pages', 'translations', 'drafts': data[var] = HashableList(filter(v.condition, locals()[var])) \ if v.condition else locals()[var] tt = time.time() for buf, path in v.generate(conf, env, data): try: helpers.mkfile(buf, path, time.time() - tt, ns=v.name, force=env.options.force, dryrun=env.options.dryrun) except UnicodeError: log.exception(path) finally: buf.close() tt = time.time() # copy modified/missing assets to output assets.compile(conf, env) # wait for unfinished hooks hooks.shutdown() # run post hooks (blocks) hooks.run(conf, env, 'post') # save conf/environment hash and new/changed/unchanged references helpers.memoize('Configuration', hash(conf)) helpers.memoize('Environment', hash(env)) refs.save() # remove abandoned cache files cache.shutdown() # print a short summary log.info('%i new, %i updated, %i skipped [%.2fs]', event.count('create'), event.count('update'), event.count('identical') + event.count('skip'), time.time() - ctime)
def compile(conf, env): """The compilation process.""" if env.options.force: cache.clear(conf.get("cache_dir")) # time measurement ctime = time.time() # populate env and corrects some conf things data = initialize(conf, env) # load pages/entries and store them in env rv = dict(zip(["entrylist", "pages", "translations", "drafts"], map(HashableList, readers.load(conf)))) entrylist, pages = rv["entrylist"], rv["pages"] translations, drafts = rv["translations"], rv["drafts"] # load references refs.load(entrylist, pages, translations, drafts) data.update(rv) env.globals.update(rv) # here we store all found filter and their aliases ns = defaultdict(set) # [<class head_offset.Headoffset at 0x1014882c0>, <class html.HTML at 0x101488328>,...] aflist = filters.get_filters() # ... and get all configured views _views = views.get_views() # filters found in all entries, views and conf.py (skip translations, has no items) found = sum((x.filters for x in chain(entrylist, pages, drafts, _views, [conf])), []) for val in found: # first we for `no` and get the function name and arguments f = val[2:] if val.startswith("no") else val fname, fargs = f.split("+")[:1][0], f.split("+")[1:] try: # initialize the filter with its function name and arguments fx = aflist[fname](conf, env, val, *fargs) if val.startswith("no"): fx = filters.disable(fx) except ValueError: try: fx = aflist[val.split("+")[:1][0]](conf, env, val, *fargs) except ValueError: raise AcrylamidException("no such filter: %s" % val) ns[fx].add(val) # include actual used filters to trigger modified state env.filters = HashableList(ns.keys()) for entry in chain(entrylist, pages, drafts): for v in _views: # a list that sorts out conflicting and duplicated filters flst = filters.FilterList() # filters found in this specific entry plus views and conf.py found = entry.filters + v.filters + data["conf"]["filters"] for fn in found: fx, _ = next((k for k in ns.iteritems() if fn in k[1])) if fx not in flst: flst.append(fx) # sort them ascending because we will pop within filters.add entry.filters.add(sorted(flst, key=lambda k: (-k.priority, k.name)), context=v) # lets offer a last break to populate tags and such for v in _views: env = v.context(conf, env, data) # now teh real thing! for v in _views: for entry in chain(entrylist, pages, translations, drafts): entry.context = v for var in "entrylist", "pages", "translations", "drafts": data[var] = HashableList(filter(v.condition, locals()[var])) if v.condition else locals()[var] tt = time.time() for buf, path in v.generate(conf, env, data): try: helpers.mkfile( buf, path, time.time() - tt, ns=v.name, force=env.options.force, dryrun=env.options.dryrun ) except UnicodeError: log.exception(path) finally: buf.close() tt = time.time() # copy modified/missing assets to output assets.compile(conf, env) # wait for unfinished hooks hooks.shutdown() # save conf/environment hash and new/changed/unchanged references helpers.memoize("Configuration", hash(conf)) helpers.memoize("Environment", hash(env)) refs.save() # remove abandoned cache files cache.shutdown() # print a short summary log.info( "%i new, %i updated, %i skipped [%.2fs]", event.count("create"), event.count("update"), event.count("identical") + event.count("skip"), time.time() - ctime, )
def test_works(self): jinja2 = get_filters()['Jinja2'](conf, env, 'Jinja2') assert jinja2.transform('{{ entry.lang }}', Entry('de')) == 'de' assert jinja2.transform("{{ 'which which' | system }}", None) == '/usr/bin/which'
def compile(conf, env, force=False, **options): # time measurement ctime = time.time() # populate env and corrects some conf things request = initialize(conf, env) if force: # acrylamid compile -f cache.clear() # list of FileEntry-objects reverse sorted by date. entrylist = sorted([FileEntry(e, conf) for e in utils.filelist(conf['content_dir'], conf.get('entries_ignore', []))], key=lambda k: k.date, reverse=True) # here we store all possible filter configurations ns = set() # get available filter list, something like with obj.get-function # list = [<class head_offset.Headoffset at 0x1014882c0>, <class html.HTML at 0x101488328>,...] aflist = filters.get_filters() # ... and get all configured views _views = views.get_views() # filters found in all entries, views and conf.py found = sum((x.filters for x in entrylist+_views), []) + request['conf']['filters'] for val in found: # first we for `no` and get the function name and arguments f = val[2:] if val.startswith('no') else val fname, fargs = f.split('+')[:1][0], f.split('+')[1:] try: # initialize the filter with its function name and arguments fx = aflist[fname](val, *fargs) if val.startswith('no'): fx.transform = lambda x, y, *z: x fx.__hash__ = lambda : 0 except ValueError: try: fx = aflist[val.split('+')[:1][0]](val, *fargs) except ValueError: raise AcrylamidException('no such filter: %s' % val) ns.add(fx) for entry in entrylist: for v in _views: # a list that sorts out conflicting and duplicated filters flst = filters.FilterList() # filters found in this specific entry plus views and conf.py found = entry.filters + v.filters + request['conf']['filters'] for fn in found: fx = filter(lambda k: fn == k.name, ns)[0] if fx not in flst: flst.append(fx) # sort them ascending because we will pop within filters.add entry.filters.add(sorted(flst, key=lambda k: (-k.priority, k.name)), context=v.__class__.__name__) # lets offer a last break to populate tags or so # XXX this API component needs a review for v in _views: env = v.context(env, {'entrylist': filter(v.condition, entrylist)}) # now teh real thing! for v in _views: # XXX the entry should automatically determine its caller (using # some sys magic to recursively check wether the calling class is # derieved from `View`.) for entry in entrylist: entry.context = v.__class__.__name__ request['entrylist'] = filter(v.condition, entrylist) tt = time.time() for html, path in v.generate(request): helpers.mkfile(html, path, time.time()-tt, **options) tt = time.time() # remove abandoned cache files cache.shutdown() log.info('Blog compiled in %.2fs' % (time.time() - ctime))
def compile(conf, env): """The compilation process.""" if env.options.force: cache.clear(conf.get('cache_dir')) # time measurement ctime = time.time() # populate env and corrects some conf things data = initialize(conf, env) # load pages/entries and store them in env rv = dict(zip(['entrylist', 'pages', 'translations', 'drafts'], map(HashableList, readers.load(conf)))) entrylist, pages = rv['entrylist'], rv['pages'] translations, drafts = rv['translations'], rv['drafts'] # load references refs.load(entrylist, pages, translations, drafts) data.update(rv) env.globals.update(rv) # here we store all found filter and their aliases ns = defaultdict(set) # get available filter list, something like with obj.get-function # list = [<class head_offset.Headoffset at 0x1014882c0>, <class html.HTML at 0x101488328>,...] aflist = filters.get_filters() # ... and get all configured views _views = views.get_views() # filters found in all entries, views and conf.py (skip translations, has no items) found = sum((x.filters for x in chain(entrylist, pages, drafts, _views, [conf])), []) for val in found: # first we for `no` and get the function name and arguments f = val[2:] if val.startswith('no') else val fname, fargs = f.split('+')[:1][0], f.split('+')[1:] try: # initialize the filter with its function name and arguments fx = aflist[fname](conf, env, val, *fargs) if val.startswith('no'): fx = filters.disable(fx) except ValueError: try: fx = aflist[val.split('+')[:1][0]](conf, env, val, *fargs) except ValueError: raise AcrylamidException('no such filter: %s' % val) ns[fx].add(val) for entry in chain(entrylist, pages, drafts): for v in _views: # a list that sorts out conflicting and duplicated filters flst = filters.FilterList() # filters found in this specific entry plus views and conf.py found = entry.filters + v.filters + data['conf']['filters'] for fn in found: fx, _ = next((k for k in ns.iteritems() if fn in k[1])) if fx not in flst: flst.append(fx) # sort them ascending because we will pop within filters.add entry.filters.add(sorted(flst, key=lambda k: (-k.priority, k.name)), context=v) # lets offer a last break to populate tags and such for v in _views: env = v.context(conf, env, data) # now teh real thing! for v in _views: for entry in chain(entrylist, pages, translations, drafts): entry.context = v for var in 'entrylist', 'pages', 'translations', 'drafts': data[var] = HashableList(filter(v.condition, locals()[var])) \ if v.condition else locals()[var] tt = time.time() for buf, path in v.generate(conf, env, data): try: helpers.mkfile(buf, path, time.time()-tt, **env.options.__dict__) finally: buf.close() tt = time.time() # copy modified/missing assets to output assets.compile(conf, env) # save conf/environment hash and new/changed/unchanged references helpers.memoize('Configuration', hash(conf)) helpers.memoize('Environment', hash(env)) refs.save() # remove abandoned cache files cache.shutdown() # print a short summary log.info('%i new, %i updated, %i skipped [%.2fs]', event.count('create'), event.count('update'), event.count('identical') + event.count('skip'), time.time() - ctime)
def compile(conf, env, force=False, **options): """The compilation process. Current API: #. when we require context #. when we called an event New API: #. before we start with view Initialization #. after we initialized views #. before we require context #. after we required context #. before we template #. before we write a file #. when we called an event #. when we finish """ # time measurement ctime = time.time() # populate env and corrects some conf things request = initialize(conf, env) # load pages/entries and store them in env entrylist, pages = readers.load(conf) env.globals['entrylist'] = entrylist env.globals['pages'] = pages # XXX translations should be moved out of core env.globals['translations'] = translations = [] if force: # acrylamid compile -f cache.clear() # here we store all found filter and their aliases ns = defaultdict(set) # get available filter list, something like with obj.get-function # list = [<class head_offset.Headoffset at 0x1014882c0>, <class html.HTML at 0x101488328>,...] aflist = filters.get_filters() # ... and get all configured views _views = views.get_views() # filters found in all entries, views and conf.py found = sum( (x.filters for x in entrylist + pages + _views), []) + request['conf']['filters'] for val in found: # first we for `no` and get the function name and arguments f = val[2:] if val.startswith('no') else val fname, fargs = f.split('+')[:1][0], f.split('+')[1:] try: # initialize the filter with its function name and arguments fx = aflist[fname](conf, env, val, *fargs) if val.startswith('no'): fx = filters.disable(fx) except ValueError: try: fx = aflist[val.split('+')[:1][0]](conf, env, val, *fargs) except ValueError: raise AcrylamidException('no such filter: %s' % val) ns[fx].add(val) for entry in entrylist + pages: for v in _views: # a list that sorts out conflicting and duplicated filters flst = filters.FilterList() # filters found in this specific entry plus views and conf.py found = entry.filters + v.filters + request['conf']['filters'] for fn in found: fx, _ = next((k for k in ns.iteritems() if fn in k[1])) if fx not in flst: flst.append(fx) # sort them ascending because we will pop within filters.add entry.filters.add(sorted(flst, key=lambda k: (-k.priority, k.name)), context=v) # lets offer a last break to populate tags or so # XXX this API component needs a review for v in _views: env = v.context(env, { 'entrylist': entrylist, 'pages': pages, 'translations': translations }) # now teh real thing! for v in _views: # XXX the entry should automatically determine its caller (using # some sys magic to recursively check wether the calling class is # derieved from `View`.) for entry in entrylist + pages + translations: entry.context = v request['pages'], request['translations'] = pages, translations request['entrylist'] = filter(v.condition, entrylist) tt = time.time() for html, path in v.generate(request): helpers.mkfile(html, path, time.time() - tt, **options) tt = time.time() # remove abandoned cache files cache.shutdown() # print a short summary log.info('%i new, %i updated, %i skipped [%.2fs]', event.count('create'), event.count('update'), event.count('identical') + event.count('skip'), time.time() - ctime)