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)), )
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"")
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'
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
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)
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'
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)
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'