def _get_combined_filename(self, files, force_generation=False, raise_=False): cached_file_path = self.cache.get(tuple(files)) if settings.DEBUG: # Always continue when DEBUG is enabled pass elif settings.FROM_CACHE and not settings.OFFLINE_GENERATION: if cached_file_path: return cached_file_path else: logging.error( 'Unable to generate cache because ' '`MINIFY_FROM_CACHE` is enabled was trying to compile %s', files) if raise_: raise FromCacheException( 'When FROM CACHE is enabled you cannot access the file system, was trying to compile %s' % files) digest = '' combined_files = [] language_specific = has_lang(files) # the filename will be max(timestamp for file_ in files: simple_fullpath = os.path.join(settings.MEDIA_ROOT, self.extension, 'original', file_) fullpaths = expand_on_lang(simple_fullpath) #expand to language specific versions, because if they changed we need to redirect for fullpath in fullpaths: digest += str(hash(open(fullpath).read())) #simple fullpath is the version with <lang> still in there combined_files.append(simple_fullpath) # hash can return negatives and break the debug js (var file_-6999668547187577964_debug = true; is not valid js) cached_file_path = os.path.join( self.cache_dir, '%d_debug_.%s' % (abs(hash(digest)), self.extension)) # ok if the expected output name is the one in cache then return it if settings.FROM_CACHE and force_generation and cached_file_path == self.cache.get( tuple(files)): self.cache[tuple(files)] = cached_file_path return cached_file_path if not os.path.isfile(cached_file_path) or force_generation: if not os.path.isdir(self.cache_dir): os.makedirs(self.cache_dir) cached_file_path = self._generate_combined_file( cached_file_path, combined_files) elif language_specific: cached_file_path = append_lang(cached_file_path) self.cache[tuple(files)] = cached_file_path return cached_file_path
def _get_combined_filename(self, files, force_generation=False, raise_=False): cached_file_path = self.cache.get(tuple(files)) if settings.DEBUG: # Always continue when DEBUG is enabled pass elif settings.FROM_CACHE and not settings.OFFLINE_GENERATION: if cached_file_path: return cached_file_path else: logging.error('Unable to generate cache because ' '`MINIFY_FROM_CACHE` is enabled was trying to compile %s', files) if raise_: raise FromCacheException('When FROM CACHE is enabled you cannot access the file system, was trying to compile %s' % files) digest = '' combined_files = [] language_specific = has_lang(files) # the filename will be max(timestamp for file_ in files: simple_fullpath = os.path.join(settings.MEDIA_ROOT, self.extension, 'original', file_) fullpaths = expand_on_lang(simple_fullpath) #expand to language specific versions, because if they changed we need to redirect for fullpath in fullpaths: digest += str(hash(open(fullpath).read())) #simple fullpath is the version with <lang> still in there combined_files.append(simple_fullpath) # hash can return negatives and break the debug js (var file_-6999668547187577964_debug = true; is not valid js) cached_file_path = os.path.join(self.cache_dir, '%d_debug_.%s' % (abs(hash(digest)), self.extension)) # ok if the expected output name is the one in cache then return it if settings.FROM_CACHE and force_generation and cached_file_path == self.cache.get(tuple(files)): self.cache[tuple(files)] = cached_file_path return cached_file_path if not os.path.isfile(cached_file_path) or force_generation: if not os.path.isdir(self.cache_dir): os.makedirs(self.cache_dir) cached_file_path = self._generate_combined_file(cached_file_path, combined_files) elif language_specific: cached_file_path = append_lang(cached_file_path) self.cache[tuple(files)] = cached_file_path return cached_file_path
def get_combined_filename(self, force_generation=False, raise_=False): cached_file_path = self.cache.get(tuple(self.files)) if settings.DEBUG: # Always continue when DEBUG is enabled pass elif settings.FROM_CACHE: if cached_file_path: return cached_file_path else: logging.error('Unable to generate cache because ' '`MINIFY_FROM_CACHE` is enabled was trying to compile %s', self.files) if raise_: raise FromCacheException('When FROM CACHE is enabled you cannot access the file system, was trying to compile %s' % self.files) timestamp = 0 digest = abs(hash(','.join(self.files))) files = [] language_specific = has_lang(self.files) # the filename will be max(timestamp for file_ in self.files: simple_fullpath = os.path.join(settings.MEDIA_ROOT, self.extension, 'original', file_) fullpaths = expand_on_lang(simple_fullpath) #expand to language specific versions, because if they changed we need to redirect for fullpath in fullpaths: stat = os.stat(fullpath) timestamp = max(timestamp, stat.st_mtime, stat.st_ctime) #simple fullpath is the version with <lang> still in there files.append(simple_fullpath) cached_file_path = os.path.join(self.cache_dir, '%d_debug_%d.%s' % (digest, timestamp, self.extension)) if not os.path.isfile(cached_file_path) or force_generation: if not os.path.isdir(self.cache_dir): os.makedirs(self.cache_dir) cached_file_path = self._generate_combined_file(cached_file_path, files) elif language_specific: cached_file_path = append_lang(cached_file_path) self.cache[tuple(self.files)] = cached_file_path return cached_file_path
def _generate_combined_file(self, filename, files): ''' Generate the combined file If there is a <lang> param used we support is by generating multiple versions And returning a combined filename with <lang> in it filename = the file we are writing to files = the list of files we are compiling Generates a stripped version of each file. Expanding language_specific files where needed Subsequently gets a combined file per locale Finally it writes a file per locale with this output ''' name = os.path.splitext(os.path.split(filename)[1])[0] language_specific = has_lang(files) #combined output per locale combined_per_locale = dict() #store the stripped file per path stripped_files_dict = dict() #loop through all files and combine them, expand if there is a <lang> for file_path in files: localized_paths = expand_on_lang(file_path) for localized_path in localized_paths: read_fh = open(localized_path) # Add the spaceless version to the output if SpacelessMiddleware: data = SpacelessMiddleware.strip_content_safe( read_fh.read()) else: data = read_fh.read() stripped_files_dict[localized_path] = data read_fh.close() #generate the combined file for each locale locales = get_languages_list(language_specific) for locale in locales: #get the language_specific versions of the files and combine them combined_output = '' for file_path in files: file_path = replace_lang(file_path, locale) content = stripped_files_dict[file_path] combined_output += content combined_output += '\n' #postfix some debug info to ensure we can check for the file's validity if self.extension == 'js': js = 'var file_%s = true;\n' % name combined_output += js js = 'var file_%s = true;\n' % name.replace('debug', 'mini') combined_output += js elif self.extension == 'css': css = '#file_%s{color: #FF00CC;}\n' % name combined_output += css css = '#file_%s{color: #FF00CC;}\n' % name.replace( 'debug', 'mini') combined_output += css else: raise TypeError('Extension %r is not supported' % self.extension) combined_per_locale[locale] = combined_output #write the combined version per locale to temporary files and then move them #to their locale specific file for locale in locales: combined_output = combined_per_locale[locale] postfix = '%s.tmp' % locale temp_file_path = filename + postfix path, ext = os.path.splitext(filename) final_file_path = filename.replace( ext, '%s%s' % (locale, ext)) if locale else filename #be atomic! with portalocker.Lock(temp_file_path, timeout=MAX_WAIT) as fh: fh.write(combined_output) if os.path.isfile(final_file_path): os.remove(final_file_path) os.rename(filename + postfix, final_file_path) if language_specific: filename = append_lang(filename) return filename
def _generate_combined_file(self, filename, files): ''' Generate the combined file If there is a <lang> param used we support is by generating multiple versions And returning a combined filename with <lang> in it filename = the file we are writing to files = the list of files we are compiling Generates a stripped version of each file. Expanding language_specific files where needed Subsequently gets a combined file per locale Finally it writes a file per locale with this output ''' name = os.path.splitext(os.path.split(filename)[1])[0] language_specific = has_lang(files) #combined output per locale combined_per_locale = dict() #store the stripped file per path stripped_files_dict = dict() #loop through all files and combine them, expand if there is a <lang> for file_path in files: localized_paths = expand_on_lang(file_path) for localized_path in localized_paths: read_fh = open(localized_path) # Add the spaceless version to the output if SpacelessMiddleware: data = SpacelessMiddleware.strip_content_safe(read_fh.read()) else: data = read_fh.read() stripped_files_dict[localized_path] = data read_fh.close() #generate the combined file for each locale locales = get_languages_list(language_specific) for locale in locales: #get the language_specific versions of the files and combine them combined_output = '' for file_path in files: file_path = replace_lang(file_path, locale) content = stripped_files_dict[file_path] combined_output += content combined_output += '\n' #postfix some debug info to ensure we can check for the file's validity if self.extension == 'js': js = 'var file_%s = true;\n' % name combined_output += js js = 'var file_%s = true;\n' % name.replace('debug', 'mini') combined_output += js elif self.extension == 'css': css = '#file_%s{color: #FF00CC;}\n' % name combined_output += css css = '#file_%s{color: #FF00CC;}\n' % name.replace('debug', 'mini') combined_output += css else: raise TypeError('Extension %r is not supported' % self.extension) combined_per_locale[locale] = combined_output #write the combined version per locale to temporary files and then move them #to their locale specific file for locale in locales: combined_output = combined_per_locale[locale] postfix = '%s.tmp' % locale temp_file_path = filename + postfix path, ext = os.path.splitext(filename) final_file_path = filename.replace(ext, '%s%s' % (locale, ext)) if locale else filename #be atomic! with portalocker.Lock(temp_file_path, timeout=MAX_WAIT) as fh: fh.write(combined_output) if os.path.isfile(final_file_path): os.remove(final_file_path) os.rename(filename + postfix, final_file_path) if language_specific: filename = append_lang(filename) return filename