Esempio n. 1
0
    def _merge_and_apply(
        self,
        ctx,
        output,
        force,
        parent_debug=None,
        parent_filters=None,
        extra_filters=None,
        disable_cache=None,
    ):
        hunk = Bundle._merge_and_apply(
            self,
            ctx,
            output,
            force,
            parent_debug=parent_debug,
            parent_filters=parent_filters,
            extra_filters=extra_filters,
            disable_cache=disable_cache,
        )

        return ChainedHunk(
            MemoryHunk(_PLUGIN_BUNDLE_WRAPPER_PREFIX.format(plugin=self.plugin)),
            (hunk, lambda x: x.replace("\n", "\n        ")),
            MemoryHunk(_PLUGIN_BUNDLE_WRAPPER_SUFFIX.format(plugin=self.plugin)),
        )
Esempio n. 2
0
    def fixed_wrap_cache(self, key, func):
        """Return cache value ``key``, or run ``func``.
		"""
        if self.cache:
            if not self.no_cache_read:
                log.debug('Checking cache for key %s', key)
                content = self.cache.get(key)
                if not content in (False, None):
                    log.debug('Using cached result for %s', key)
                    return MemoryHunk(content)

        try:
            content = func().getvalue()
            if self.cache:
                try:
                    log.debug(
                        'Storing result in cache with key %s',
                        key,
                    )
                    self.cache.set(key, content)
                except:
                    error_logger.exception(
                        "Got an exception while trying to save file to cache, not caching"
                    )
            return MemoryHunk(content)
        except:
            error_logger.exception(
                "Got an exception while trying to apply filter, ignoring file")
            return MemoryHunk(u"")
Esempio n. 3
0
 def _test_hunks(self, c):
     """Test hunks as keys."""
     key = (MemoryHunk('bla'), 42)
     assert c.get(key) is None
     c.set(key, 'foo')
     assert c.get(key) == 'foo'
     assert c.get((MemoryHunk('bla'), 42)) == 'foo'
Esempio n. 4
0
    def test_write_memory_hunk(self):
        outfile = self.path('out')
        h = MemoryHunk(self.BINARY_DATA)
        h.save(outfile)

        with open(outfile, 'rb') as f:
            d = f.read()

        assert isinstance(d, str)
        assert d == self.BINARY_DATA
Esempio n. 5
0
 def test_with_hunk(self):
     # If a hunk indicates call during a build, the output file is ignored,
     # and the versioner looks at the source files.
     self.create_files([self.bundle.output])
     self.setmtime(self.bundle.output, mtime=self.source_max+100)
     hunk = MemoryHunk('foo')
     assert self.v.determine_version(
         self.bundle, self.env, hunk) == int(self.source_max)
Esempio n. 6
0
 def test_options(self):
     """Test customization options."""
     hunk = MemoryHunk('foo')
     assert HashVersion(length=None).determine_version(
         self.bundle, self.env, hunk) == 'acbd18db4cc2f85cedef654fccc4a4d8'
     assert HashVersion(length=2).determine_version(
         self.bundle, self.env, hunk) == 'ac'
     assert HashVersion(hash=hashlib.sha256).determine_version(
         self.bundle, self.env, hunk) == '2c26b46b'
