예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
 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
예제 #4
0
    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
예제 #5
0
    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