<s> from __future__ import absolute_import <EOL> from io import StringIO <EOL> from os . path import getmtime <EOL> from collections import defaultdict <EOL> from jinja2 import Environment as J2Environemnt , FileSystemBytecodeCache <EOL> from jinja2 import FileSystemLoader , meta , nodes <EOL> from acrylamid . templates import AbstractEnvironment , AbstractTemplate <EOL> try : <EOL> from acrylamid . assets . web import Mixin <EOL> except ImportError : <EOL> from acrylamid . assets . fallback import Mixin <EOL> def unast ( node ) : <EOL> if isinstance ( node , nodes . Const ) : <EOL> return node . value <EOL> elif isinstance ( node , nodes . List ) : <EOL> return [ unast ( item ) for item in node . items ] <EOL> raise NotImplementedError ( node ) <EOL> def find_assets ( ast ) : <EOL> """<STR_LIT>""" <EOL> for node in ast . find_all ( ( nodes . Call , ) ) : <EOL> if isinstance ( node . node , nodes . Name ) and node . node . name == '<STR_LIT>' : <EOL> yield [ x . value for x in node . args ] , dict ( ( x . key , unast ( x . value ) ) for x in node . kwargs ) <EOL> class ExtendedFileSystemLoader ( FileSystemLoader ) : <EOL> def __init__ ( self , layoutdirs ) : <EOL> self . modified = { '<STR_LIT>' : False } <EOL> self . resolved = defaultdict ( set ) <EOL> self . assets = defaultdict ( list ) <EOL> super ( ExtendedFileSystemLoader , self ) . __init__ ( layoutdirs ) <EOL> def load ( self , environment , name , globals = None ) : <EOL> bcc = environment . bytecode_cache <EOL> if globals is None : <EOL> globals = { } <EOL> deps = [ name , ] <EOL> while len ( deps ) > <NUM_LIT:0> : <EOL> child = deps . pop ( ) <EOL> if child in self . modified : <EOL> continue <EOL> source , filename , uptodate = self . get_source ( environment , child ) <EOL> bucket = bcc . get_bucket ( environment , child , filename , source ) <EOL> try : <EOL> modified = getmtime ( filename ) > getmtime ( bcc . _get_cache_filename ( bucket ) ) <EOL> except OSError : <EOL> modified = True <EOL> self . modified [ child ] = modified <EOL> if modified : <EOL> code = environment . compile ( source , child , filename ) <EOL> bucket . code = code <EOL> bcc . set_bucket ( bucket ) <EOL> ast = environment . parse ( source ) <EOL> for parent in meta . find_referenced_templates ( ast ) : <EOL> self . resolved [ child ] . add ( parent ) <EOL> deps . append ( parent ) <EOL> for args , kwargs in find_assets ( ast ) : <EOL> self . assets [ name ] . append ( ( args , kwargs ) ) <EOL> source , filename , uptodate = self . get_source ( environment , name ) <EOL> code = bcc . get_bucket ( environment , name , filename , source ) . code <EOL> if code is None : <EOL> code = environment . compile ( source , name , filename ) <EOL> tt = environment . template_class . from_code ( environment , code , <EOL> globals , uptodate ) <EOL> return tt <EOL> class Environment ( AbstractEnvironment ) : <EOL> extension = [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> loader = None <EOL> def __init__ ( self , layoutdir , cachedir ) : <EOL> self . templates = { } <EOL> self . loader = ExtendedFileSystemLoader ( layoutdir ) <EOL> self . _jinja2 = J2Environemnt ( <EOL> loader = self . loader , bytecode_cache = FileSystemBytecodeCache ( cachedir ) ) <EOL> import time , datetime , urllib <EOL> for module in ( time , datetime , urllib ) : <EOL> self . _jinja2 . globals [ module . __name__ ] = module <EOL> for name in dir ( module ) : <EOL> if name . startswith ( '<STR_LIT:_>' ) : <EOL> continue <EOL> obj = getattr ( module , name ) <EOL> if hasattr ( obj , '<STR_LIT>' ) and callable ( obj ) : <EOL> self . _jinja2 . filters [ module . __name__ + '<STR_LIT:.>' + name ] = obj <EOL> def register ( self , name , func ) : <EOL> self . _jinja2 . globals [ name ] = func <EOL> self . _jinja2 . filters [ name ] = func <EOL> def fromfile ( self , env , path ) : <EOL> return self . templates . setdefault ( path , <EOL> Template ( env , path , self . _jinja2 . get_template ( path ) ) ) <EOL> def extend ( self , path ) : <EOL> self . loader . searchpath . append ( path ) <EOL> class Template ( AbstractTemplate , Mixin ) : <EOL> def render ( self , ** kw ) : <EOL> buf = StringIO ( ) <EOL> self . template . stream ( ** kw ) . dump ( buf ) <EOL> return buf </s>