Esempio n. 7
0
    def build(self,
              bundles=None,
              output=None,
              directory=None,
              no_cache=None,
              manifest=None):
        """Build/Rebuild assets.

        ``bundles``
            A list of bundle names. If given, only this list of bundles
            should be built.

        ``output``
            List of (bundle, filename) 2-tuples. If given, only these
            bundles will be built, using the custom output filenames.
            Cannot be used with ``bundles``.

        ``directory``
            Custom output directory to use for the bundles. The original
            basenames defined in the bundle ``output`` attribute will be
            used. If the ``output`` of the bundles are pointing to different
            directories, they will be offset by their common prefix.
            Cannot be used with ``output``.

        ``no_cache``
            If set, a cache (if one is configured) will not be used.

        ``manifest``
            If set, the given manifest instance will be used, instead of
            any that might have been configured in the Environment. The value
            passed will be resolved through ``get_manifest()``. If this fails,
            a file-based manifest will be used using the given value as the
            filename.
        """
        if self.environment.debug != False:
            self.log.warning(
                ("Current debug option is '%s'. Building as "
                 "if in production (debug=False)") % self.environment.debug)
            self.environment.debug = False

        # Validate arguments
        if bundles and output:
            raise CommandError(
                'When specifying explicit output filenames you must '
                'do so for all bundles you want to build.')
        if directory and output:
            raise CommandError('A custom output directory cannot be '
                               'combined with explicit output filenames '
                               'for individual bundles.')

        # TODO: Oh how nice it would be to use the future options stack.
        if manifest is not None:
            try:
                manifest = get_manifest(manifest, env=self.environment)
            except ValueError:
                manifest = get_manifest(
                    # abspath() is important, or this will be considered
                    # relative to Environment.directory.
                    "file:%s" % os.path.abspath(manifest),
                    env=self.environment)
            self.environment.manifest = manifest

        # Use output as a dict.
        if output:
            output = dict(output)

        # Validate bundle names
        bundle_names = bundles if bundles else (
            output.keys() if output else [])
        for name in bundle_names:
            if not name in self.environment:
                raise CommandError('I do not know a bundle name named "%s".' %
                                   name)

        # Make a list of bundles to build, and the filename to write to.
        if bundle_names:
            # TODO: It's not ok to use an internal property here.
            bundles = [(n, b)
                       for n, b in self.environment._named_bundles.items()
                       if n in bundle_names]
        else:
            # Includes unnamed bundles as well.
            bundles = [(None, b) for b in self.environment]

        # Determine common prefix for use with ``directory`` option.
        if directory:
            prefix = os.path.commonprefix([
                os.path.normpath(self.environment.abspath(b.output))
                for _, b in bundles if b.output
            ])
            # dirname() gives the right value for a single file.
            prefix = os.path.dirname(prefix)

        to_build = []
        for name, bundle in bundles:
            # TODO: We really should support this. This error here
            # is just in place of a less understandable error that would
            # otherwise occur.
            if bundle.is_container and directory:
                raise CommandError(
                    'A custom output directory cannot currently be '
                    'used with container bundles.')

            # Determine which filename to use, if not the default.
            overwrite_filename = None
            if output:
                overwrite_filename = output[name]
            elif directory:
                offset = os.path.normpath(
                    self.environment.abspath(bundle.output))[len(prefix) + 1:]
                overwrite_filename = os.path.join(directory, offset)
            to_build.append((
                bundle,
                overwrite_filename,
                name,
            ))

        # Build.
        built = []
        for bundle, overwrite_filename, name in to_build:
            if name:
                # A name is not necessary available of the bundle was
                # registered without one.
                self.log.info("Building bundle: %s (to %s)" %
                              (name, overwrite_filename or bundle.output))
            else:
                self.log.info("Building bundle: %s" % bundle.output)

            try:
                if not overwrite_filename:
                    bundle.build(force=True,
                                 env=self.environment,
                                 disable_cache=no_cache)
                else:
                    # TODO: Rethink how we deal with container bundles here.
                    # As it currently stands, we write all child bundles
                    # to the target output, merged (which is also why we
                    # create and force writing to a StringIO instead of just
                    # using the ``Hunk`` objects that build() would return
                    # anyway.
                    output = StringIO()
                    bundle.build(force=True,
                                 env=self.environment,
                                 output=output,
                                 disable_cache=no_cache)
                    if directory:
                        # Only auto-create directories in this mode.
                        output_dir = os.path.dirname(overwrite_filename)
                        if not os.path.exists(output_dir):
                            os.makedirs(output_dir)
                    MemoryHunk(output.getvalue()).save(overwrite_filename)
                built.append(bundle)
            except BuildError, e:
                self.log.error("Failed, error was: %s" % e)
Esempio n. 8
0
 def test_with_hunk(self):
     # If a hunk is given, the has will be based on it, not the output file
     self.create_files({self.bundle.output: 'bar'})
     hunk = MemoryHunk('foo')
     assert self.v.determine_version(
         self.bundle, self.env, hunk) == 'acbd18db'