def setup(self): TempEnvironmentHelper.setup(self) # Test the timestamp updater with cache disabled, so that the # BundleDefUpdater() base class won't interfere. self.env.cache = False self.env.updater = self.updater = TimestampUpdater()
def setup(self): TempEnvironmentHelper.setup(self) class MyCache(BaseCache): def __init__(self): self.enabled = False self.reset() def get(self, key): self.getops += 1 if self.enabled: return u'foo' return False def set(self, key, data): self.setops += 1 def reset(self): self.getops = 0 self.setops = 0 class CompleteFilter(Filter): # Support all possible filter operations def input(self, *a, **kw): pass output = open = concat = input self.filter = CompleteFilter self.env.cache = self.cache = MyCache() self.env.manifest = None # Note that updater will use the cache also self.env.updater = TimestampUpdater()
def test_autorebuild_updaters(self): # Make sure the timestamp updater can deal with bundles that # contain urls. We need to make sure the output file already # exists to test this or the updater may simply decide not to # run at all. self.create_files({'out': 'foo'}) bundle = self.mkbundle('http://foo', output='out') TimestampUpdater().needs_rebuild(bundle, bundle.env)
def check(self): """Check to see if assets need to be rebuilt. A non-zero exit status will be returned if any of the input files are newer (based on mtime) than their output file. This is intended to be used in pre-commit hooks. """ needsupdate = False updater = self.environment.updater if not updater: self.log.debug('no updater configured, using TimestampUpdater') updater = TimestampUpdater() for bundle in self.environment: self.log.info('Checking asset: %s', bundle.output) if updater.needs_rebuild(bundle, self.environment): self.log.info(' needs update') needsupdate = True if needsupdate: sys.exit(-1)
def test_filesystem_cache(self): """Regresssion test for two bugs: One where the FilesystemCache class was called with an unhashable key (which is not allowed), the second where the updater tried to cache a non-string value. Both in the process of a standard build. """ bundle = self.mkbundle('in1', 'in2', output='out', filters="rjsmin") self.env.cache = True # use the filesystem cache self.env.updater = TimestampUpdater() bundle.build(force=True)
def test_dependency_refresh(self): """This tests a specific behavior of bundle dependencies. If they are specified via glob, then that glob is cached and only refreshed after a build. The thinking is that in those cases for which the depends option was designed, if for example a new SASS include file is created, for this file to be included, one of the existing files first needs to be modified to actually add the include command. """ updater = self.env.updater = TimestampUpdater() self.env.cache = False self.create_files({'first.sass': 'one'}) b = self.mkbundle('in1', output='out', depends='*.sass') b.build() now = self.setmtime('in1', 'first.sass', 'out') # At this point, no rebuild is required assert updater.needs_rebuild(b, self.env) == False # Create a new file that matches the dependency; # make sure it is newer. self.create_files({'second.sass': 'two'}) self.setmtime('second.sass', mtime=now + 100) # Still no rebuild required though assert updater.needs_rebuild(b, self.env) == False # Touch one of the existing files self.setmtime('first.sass', mtime=now + 200) # Do the rebuild that is now required # TODO: first.sass is a dependency, because the glob matches # the bundle contents as well; As a result, we might check # its timestamp twice. Should something be done about it? assert updater.needs_rebuild(b, self.env) == SKIP_CACHE b.build() self.setmtime('out', mtime=now + 200) # Now, touch the new dependency we created - a # rebuild is now required. self.setmtime('second.sass', mtime=now + 300) assert updater.needs_rebuild(b, self.env) == SKIP_CACHE
def _dependency_refresh_with_cache(self, rebuild_with_force): # We have to repeat these a lot DEPENDENCY = 'dependency.sass' DEPENDENCY_SUB = 'dependency_sub.sass' # Init a environment with a cache self.env.updater = TimestampUpdater() self.env.cache = MemoryCache(100) self.create_files({ DEPENDENCY: '-main', DEPENDENCY_SUB: '-sub', 'in': '', 'in_sub': '' }) # Create a bundle with a dependency, and a filter which # will cause the dependency content to be written. If # everything works as it should, a change in the # dependency should thus cause the output to change. bundle = self.mkbundle('in', output='out', depends=(DEPENDENCY, ), filters=lambda in_, out: out.write(in_.read( ) + self.get(DEPENDENCY))) # Additionally, to test how the cache usage of the parent # bundle affects child bundles, create a child bundle. # This one also writes the final content based on a dependency, # but one that is undeclared, so to not override the parent # cache behavior, the passing down of which we intend to test. # # This is a constructed setup so we can test whether the child # bundle was using the cache by looking at the output, not # something that makes sense in real usage. bundle.contents += (self.mkbundle( 'in_sub', filters=lambda in_, out: out.write(self.get(DEPENDENCY_SUB))), ) # Do an initial build to ensure we have the build steps in # the cache. bundle.build() assert self.get('out') == '\n-sub-main' assert self.env.cache.keys # Change the dependencies self.create_files({DEPENDENCY: '-main12345'}) self.create_files({DEPENDENCY_SUB: '-subABCDE'}) # Ensure the timestamps are such that dependency will # cause the rebuild. now = self.setmtime('out') self.setmtime('in', 'in_sub', mtime=now - 100) self.setmtime(DEPENDENCY, DEPENDENCY_SUB, mtime=now + 100) # Build again, verify result bundle.build(force=rebuild_with_force) # The main bundle has always updated (i.e. the cache # was invalidated/not used). # # The child bundle is still using the cache if force=True is # used, but will inherit the 'skip the cache' flag from the # parent when force=False. # There is no reason for this, it's just the way the code # currently works, and liable to change in the future. if rebuild_with_force: assert self.get('out') == '\n-sub-main12345' else: assert self.get('out') == '\n-subABCDE-main12345'
def init_app(app): assets_env.app = app assets_env.init_app(app) assets_env.manifest = "file:%s" % (os.path.join(STATIC_PATH, '.webassets-manifest')) cache_path = app.config['WEBASSETS_CACHE_PATH'] if not app.debug and not os.path.exists(cache_path): os.makedirs(cache_path) assets_env.cache = cache_path assets_env.load_path = STATIC_PATH assets_env.versions = 'hash:32' assets_env.auto_build = app.config['WEBASSETS_AUTO_BUILD'] assets_env.url_expire = False # Tell flask-assets where to look for our coffeescript and scss files. assets_env.load_path = [ os.path.join(os.path.dirname(__file__), 'scss'), os.path.join(os.path.dirname(__file__), 'coffee'), VENDOR_PATH ] bower_dependencies = read_bower_json() js_files = bower_dependencies.get('.js', []) js_out = 'js/js_app.%(version)s.js' if app.debug: js_out = 'js/js_app.js' coffee_files = get_coffee_files(app) if coffee_files: js_files.append( assets.Bundle( coffee_files, depends=('*.coffee'), # OTHER CONFIGS filters=['coffeescript'], output=js_out)) app.config['COMPASS_CONFIG'] = dict( encoding="utf-8", css_dir="css", fonts_dir="fonts", sass_dir="scss", images_dir="images", javascripts_dir="js", project_path=STATIC_PATH, relative_assets=True, ) js_out = 'js/js_all.%(version)s.js' if app.debug: js_out = 'js/js_all.js' if js_files: js_all_bundle = assets.Bundle(*js_files, output=js_out) else: js_all_bundle = assets.Bundle() assets_env.register('js_all', js_all_bundle) scss_files = bower_dependencies.get('.scss', []) scss_bower_out = 'css/css_bower.%(version)s.css' if app.debug: scss_bower_out = 'css/css_bower.css' scss_bower_bundle = assets.Bundle(*scss_files, depends=('_*.scss'), filters=['compass'], output=scss_bower_out) css_out = 'css/css_all.%(version)s.css' if app.debug: css_out = 'css/css_all.css' css_all_bundle = assets.Bundle('all.scss', depends=('_*.scss'), filters=['compass'], output=css_out) css_out = 'css/base.%(version)s.css' if app.debug: css_out = 'css/base.css' css_files = bower_dependencies.get('.css', []) css_base_bundle = assets.Bundle(*css_files, filters=['cssmin'], output=css_out) css_out = 'css/style.%(version)s.css' if app.debug: css_out = 'css/style.css' css_all_bundle = assets.Bundle(scss_bower_bundle, css_base_bundle, css_all_bundle, filters=['cssmin'], output=css_out) assets_env.register('css_all', css_all_bundle) if app.debug: assets_env.set_updater(TimestampUpdater()) assets_env.cache = False assets_env.auto_build = True assets_env.debug = True