示例#1
0
    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()
示例#2
0
    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()
示例#3
0
 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)
示例#4
0
    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)
示例#5
0
    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)
示例#6
0
    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)
示例#7
0
    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
示例#8
0
    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'
示例#9
0
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